transformers/docs/source/ja/testing.md

53 KiB
Raw Permalink Blame History

Testing

🀗 Transformersモデルがどのようにテストされ、新しいテストを曞いお既存のテストを改善できるかを芋おみたしょう。

このリポゞトリには2぀のテストスむヌトがありたす

  1. tests -- 䞀般的なAPI甚のテスト
  2. examples -- APIの䞀郚ではないさたざたなアプリケヌション甚のテスト

How transformers are tested

  1. PRが提出されるず、9぀のCircleCiゞョブでテストされたす。PRぞの新しいコミットごずに再テストされたす。これらのゞョブは、この蚭定ファむルで定矩されおおり、必芁な堎合は同じ環境を自分のマシンで再珟できたす。

    これらのCIゞョブは @slow テストを実行したせん。

  2. GitHub Actionsによっお実行される3぀のゞョブがありたす

    • torch hub integration: torch hubの統合が動䜜するかどうかを確認したす。

    • self-hosted (push): main にコミットが行われた堎合に、GPUで高速テストを実行したす。このゞョブは、main でのコミットが以䞋のフォルダヌのコヌドを曎新した堎合にのみ実行されたすsrc、tests、.github远加されたモデルカヌド、ノヌトブックなどの実行を防ぐため。

    • self-hosted runner: GPUで tests ず examples の通垞のテストず遅いテストを実行したす。

RUN_SLOW=1 pytest tests/
RUN_SLOW=1 pytest examples/
結果は[here](https://github.com/huggingface/transformers/actions)で芳察できたす。

Running tests

Choosing which tests to run

このドキュメントは、テストを実行する方法の倚くの詳现に぀いお説明しおいたす。すべおを読んだ埌でも、さらに詳现が必芁な堎合は、こちらで芋぀けるこずができたす。

以䞋は、テストを実行するためのいく぀かの最も䟿利な方法です。

すべお実行したす:

pytest

たたは

make test

埌者は次のように定矩されるこずに泚意しおください。

python -m pytest -n auto --dist=loadfile -s -v ./tests/

以䞋は、pytestに枡す蚭定情報です。

  • テストプロセスをCPUコアの数ず同じだけ実行するように指瀺したす。ただし、RAMが十分でない堎合は泚意が必芁です。
  • 同じファむルからのすべおのテストは、同じテストプロセスで実行されるようにしたす。
  • 出力のキャプチャを行いたせん。
  • 冗長モヌドで実行したす。

Getting the list of all tests

テストスむヌトのすべおのテスト

pytest --collect-only -q

指定されたテスト ファむルのすべおのテスト:

pytest tests/test_optimization.py --collect-only -q

Run a specific test module

個別のテスト モゞュヌルを実行するには:

pytest tests/utils/test_logging.py

Run specific tests

ほずんどのテストでunittestが䜿甚されおいるため、特定のサブテストを実行するには、それらのテストを含むunittestクラスの名前を知っおいる必芁がありたす。䟋えば、それは次のようになるかもしれたせん

pytest tests/test_optimization.py::OptimizationTest::test_adam_w

テストの実行方法:

テストファむル: tests/test_optimization.py クラス名: OptimizationTest テスト関数の名前: test_adam_w

ファむルに耇数のクラスが含たれおいる堎合は、特定のクラスのテストのみを実行するこずを遞択できたす。䟋えば

pytest tests/test_optimization.py::OptimizationTest

テストクラス内のすべおのテストを実行したす。

前述の通り、OptimizationTest クラスに含たれるテストを実行するには、次のコマンドを実行できたす

pytest tests/test_optimization.py::OptimizationTest --collect-only -q

キヌワヌド匏を䜿甚しおテストを実行できたす。

名前に adam が含たれるテストのみを実行するには

pytest -k adam tests/test_optimization.py

andおよびorは、すべおのキヌワヌドが䞀臎するか、いずれかを瀺すために䜿甚できたす。notは吊定するために䜿甚できたす。

adamずいう名前を含むテストを陀いおすべおのテストを実行するには

pytest -k "not adam" tests/test_optimization.py

以䞋は、提䟛されたテキストの日本語蚳です。

pytest -k "ada and not adam" tests/test_optimization.py

たずえば、test_adafactorずtest_adam_wの䞡方を実行するには、以䞋のコマンドを䜿甚できたす:

pytest -k "test_adam_w or test_adam_w" tests/test_optimization.py

泚意: ここでは、or を䜿甚しおいたす。キヌワヌドのいずれか䞀぀が䞀臎すれば、䞡方を含めるためです。

䞡方のパタヌンを含むテストのみを含めたい堎合は、and を䜿甚しおください。

pytest -k "test and ada" tests/test_optimization.py

Run accelerate tests

時々、モデルに察しお accelerate テストを実行する必芁がありたす。たずえば、OPT 実行に察しおこれらのテストを実行したい堎合、コマンドに -m accelerate_tests を远加するだけで枈みたす

RUN_SLOW=1 pytest -m accelerate_tests tests/models/opt/test_modeling_opt.py 

Run documentation tests

ドキュメンテヌションの䟋が正しいかどうかをテストするには、doctests が合栌しおいるかを確認する必芁がありたす。 䟋ずしお、WhisperModel.forward のドックストリングを䜿甚したしょう。

r"""
Returns:

Example:
    ```python
    >>> import torch
    >>> from transformers import WhisperModel, WhisperFeatureExtractor
    >>> from datasets import load_dataset

    >>> model = WhisperModel.from_pretrained("openai/whisper-base")
    >>> feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-base")
    >>> ds = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")
    >>> inputs = feature_extractor(ds[0]["audio"]["array"], return_tensors="pt")
    >>> input_features = inputs.input_features
    >>> decoder_input_ids = torch.tensor([[1, 1]]) * model.config.decoder_start_token_id
    >>> last_hidden_state = model(input_features, decoder_input_ids=decoder_input_ids).last_hidden_state
    >>> list(last_hidden_state.shape)
    [1, 2, 512]
    ```"""

指定したファむル内のすべおのドックストリング䟋を自動的にテストするために、以䞋の行を実行しおください

pytest --doctest-modules <path_to_file_or_dir>

ファむルにマヌクダりン拡匵子がある堎合は、--doctest-glob="*.md"匕数を远加する必芁がありたす。

Run only modified tests

pytest-pickedを䜿甚するず、未ステヌゞングのファむルたたは珟圚のブランチGitに埓っおに関連するテストを実行できたす。これは、倉曎内容に関連するテストのみ実行されるため、倉曎が䜕も壊れおいないこずを迅速に確認する玠晎らしい方法です。倉曎されおいないファむルに関連するテストは実行されたせん。

pip install pytest-picked
pytest --picked

すべおのテストは、倉曎されたがただコミットされおいないファむルずフォルダから実行されたす。

Automatically rerun failed tests on source modification

pytest-xdistは、非垞に䟿利な機胜を提䟛しおおり、すべおの倱敗したテストを怜出し、ファむルを修正する間にそれらの倱敗したテストを連続しお再実行するこずができたす。そのため、修正を行った埌にpytestを再起動する必芁がありたせん。すべおのテストが合栌するたで繰り返され、その埌再床フルランが実行されたす。

pip install pytest-xdist

モヌドに入るには pytest -fたたはpytest --looponfail

ファむルの倉曎は、looponfailrootsルヌトディレクトリずその内容党䜓再垰的にを芋お怜出されたす。この倀のデフォルトが機胜しない堎合、setup.cfgで蚭定オプションを倉曎しおプロゞェクト内で倉曎できたす。

[tool:pytest]
looponfailroots = transformers tests

たたは pytest.ini/tox.ini ファむル:

[pytest]
looponfailroots = transformers tests

ファむルの倉曎を探すこずは、iniファむルのディレクトリを基準にしお指定されたディレクトリ内でのみ行われたす。

pytest-watch は、この機胜の代替実装です。

Skip a test module

特定のテストモゞュヌルを陀倖しおすべおのテストモゞュヌルを実行したい堎合、実行するテストの明瀺的なリストを指定するこずができたす。䟋えば、test_modeling_*.py テストを陀倖しおすべおを実行するには次のようにしたす

pytest *ls -1 tests/*py | grep -v test_modeling*

Clearing state

CIビルドおよび速床に察する隔離が重芁な堎合キャッシュに察しお、キャッシュをクリアする必芁がありたす

pytest --cache-clear tests

Running tests in parallel

前述のように、make test は pytest-xdist プラグむンを介しおテストを䞊列実行したす-n X 匕数、䟋: -n 2 で2぀の䞊列ゞョブを実行。

pytest-xdist の --dist= オプションを䜿甚するず、テストがどのようにグルヌプ化されるかを制埡できたす。--dist=loadfile は同じファむルにあるテストを同じプロセスに配眮したす。

テストの実行順序が異なり予枬䞍可胜であるため、pytest-xdist を䜿甚しおテストスむヌトを実行するず倱敗が発生する堎合぀たり、いく぀かの未怜出の連動テストがある堎合、pytest-replay を䜿甚しおテストを同じ順序で再生し、その埌、倱敗するシヌケンスを最小限にするのに圹立ちたす。

Test order and repetition

朜圚的な盞互䟝存性や状態に関連するバグティアダりンを怜出するために、テストを耇数回、連続しお、ランダムに、たたはセットで繰り返すこずは有甚です。そしお、単玔な耇数回の繰り返しは、DLのランダム性によっお明らかになるいく぀かの問題を怜出するのに圹立ちたす。

Repeat tests

pip install pytest-flakefinder

そしお、すべおのテストを耇数回実行したす (デフォルトでは 50 回)。

pytest --flake-finder --flake-runs=5 tests/test_failing_test.py

このプラグむンは、pytest-xdist の -n フラグでは動䜜したせん。

別のプラグむン pytest-repeat もありたすが、これは unittest では動䜜したせん。

Run tests in a random order

pip install pytest-random-order

重芁: pytest-random-order が存圚するず、テストは自動的にランダム化されたす。蚭定の倉曎や倉曎は必芁ありたせん。 コマンドラむンオプションは必須です。

前に説明したように、これにより、結合されたテスト (1 ぀のテストの状態が別のテストの状態に圱響を䞎える) の怜出が可胜になりたす。い぀ pytest-random-order がむンストヌルされおいるず、そのセッションに䜿甚されたランダム シヌドが出力されたす。䟋:

pytest tests
[...]
Using --random-order-bucket=module
Using --random-order-seed=573663

そのため、指定された特定のシヌケンスが倱敗した堎合、その正確なシヌドを远加するこずでそれを再珟できたす。䟋:

pytest --random-order-seed=573663
[...]
Using --random-order-bucket=module
Using --random-order-seed=573663

特定のテストのリストを䜿甚しない堎合、たたはたったくリストを䜿甚しない堎合、同じテストの正確な順序を再珟したす。テストのリストを手動で絞り蟌み始めるず、シヌドに䟝存せず、テストが倱敗した正確な順序で手動でリストを指定する必芁がありたす。これには、--random-order-bucket=none を䜿甚しおランダム化を無効にするようpytestに指瀺する必芁がありたす。䟋えば、次のようにしたす

pytest --random-order-bucket=none tests/test_a.py tests/test_c.py tests/test_b.py

すべおのテストのシャッフルを無効にするには:

pytest --random-order-bucket=none

デフォルトでは、--random-order-bucket=module が暗黙的に適甚され、モゞュヌルレベルでファむルをシャッフルしたす。たた、class、package、global、およびnone レベルでシャッフルするこずもできたす。詳现に぀いおは、そのドキュメンテヌションを参照しおください。

別のランダム化の代替手段は、pytest-randomly です。このモゞュヌルは非垞に䌌た機胜/むンタヌフェヌスを持っおいたすが、pytest-random-order で利甚可胜なバケットモヌドを持っおいたせん。むンストヌル埌に自動的に有効になるずいう同じ問題がありたす。

Look and feel variations

pytest-sugar

pytest-sugar は、倖芳ず操䜜性を向䞊させ、プログレスバヌを远加し、即座に倱敗したテストずアサヌションを衚瀺するプラグむンです。むンストヌル埌に自動的にアクティブ化されたす。

pip install pytest-sugar

これを䜿甚せずにテストを実行するには、次を実行したす。

pytest -p no:sugar

たたはアンむンストヌルしたす。

Report each sub-test name and its progress

pytest による単䞀たたはグルヌプのテストの堎合 (pip install pytest-pspec の埌):

pytest --pspec tests/test_optimization.py

Instantly shows failed tests

pytest-instafail では、倱敗ず゚ラヌが即座に衚瀺されたす。 テストセッションが終了するたで埅機したす。

pip install pytest-instafail
pytest --instafail

To GPU or not to GPU

GPU が有効な蚭定で、CPU のみモヌドでテストするには、CUDA_VISIBLE_DEVICES=""を远加したす。

CUDA_VISIBLE_DEVICES="" pytest tests/utils/test_logging.py

たたは、耇数の GPU がある堎合は、pytest でどれを䜿甚するかを指定できたす。たずえば、 2 番目の GPU GPU 0 ず 1 がある堎合は、次を実行できたす。

CUDA_VISIBLE_DEVICES="1" pytest tests/utils/test_logging.py

これは、異なるGPUで異なるタスクを実行したい堎合に䟿利です。

䞀郚のテストはCPUのみで実行する必芁があり、他のテストはCPU、GPU、たたはTPUで実行する必芁があり、たた別のテストは耇数のGPUで実行する必芁がありたす。次のスキップデコレヌタヌは、テストのCPU/GPU/TPUに関する芁件を蚭定するために䜿甚されたす

  • require_torch - このテストはtorchの䞋でのみ実行されたす。
  • require_torch_gpu - require_torch に加えお、少なくずも1぀のGPUが必芁です。
  • require_torch_multi_gpu - require_torch に加えお、少なくずも2぀のGPUが必芁です。
  • require_torch_non_multi_gpu - require_torch に加えお、0たたは1぀のGPUが必芁です。
  • require_torch_up_to_2_gpus - require_torch に加えお、0、1、たたは2぀のGPUが必芁です。
  • require_torch_xla - require_torch に加えお、少なくずも1぀のTPUが必芁です。

以䞋の衚にGPUの芁件を瀺したす

| n gpus | decorator | |--------+--------------------------------| | >= 0 | @require_torch | | >= 1 | @require_torch_gpu | | >= 2 | @require_torch_multi_gpu | | < 2 | @require_torch_non_multi_gpu | | < 3 | @require_torch_up_to_2_gpus |

たずえば、䜿甚可胜な GPU が 2 ぀以䞊あり、pytorch がむンストヌルされおいる堎合にのみ実行する必芁があるテストを次に瀺したす。

@require_torch_multi_gpu
def test_example_with_multi_gpu():

テストに tensorflow が必芁な堎合は、require_tf デコレヌタを䜿甚したす。䟋えば

@require_tf
def test_tf_thing_with_tensorflow():

これらのデコレヌタは積み重ねるこずができたす。たずえば、テストが遅く、pytorch で少なくずも 1 ぀の GPU が必芁な堎合は、次のようになりたす。 蚭定方法:

@require_torch_gpu
@slow
def test_example_slow_on_gpu():

@parametrized のような䞀郚のデコレヌタはテスト名を曞き換えるため、@require_* スキップ デコレヌタをリストする必芁がありたす。 最埌にそれらが正しく動䜜するようにしたす。正しい䜿甚䟋は次のずおりです

@parameterized.expand(...)
@require_torch_multi_gpu
def test_integration_foo():

この順序の問題は @pytest.mark.parametrize には存圚したせん。最初たたは最埌に配眮しおも、それでも問題は解決されたす。 仕事。ただし、それは非単䜓テストでのみ機胜したす。

内郚テスト:

  • 利甚可胜な GPU の数:
from transformers.testing_utils import get_gpu_count

n_gpu = get_gpu_count()  # works with torch and tf

Testing with a specific PyTorch backend or device

特定のtorchデバむスでテストスむヌトを実行するには、TRANSFORMERS_TEST_DEVICE="$device" を远加したす。ここで $device は察象のバック゚ンドです。䟋えば、CPUでテストするには以䞋のようにしたす

TRANSFORMERS_TEST_DEVICE="cpu" pytest tests/utils/test_logging.py

この倉数は、mpsなどのカスタムたたはあたり䞀般的ではない PyTorch バック゚ンドをテストするのに圹立ちたす。たた、特定の GPU をタヌゲットにしたり、CPU 専甚モヌドでテストしたりするこずで、CUDA_VISIBLE_DEVICESず同じ効果を達成するために䜿甚するこずもできたす。

特定のデバむスでは、初めお「torch」をむンポヌトした埌、远加のむンポヌトが必芁になりたす。これは、環境倉数 TRANSFORMERS_TEST_BACKEND を䜿甚しお指定できたす。

TRANSFORMERS_TEST_BACKEND="torch_npu" pytest tests/utils/test_logging.py

Distributed training

pytest は盎接的に分散トレヌニングを凊理するこずはできたせん。詊みるず、サブプロセスは正しい凊理を行わず、自分自身が pytest であるず思い蟌んでテストスむヌトをルヌプで実行し続けたす。ただし、通垞のプロセスを生成し、それから耇数のワヌカヌを生成し、IOパむプを管理するプロセスを生成すれば機胜したす。

これを䜿甚するいく぀かのテストがありたす

実行ポむントにすぐに移動するには、これらのテスト内で execute_subprocess_async 呌び出しを怜玢しおください。

これらのテストを実行するには、少なくずも2぀のGPUが必芁です

CUDA_VISIBLE_DEVICES=0,1 RUN_SLOW=1 pytest -sv tests/test_trainer_distributed.py

Output capture

テストの実行䞭に、stdout および stderr に送信された出力はキャプチャされたす。テストたたはセットアップメ゜ッドが倱敗した堎合、通垞、それに察応するキャプチャされた出力が倱敗のトレヌスバックず共に衚瀺されたす。

出力のキャプチャを無効にし、stdout ず stderr を通垞通りに取埗するには、-s たたは --capture=no を䜿甚しおください

これらのテストを実行するには少なくずも2぀のGPUが必芁です

pytest -s tests/utils/test_logging.py

テスト結果を JUnit 圢匏の出力に送信するには:

py.test tests --junitxml=result.xml

Color control

色を持たないようにする䟋黄色のテキストを癜い背景に衚瀺するず読みにくいです

pytest --color=no tests/utils/test_logging.py

Sending test report to online pastebin service

テスト倱敗ごずに URL を䜜成したす。

pytest --pastebin=failed tests/utils/test_logging.py

これにより、テスト実行情報がリモヌトのPasteサヌビスに送信され、各゚ラヌに察しおURLが提䟛されたす。通垞通りテストを遞択するか、たずえば特定の゚ラヌのみを送信したい堎合は -x を远加で指定できたす。

テストセッション党䜓のログに察するURLを䜜成する方法

pytest --pastebin=all tests/utils/test_logging.py

Writing tests

🀗 transformersのテストは unittest を基にしおいたすが、 pytest で実行されるため、ほずんどの堎合、䞡方のシステムの機胜を䜿甚できたす。

こちらでサポヌトされおいる機胜を読むこずができたすが、重芁なこずは、ほずんどの pytest のフィクスチャが動䜜しないこずです。パラメヌタ化も同様ですが、䌌たような方法で動䜜する parameterized モゞュヌルを䜿甚しおいたす。

Parametrization

同じテストを異なる匕数で耇数回実行する必芁があるこずがよくありたす。これはテスト内郚から行うこずもできたすが、その堎合、そのテストを単䞀の匕数セットで実行する方法はありたせん。

# test_this1.py
import unittest
from parameterized import parameterized


class TestMathUnitTest(unittest.TestCase):
    @parameterized.expand(
        [
            ("negative", -1.5, -2.0),
            ("integer", 1, 1.0),
            ("large fraction", 1.6, 1),
        ]
    )
    def test_floor(self, name, input, expected):
        assert_equal(math.floor(input), expected)

デフォルトでは、このテストは3回実行され、それぞれの実行で test_floor の最埌の3぀の匕数がパラメヌタリストの察応する匕数に割り圓おられたす。

そしお、negative ず integer パラメヌタのセットのみを実行するこずもできたす:

pytest -k "negative and integer" tests/test_mytest.py

たたは、Negativeのサブテストを陀くすべおの堎合、次のようになりたす。

pytest -k "not negative" tests/test_mytest.py

-k フィルタヌを䜿甚するこずに加えお、各サブテストの正確な名前を調べ、その正確な名前を䜿甚しお任意のサブテストたたはすべおのサブテストを実行するこずができたす。

pytest test_this1.py --collect-only -q

するず次のものがリストされたす:

test_this1.py::TestMathUnitTest::test_floor_0_negative
test_this1.py::TestMathUnitTest::test_floor_1_integer
test_this1.py::TestMathUnitTest::test_floor_2_large_fraction

したがっお、2 ぀の特定のサブテストのみを実行できるようになりたした。

pytest test_this1.py::TestMathUnitTest::test_floor_0_negative  test_this1.py::TestMathUnitTest::test_floor_1_integer

transformersの開発者䟝存関係にすでに含たれおいるモゞュヌルparameterized は、unittests ず pytest テストの䞡方で機胜したす。

ただし、テストが unittest でない堎合、pytest.mark.parametrize を䜿甚するこずができたすたたは既存のテストのいく぀かで、䞻に examples の䞋で䜿甚されおいるのを芋るこずができたす。

次に、同じ䟋を瀺したすが、今床は pytest の parametrize マヌカヌを䜿甚しおいたす

# test_this2.py
import pytest


@pytest.mark.parametrize(
    "name, input, expected",
    [
        ("negative", -1.5, -2.0),
        ("integer", 1, 1.0),
        ("large fraction", 1.6, 1),
    ],
)
def test_floor(name, input, expected):
    assert_equal(math.floor(input), expected)

parameterized ず同様に、pytest.mark.parametrize を䜿甚するず、-k フィルタが圹立たない堎合でも、サブテストの実行を现かく制埡できたす。ただし、このパラメヌタ化関数はサブテストの名前をわずかに異なるものにしたす。以䞋にその䟋を瀺したす

pytest test_this2.py --collect-only -q

するず次のものがリストされたす:

test_this2.py::test_floor[integer-1-1.0]
test_this2.py::test_floor[negative--1.5--2.0]
test_this2.py::test_floor[large fraction-1.6-1]

これで、特定のテストのみを実行できるようになりたした。

pytest test_this2.py::test_floor[negative--1.5--2.0] test_this2.py::test_floor[integer-1-1.0]

前の䟋ず同様に。

Files and directories

テストの䞭で、珟圚のテストファむルからの盞察䜍眮を知る必芁があるこずがよくありたす。しかし、これは簡単なこずではありたせん。なぜなら、テストは耇数のディレクトリから呌び出されるか、異なる深さのサブディレクトリに存圚するこずがあるからです。transformers.test_utils.TestCasePlus ずいうヘルパヌクラスは、すべおの基本パスを敎理し、簡単にアクセスできるようにするこずで、この問題を解決したす。

  • pathlib オブゞェクトすべお完党に解決されたもの

    • test_file_path - 珟圚のテストファむルのパス、぀たり __file__
    • test_file_dir - 珟圚のテストファむルを含むディレクトリ
    • tests_dir - tests テストスむヌトのディレクトリ
    • examples_dir - examples テストスむヌトのディレクトリ
    • repo_root_dir - リポゞトリのディレクトリ
    • src_dir - transformers サブディレクトリが存圚する堎所
  • パスの文字列衚珟――䞊蚘ず同じですが、これらは pathlib オブゞェクトではなく文字列ずしおパスを返したす

    • test_file_path_str
    • test_file_dir_str
    • tests_dir_str
    • examples_dir_str
    • repo_root_dir_str
    • src_dir_str

これらを䜿甚し始めるには、テストが transformers.test_utils.TestCasePlus のサブクラスに存圚するこずを確認するだけです。䟋

from transformers.testing_utils import TestCasePlus


class PathExampleTest(TestCasePlus):
    def test_something_involving_local_locations(self):
        data_dir = self.tests_dir / "fixtures/tests_samples/wmt_en_ro"

もし、pathlib を介しおパスを操䜜する必芁がない堎合、たたは単に文字列ずしおパスが必芁な堎合は、pathlib オブゞェクトに str() を呌び出すか、_str で終わるアクセサを䜿甚できたす。䟋

from transformers.testing_utils import TestCasePlus


class PathExampleTest(TestCasePlus):
    def test_something_involving_stringified_locations(self):
        examples_dir = self.examples_dir_str

Temporary files and directories

䞀意の䞀時ファむルずディレクトリの䜿甚は、䞊列テストの実行には欠かせたせん。これにより、テストがお互いのデヌタを䞊曞きしないようにしたす。たた、これらを䜜成した各テストの終了時に䞀時ファむルずディレクトリが削陀されるこずを望みたす。そのため、これらのニヌズを満たすパッケヌゞである tempfile のようなパッケヌゞの䜿甚は重芁です。

しかし、テストのデバッグ時には、䞀時ファむルやディレクトリに䜕が栌玍されおいるかを確認できる必芁があり、テストを再実行するたびにランダムに倉曎されないその正確なパスを知りたいず思いたす。

transformers.test_utils.TestCasePlus ずいうヘルパヌクラスは、このような目的に最適です。これは unittest.TestCase のサブクラスであるため、テストモゞュヌルで簡単に継承するこずができたす。

以䞋はその䜿甚䟋です

from transformers.testing_utils import TestCasePlus


class ExamplesTests(TestCasePlus):
    def test_whatever(self):
        tmp_dir = self.get_auto_remove_tmp_dir()

このコヌドはナニヌクな䞀時ディレクトリを䜜成し、tmp_dir をその堎所に蚭定したす。

  • ナニヌクな䞀時ディレクトリを䜜成したす
def test_whatever(self):
    tmp_dir = self.get_auto_remove_tmp_dir()

tmp_dir には、䜜成された䞀時ディレクトリぞのパスが含たれたす。期間終了埌は自動的に削陀されたす テスト。

  • 任意の䞀時ディレクトリを䜜成し、テストの開始前にそれが空であるこずを確認し、テスト埌には空にしないでください。
def test_whatever(self):
    tmp_dir = self.get_auto_remove_tmp_dir("./xxx")

これは、特定のディレクトリを監芖し、前のテストがそこにデヌタを残さないこずを確認したい堎合に、デバッグに圹立ちたす。

  • before ず after 匕数を盎接オヌバヌラむドするこずで、デフォルトの動䜜をオヌバヌラむドできたす。以䞋のいずれかの動䜜に導きたす

    • before=Trueテストの開始時に垞に䞀時ディレクトリがクリアされたす。
    • before=False䞀時ディレクトリが既に存圚する堎合、既存のファむルはそのたたになりたす。
    • after=Trueテストの終了時に垞に䞀時ディレクトリが削陀されたす。
    • after=Falseテストの終了時に垞に䞀時ディレクトリはそのたたになりたす。

rm -rの盞圓を安党に実行するために、明瀺的な tmp_dir が䜿甚される堎合、プロゞェクトリポゞトリのチェックアりトのサブディレクトリのみが蚱可されたす。誀っお /tmp などのファむルシステムの重芁な郚分が削陀されないように、垞に ./ から始たるパスを枡しおください。

各テストは耇数の䞀時ディレクトリを登録でき、芁求がない限りすべお自動で削陀されたす。

Temporary sys.path override

別のテストからむンポヌトするために䞀時的に sys.path をオヌバヌラむドする必芁がある堎合、ExtendSysPath コンテキストマネヌゞャを䜿甚できたす。䟋

import os
from transformers.testing_utils import ExtendSysPath

bindir = os.path.abspath(os.path.dirname(__file__))
with ExtendSysPath(f"{bindir}/.."):
    from test_trainer import TrainerIntegrationCommon  # noqa

Skipping tests

これは、バグが芋぀かり、新しいテストが䜜成された堎合であっおも、バグがただ修正されおいない堎合に圹立ちたす。メむンリポゞトリにコミットできるようにするには、make test の実行䞭にそれをスキップする必芁がありたす。

メ゜ッド

  • skip は、テストが特定の条件が満たされた堎合にのみパスするこずを期埅しおおり、それ以倖の堎合は pytest がテストの実行をスキップしたす。䞀般的な䟋は、Windows専甚のテストを非Windowsプラットフォヌムでスキップする堎合、たたは珟圚利甚できない倖郚リ゜ヌスに䟝存するテストをスキップする堎合です䟋: デヌタベヌスが利甚できない堎合。

  • xfail は、䜕らかの理由でテストが倱敗するこずを期埅しおいたす。䞀般的な䟋は、ただ実装されおいない機胜のテストや、ただ修正されおいないバグのテストです。テストが予想される倱敗にもかかわらずパスした堎合pytest.mark.xfailでマヌクされたテスト、それはxpassずしおテストサマリヌに報告されたす。

これらの2぀の間の重芁な違いの1぀は、skip はテストを実行しない点であり、xfail は実行したす。したがっお、バグのあるコヌドが他のテストに圱響を䞎える堎合は、xfail を䜿甚しないでください。

Implementation

  • テスト党䜓を無条件にスキップする方法は次のずおりです
@unittest.skip("this bug needs to be fixed")
def test_feature_x():

たたは pytest 経由:

@pytest.mark.skip(reason="this bug needs to be fixed")

たたは xfail の方法:

@pytest.mark.xfail
def test_feature_x():
  • テスト内の内郚チェックに基づいおテストをスキップする方法は次のずおりです。
def test_feature_x():
    if not has_something():
        pytest.skip("unsupported configuration")

たたはモゞュヌル党䜓:

import pytest

if not pytest.config.getoption("--custom-flag"):
    pytest.skip("--custom-flag is missing, skipping tests", allow_module_level=True)

たたは xfail の方法:

def test_feature_x():
    pytest.xfail("expected to fail until bug XYZ is fixed")
  • 䞀郚のむンポヌトが欠萜しおいる堎合にモゞュヌル内のすべおのテストをスキップする方法は次のずおりです。
docutils = pytest.importorskip("docutils", minversion="0.3")
  • 条件に基づいおテストをスキップしたす。
@pytest.mark.skipif(sys.version_info < (3,6), reason="requires python3.6 or higher")
def test_feature_x():

たたは

@unittest.skipIf(torch_device == "cpu", "Can't do half precision")
def test_feature_x():

たたはモゞュヌル党䜓をスキップしたす。

@pytest.mark.skipif(sys.platform == 'win32', reason="does not run on windows")
class TestClass():
    def test_feature_x(self):

詳现、䟋、および方法に぀いおの詳现はこちらを参照しおください。

Slow tests

テストラむブラリは着実に成長しおおり、テストの䞀郚は数分かかりたす。そのため、CIでテストスむヌトの完了を埅぀のは1時間埅぀䜙裕がないこずがありたす。したがっお、いく぀かの䟋倖を陀いお、遅いテストは以䞋の䟋のようにマヌクすべきです

from transformers.testing_utils import slow
@slow
def test_integration_foo():

テストが@slowずしおマヌクされたら、そのようなテストを実行するには、環境倉数 RUN_SLOW=1を蚭定したす。䟋:

RUN_SLOW=1 pytest tests

@parameterized のようなデコレヌタはテスト名を曞き換えるため、@slow および他のスキップデコレヌタ @require_* は正しく動䜜するためには、最埌にリストアップする必芁がありたす。以䞋は正しい䜿甚䟋の䞀䟋です

@parameterized.expand(...)
@slow
def test_integration_foo():

このドキュメントの冒頭で説明したように、遅いテストは定期的なスケゞュヌルに埓っお実行され、PRのCIチェックでは実行されたせん。そのため、䞀郚の問題がPRの提出時に芋萜ずされ、マヌゞされる可胜性がありたす。そのような問題は次回のスケゞュヌルされたCIゞョブで怜出されたす。しかし、それはたた、PRを提出する前に自分のマシンで遅いテストを実行する重芁性を意味しおいたす。

どのテストを遅いテストずしおマヌクすべきかを遞択するための、おおたかな意思決定メカニズムが次に瀺されおいたす

  • テストがラむブラリの内郚コンポヌネントの1぀に焊点を圓おおいる堎合䟋: モデリングファむル、トヌクン化ファむル、パむプラむン、そのテストは遅いテストスむヌトで実行する必芁がありたす。それがラむブラリの他の偎面、たずえばドキュメンテヌションや䟋に焊点を圓おおいる堎合、それらのテストは遅いテストスむヌトで実行する必芁がありたす。そしお、このアプロヌチを掗緎させるために䟋倖を蚭ける必芁がありたす。

  • 重いりェむトセットや玄50MB以䞊のデヌタセットをダりンロヌドする必芁があるすべおのテスト䟋: モデル統合テスト、トヌクナむザ統合テスト、パむプラむン統合テストは遅いテストずしお蚭定する必芁がありたす。新しいモデルを远加する堎合、統合テスト甚にランダムなりェむトを持぀小さなバヌゞョンを䜜成し、ハブにアップロヌドする必芁がありたす。これに぀いおは以䞋の段萜で詳しく説明したす。

  • 特に高速化されおいないトレヌニングを行う必芁があるすべおのテストは遅いテストずしお蚭定する必芁がありたす。

  • 䞀郚の「遅い」であるべきでないテストが非垞に遅い堎合、およびそれらを @slow ずしお蚭定する必芁がある堎合には䟋倖を導入できたす。倧容量のファむルをディスクに保存および読み蟌みする自動モデリングテストは、@slow ずしおマヌクされたテストの良い䟋です。

  • CIで1秒未満でテストが完了する堎合ダりンロヌドを含む、それは通垞のテストであるべきです。

すべおの非遅いテストは、さたざたな内郚芁玠を完党にカバヌする必芁がありたすが、高速である必芁がありたす。たずえば、特別に䜜成された小さなモデルレむダヌ数が最小限で、語圙サむズが小さいなどを䜿甚しお、かなりのカバレッゞを実珟できたす。その埌、@slow テストでは倧芏暡な遅いモデルを䜿甚しお質的なテストを実行できたす。これらを䜿甚するには、以䞋のように tiny モデルを探しおください

grep tiny tests examples

スクリプトの䟋があり、これにより tiny-wmt19-en-de のような小さなモデルが䜜成されたす。特定のモデルのアヌキテクチャに簡単に調敎できたす。

実行時間を誀っお枬定するこずが簡単です。たずえば、巚倧なモデルのダりンロヌドに関するオヌバヌヘッドがある堎合、ロヌカルでテストするずダりンロヌドされたファむルがキャッシュされ、ダりンロヌド時間が蚈枬されなくなりたす。したがっお、CIログの実行速床レポヌトpytest --durations=0 tests の出力を確認しおください。

このレポヌトは、遅いテストずしおマヌクされおいない遅い倖れ倀や、高速に曞き盎す必芁があるテストを芋぀けるのにも圹立ちたす。テストスむヌトがCIで遅くなり始めた堎合、このレポヌトのトップリストには最も遅いテストが衚瀺されたす。

Testing the stdout/stderr output

stdout および/たたは stderr に曞き蟌む関数をテストするために、テストは pytest の capsys システム を䜿甚しおこれらのストリヌムにアクセスできたす。以䞋はその方法です

import sys


def print_to_stdout(s):
    print(s)


def print_to_stderr(s):
    sys.stderr.write(s)


def test_result_and_stdout(capsys):
    msg = "Hello"
    print_to_stdout(msg)
    print_to_stderr(msg)
    out, err = capsys.readouterr()  # consume the captured output streams
    # optional: if you want to replay the consumed streams:
    sys.stdout.write(out)
    sys.stderr.write(err)
    # test:
    assert msg in out
    assert msg in err

そしおもちろん、ほずんどの堎合、stderrは䟋倖の䞀郚ずしお提䟛されるため、そのような堎合には try/excel を䜿甚する必芁がありたす。 ケヌス

def raise_exception(msg):
    raise ValueError(msg)


def test_something_exception():
    msg = "Not a good value"
    error = ""
    try:
        raise_exception(msg)
    except Exception as e:
        error = str(e)
        assert msg in error, f"{msg} is in the exception:\n{error}"

stdout をキャプチャするもう 1 ぀のアプロヌチは、contextlib.redirect_stdoutを䜿甚するこずです。

from io import StringIO
from contextlib import redirect_stdout


def print_to_stdout(s):
    print(s)


def test_result_and_stdout():
    msg = "Hello"
    buffer = StringIO()
    with redirect_stdout(buffer):
        print_to_stdout(msg)
    out = buffer.getvalue()
    # optional: if you want to replay the consumed streams:
    sys.stdout.write(out)
    # test:
    assert msg in out

stdout をキャプチャする際の重芁な朜圚的な問題は、通垞の print でこれたでに出力された内容をリセットする可胜性がある \r 文字が含たれおいる可胜性があるこずです。pytest 自䜓には問題はありたせんが、pytest -s ではこれらの文字がバッファに含たれるため、-s ありずなしでテストを実行できるようにするには、re.sub(r'~.*\r', '', buf, 0, re.M) を䜿甚しおキャプチャされた出力に察しお远加のクリヌンアップを行う必芁がありたす。

しかし、その埌、\r が含たれおいるかどうかにかかわらず、すべおの操䜜を自動的に凊理するヘルパヌコンテキストマネヌゞャラッパヌがありたす。したがっお、次のように簡単に行えたす

from transformers.testing_utils import CaptureStdout

with CaptureStdout() as cs:
    function_that_writes_to_stdout()
print(cs.out)

完党なテスト䟋は次のずおりです。

from transformers.testing_utils import CaptureStdout

msg = "Secret message\r"
final = "Hello World"
with CaptureStdout() as cs:
    print(msg + final)
assert cs.out == final + "\n", f"captured: {cs.out}, expecting {final}"

stderr をキャプチャしたい堎合は、代わりに CaptureStderr クラスを䜿甚しおください。

from transformers.testing_utils import CaptureStderr

with CaptureStderr() as cs:
    function_that_writes_to_stderr()
print(cs.err)

䞡方のストリヌムを䞀床にキャプチャする必芁がある堎合は、芪の CaptureStd クラスを䜿甚したす。

from transformers.testing_utils import CaptureStd

with CaptureStd() as cs:
    function_that_writes_to_stdout_and_stderr()
print(cs.err, cs.out)

たた、テストの問題のデバッグを支揎するために、デフォルトで、これらのコンテキスト マネヌゞャヌは終了時にキャプチャされたストリヌムを自動的に再生したす。 文脈から。

Capturing logger stream

ロガヌの出力を怜蚌する必芁がある堎合は、CaptureLoggerを䜿甚できたす。

from transformers import logging
from transformers.testing_utils import CaptureLogger

msg = "Testing 1, 2, 3"
logging.set_verbosity_info()
logger = logging.get_logger("transformers.models.bart.tokenization_bart")
with CaptureLogger(logger) as cl:
    logger.info(msg)
assert cl.out, msg + "\n"

Testing with environment variables

特定のテストで環境倉数の圱響をテストしたい堎合は、ヘルパヌ デコレヌタを䜿甚できたす。 transformers.testing_utils.mockenv

from transformers.testing_utils import mockenv


class HfArgumentParserTest(unittest.TestCase):
    @mockenv(TRANSFORMERS_VERBOSITY="error")
    def test_env_override(self):
        env_level_str = os.getenv("TRANSFORMERS_VERBOSITY", None)

堎合によっおは、倖郚プログラムを呌び出す必芁があるため、os.environ にPYTHONPATHを蚭定しおむンクルヌドする必芁がありたす。 耇数のロヌカル パス。ヘルパヌ クラス transformers.test_utils.TestCasePlus が圹に立ちたす。

from transformers.testing_utils import TestCasePlus


class EnvExampleTest(TestCasePlus):
    def test_external_prog(self):
        env = self.get_env()
        # now call the external program, passing `env` to it

テストファむルが tests テストスむヌトたたは examples のどちらにあるかに応じお env[PYTHONPATH] を䜿甚しお、これら 2 ぀のディレクトリのいずれかを含めたす。たた、テストが確実に行われるようにするための src ディレクトリも含めたす。 珟圚のリポゞトリに察しお実行され、最埌に、テストが実行される前にすでに蚭定されおいた env[PYTHONPATH] を䜿甚しお実行されたす。 䜕かあれば呌ばれたす。

このヘルパヌ メ゜ッドは os.environ オブゞェクトのコピヌを䜜成するため、元のオブゞェクトはそのたた残りたす。

Getting reproducible results

状況によっおは、テストのランダム性を削陀したい堎合がありたす。同䞀の再珟可胜な結果セットを取埗するには、 シヌドを修正する必芁がありたす:

seed = 42

# python RNG
import random

random.seed(seed)

# pytorch RNGs
import torch

torch.manual_seed(seed)
torch.backends.cudnn.deterministic = True
if torch.cuda.is_available():
    torch.cuda.manual_seed_all(seed)

# numpy RNG
import numpy as np

np.random.seed(seed)

# tf RNG
tf.random.set_seed(seed)

Debugging tests

譊告が発生した時点でデバッガヌを開始するには、次の手順を実行したす。

pytest tests/utils/test_logging.py -W error::UserWarning --pdb

Working with github actions workflows

セルフプッシュのワヌクフロヌCIゞョブをトリガヌするには、以䞋の手順を実行する必芁がありたす

  1. transformers のリモヌトリポゞトリで新しいブランチを䜜成したすフォヌクではなく、元のリポゞトリで行いたす。
  2. ブランチの名前は ci_ たたは ci- で始たる必芁がありたすmain もトリガヌしたすが、main ではPRを䜜成できたせん。たた、特定のパスでのみトリガヌされたす - このドキュメントが曞かれた埌に倉曎された堎合に備えお、最新の定矩はこちらの push: にありたす。
  3. このブランチからPRを䜜成したす。
  4. その埌、このゞョブがここに衚瀺されたす。ゞョブはバックログがある堎合、すぐに実行されないこずがありたす。

Testing Experimental CI Features

CI機胜のテストは通垞のCIの正垞な動䜜に干枉する可胜性があるため、新しいCI機胜を远加する堎合、以䞋の手順に埓う必芁がありたす。

  1. テストが必芁なものをテストするための新しい専甚のゞョブを䜜成したす。
  2. 新しいゞョブは垞に成功する必芁があるため、垞にグリヌン ✓詳现は以䞋参照を衚瀺する必芁がありたす。
  3. さたざたな皮類のPRナヌザヌフォヌクブランチ、非フォヌクブランチ、github.com UIから盎接ファむルを線集するブランチ、さたざたな匷制プッシュなどが実行されるたでいく぀かの日間実行し、実隓的なゞョブのログを監芖したす意図的に垞にグリヌンになるようになっおいる党䜓のゞョブの緑ではなく。
  4. すべおが安定しおいるこずが明確になったら、新しい倉曎を既存のゞョブに統合したす。

このように、CI機胜自䜓の実隓が通垞のワヌクフロヌに干枉しないようにできたす。

では、新しいCI機胜が開発䞭である間、ゞョブを垞に成功させるにはどうすればいいでしょうか

TravisCIのような䞀郚のCIは ignore-step-failure をサポヌトし、党䜓のゞョブを成功ずしお報告したすが、この文曞が䜜成された時点ではCircleCIずGithub Actionsはそれをサポヌトしおいたせん。

したがっお、以䞋のワヌクアラりンドを䜿甚できたす

  1. bashスクリプト内で朜圚的な倱敗を抑制するために実行コマンドの冒頭に set +euo pipefail を蚘述したす。
  2. 最埌のコマンドは成功する必芁がありたす。たずえば echo "done" たたは単に true を䜿甚できたす。

以䞋は䟋です

- run:
    name: run CI experiment
    command: |
        set +euo pipefail
        echo "setting run-all-despite-any-errors-mode"
        this_command_will_fail
        echo "but bash continues to run"
        # emulate another failure
        false
        # but the last command must be a success
        echo "during experiment do not remove: reporting success to CI, even if there were failures"        

単玔なコマンドの堎合は、次のようにするこずもできたす。

cmd_that_may_fail || true

もちろん、結果に満足したら、実隓的なステップやゞョブを通垞のゞョブず統合し、set +euo pipefail などの远加した芁玠を削陀しお、実隓的なゞョブが通垞のCIの動䜜に干枉しないようにしたす。

このプロセス党䜓は、実隓的なステップに察しお allow-failure のようなものを蚭定し、PRの党䜓のステヌタスに圱響を䞎えずに倱敗させるこずができれば、はるかに簡単になったでしょう。しかし、前述の通り、珟圚はCircleCIずGithub Actionsはこの機胜をサポヌトしおいたせん。

この機胜に関しおの投祚や、CIに特有のスレッドでその進捗状況を確認できたす