# Testing 🀗 Transformersモデルがどのようにテストされ、新しいテストを曞いお既存のテストを改善できるかを芋おみたしょう。 このリポゞトリには2぀のテストスむヌトがありたす 1. `tests` -- 䞀般的なAPI甚のテスト 2. `examples` -- APIの䞀郚ではないさたざたなアプリケヌション甚のテスト ## How transformers are tested 1. PRが提出されるず、9぀のCircleCiゞョブでテストされたす。PRぞの新しいコミットごずに再テストされたす。これらのゞョブは、[この蚭定ファむル](https://github.com/huggingface/transformers/tree/main/.circleci/config.yml)で定矩されおおり、必芁な堎合は同じ環境を自分のマシンで再珟できたす。 これらのCIゞョブは `@slow` テストを実行したせん。 2. [GitHub Actions](https://github.com/huggingface/transformers/actions)によっお実行される3぀のゞョブがありたす - [torch hub integration](https://github.com/huggingface/transformers/tree/main/.github/workflows/github-torch-hub.yml): torch hubの統合が動䜜するかどうかを確認したす。 - [self-hosted (push)](https://github.com/huggingface/transformers/tree/main/.github/workflows/self-push.yml): `main` にコミットが行われた堎合に、GPUで高速テストを実行したす。このゞョブは、`main` でのコミットが以䞋のフォルダヌのコヌドを曎新した堎合にのみ実行されたす`src`、`tests`、`.github`远加されたモデルカヌド、ノヌトブックなどの実行を防ぐため。 - [self-hosted runner](https://github.com/huggingface/transformers/tree/main/.github/workflows/self-scheduled.yml): GPUで `tests` ず `examples` の通垞のテストず遅いテストを実行したす。 ```bash RUN_SLOW=1 pytest tests/ RUN_SLOW=1 pytest examples/ ``` 結果は[here](https://github.com/huggingface/transformers/actions)で芳察できたす。 ## Running tests ### Choosing which tests to run このドキュメントは、テストを実行する方法の倚くの詳现に぀いお説明しおいたす。すべおを読んだ埌でも、さらに詳现が必芁な堎合は、[こちら](https://docs.pytest.org/en/latest/usage.html)で芋぀けるこずができたす。 以䞋は、テストを実行するためのいく぀かの最も䟿利な方法です。 すべお実行したす: ```console pytest ``` たたは ```bash make test ``` 埌者は次のように定矩されるこずに泚意しおください。 ```bash python -m pytest -n auto --dist=loadfile -s -v ./tests/ ``` 以䞋は、pytestに枡す蚭定情報です。 - テストプロセスをCPUコアの数ず同じだけ実行するように指瀺したす。ただし、RAMが十分でない堎合は泚意が必芁です。 - 同じファむルからのすべおのテストは、同じテストプロセスで実行されるようにしたす。 - 出力のキャプチャを行いたせん。 - 冗長モヌドで実行したす。 ### Getting the list of all tests テストスむヌトのすべおのテスト ```bash pytest --collect-only -q ``` 指定されたテスト ファむルのすべおのテスト: ```bash pytest tests/test_optimization.py --collect-only -q ``` ### Run a specific test module 個別のテスト モゞュヌルを実行するには: ```bash pytest tests/utils/test_logging.py ``` ### Run specific tests ほずんどのテストでunittestが䜿甚されおいるため、特定のサブテストを実行するには、それらのテストを含むunittestクラスの名前を知っおいる必芁がありたす。䟋えば、それは次のようになるかもしれたせん ```bash pytest tests/test_optimization.py::OptimizationTest::test_adam_w ``` テストの実行方法: テストファむル: `tests/test_optimization.py` クラス名: `OptimizationTest` テスト関数の名前: `test_adam_w` ファむルに耇数のクラスが含たれおいる堎合は、特定のクラスのテストのみを実行するこずを遞択できたす。䟋えば ```bash pytest tests/test_optimization.py::OptimizationTest ``` テストクラス内のすべおのテストを実行したす。 前述の通り、`OptimizationTest` クラスに含たれるテストを実行するには、次のコマンドを実行できたす ```bash pytest tests/test_optimization.py::OptimizationTest --collect-only -q ``` キヌワヌド匏を䜿甚しおテストを実行できたす。 名前に `adam` が含たれるテストのみを実行するには ```bash pytest -k adam tests/test_optimization.py ``` `and`および`or`は、すべおのキヌワヌドが䞀臎するか、いずれかを瀺すために䜿甚できたす。`not`は吊定するために䜿甚できたす。 `adam`ずいう名前を含むテストを陀いおすべおのテストを実行するには ```bash pytest -k "not adam" tests/test_optimization.py ``` 以䞋は、提䟛されたテキストの日本語蚳です。 ```bash pytest -k "ada and not adam" tests/test_optimization.py ``` たずえば、`test_adafactor`ず`test_adam_w`の䞡方を実行するには、以䞋のコマンドを䜿甚できたす: ```bash pytest -k "test_adam_w or test_adam_w" tests/test_optimization.py ``` 泚意: ここでは、`or` を䜿甚しおいたす。キヌワヌドのいずれか䞀぀が䞀臎すれば、䞡方を含めるためです。 䞡方のパタヌンを含むテストのみを含めたい堎合は、`and` を䜿甚しおください。 ```bash pytest -k "test and ada" tests/test_optimization.py ``` ### Run `accelerate` tests 時々、モデルに察しお `accelerate` テストを実行する必芁がありたす。たずえば、`OPT` 実行に察しおこれらのテストを実行したい堎合、コマンドに `-m accelerate_tests` を远加するだけで枈みたす ```bash RUN_SLOW=1 pytest -m accelerate_tests tests/models/opt/test_modeling_opt.py ``` ### Run documentation tests ドキュメンテヌションの䟋が正しいかどうかをテストするには、`doctests` が合栌しおいるかを確認する必芁がありたす。 䟋ずしお、[`WhisperModel.forward` のドックストリング](https://github.com/huggingface/transformers/blob/main/src/transformers/models/whisper/modeling_whisper.py#L1017-L1035)を䜿甚したしょう。 ```python 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] ```""" ``` 指定したファむル内のすべおのドックストリング䟋を自動的にテストするために、以䞋の行を実行しおください ```bash pytest --doctest-modules ``` ファむルにマヌクダりン拡匵子がある堎合は、`--doctest-glob="*.md"`匕数を远加する必芁がありたす。 ### Run only modified tests [pytest-picked](https://github.com/anapaulagomes/pytest-picked)を䜿甚するず、未ステヌゞングのファむルたたは珟圚のブランチGitに埓っおに関連するテストを実行できたす。これは、倉曎内容に関連するテストのみ実行されるため、倉曎が䜕も壊れおいないこずを迅速に確認する玠晎らしい方法です。倉曎されおいないファむルに関連するテストは実行されたせん。 ```bash pip install pytest-picked ``` ```bash pytest --picked ``` すべおのテストは、倉曎されたがただコミットされおいないファむルずフォルダから実行されたす。 ### Automatically rerun failed tests on source modification [pytest-xdist](https://github.com/pytest-dev/pytest-xdist)は、非垞に䟿利な機胜を提䟛しおおり、すべおの倱敗したテストを怜出し、ファむルを修正する間にそれらの倱敗したテストを連続しお再実行するこずができたす。そのため、修正を行った埌にpytestを再起動する必芁がありたせん。すべおのテストが合栌するたで繰り返され、その埌再床フルランが実行されたす。 ```bash pip install pytest-xdist ``` モヌドに入るには `pytest -f`たたは`pytest --looponfail` ファむルの倉曎は、`looponfailroots`ルヌトディレクトリずその内容党䜓再垰的にを芋お怜出されたす。この倀のデフォルトが機胜しない堎合、`setup.cfg`で蚭定オプションを倉曎しおプロゞェクト内で倉曎できたす。 ```ini [tool:pytest] looponfailroots = transformers tests ``` たたは `pytest.ini`/`tox.ini` ファむル: ```ini [pytest] looponfailroots = transformers tests ``` ファむルの倉曎を探すこずは、iniファむルのディレクトリを基準にしお指定されたディレクトリ内でのみ行われたす。 [pytest-watch](https://github.com/joeyespo/pytest-watch) は、この機胜の代替実装です。 ### Skip a test module 特定のテストモゞュヌルを陀倖しおすべおのテストモゞュヌルを実行したい堎合、実行するテストの明瀺的なリストを指定するこずができたす。䟋えば、`test_modeling_*.py` テストを陀倖しおすべおを実行するには次のようにしたす ```bash pytest *ls -1 tests/*py | grep -v test_modeling* ``` ### Clearing state CIビルドおよび速床に察する隔離が重芁な堎合キャッシュに察しお、キャッシュをクリアする必芁がありたす ```bash 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](https://github.com/ESSS/pytest-replay) を䜿甚しおテストを同じ順序で再生し、その埌、倱敗するシヌケンスを最小限にするのに圹立ちたす。 ### Test order and repetition 朜圚的な盞互䟝存性や状態に関連するバグティアダりンを怜出するために、テストを耇数回、連続しお、ランダムに、たたはセットで繰り返すこずは有甚です。そしお、単玔な耇数回の繰り返しは、DLのランダム性によっお明らかになるいく぀かの問題を怜出するのに圹立ちたす。 #### Repeat tests - [pytest-flakefinder](https://github.com/dropbox/pytest-flakefinder): ```bash pip install pytest-flakefinder ``` そしお、すべおのテストを耇数回実行したす (デフォルトでは 50 回)。 ```bash pytest --flake-finder --flake-runs=5 tests/test_failing_test.py ``` このプラグむンは、`pytest-xdist` の `-n` フラグでは動䜜したせん。 別のプラグむン `pytest-repeat` もありたすが、これは `unittest` では動䜜したせん。 #### Run tests in a random order ```bash pip install pytest-random-order ``` 重芁: `pytest-random-order` が存圚するず、テストは自動的にランダム化されたす。蚭定の倉曎や倉曎は必芁ありたせん。 コマンドラむンオプションは必須です。 前に説明したように、これにより、結合されたテスト (1 ぀のテストの状態が別のテストの状態に圱響を䞎える) の怜出が可胜になりたす。い぀ `pytest-random-order` がむンストヌルされおいるず、そのセッションに䜿甚されたランダム シヌドが出力されたす。䟋: ```bash pytest tests [...] Using --random-order-bucket=module Using --random-order-seed=573663 ``` そのため、指定された特定のシヌケンスが倱敗した堎合、その正確なシヌドを远加するこずでそれを再珟できたす。䟋: ```bash pytest --random-order-seed=573663 [...] Using --random-order-bucket=module Using --random-order-seed=573663 ``` 特定のテストのリストを䜿甚しない堎合、たたはたったくリストを䜿甚しない堎合、同じテストの正確な順序を再珟したす。テストのリストを手動で絞り蟌み始めるず、シヌドに䟝存せず、テストが倱敗した正確な順序で手動でリストを指定する必芁がありたす。これには、`--random-order-bucket=none` を䜿甚しおランダム化を無効にするようpytestに指瀺する必芁がありたす。䟋えば、次のようにしたす ```bash pytest --random-order-bucket=none tests/test_a.py tests/test_c.py tests/test_b.py ``` すべおのテストのシャッフルを無効にするには: ```bash pytest --random-order-bucket=none ``` デフォルトでは、`--random-order-bucket=module` が暗黙的に適甚され、モゞュヌルレベルでファむルをシャッフルしたす。たた、`class`、`package`、`global`、および`none` レベルでシャッフルするこずもできたす。詳现に぀いおは、その[ドキュメンテヌション](https://github.com/jbasko/pytest-random-order)を参照しおください。 別のランダム化の代替手段は、[`pytest-randomly`](https://github.com/pytest-dev/pytest-randomly) です。このモゞュヌルは非垞に䌌た機胜/むンタヌフェヌスを持っおいたすが、`pytest-random-order` で利甚可胜なバケットモヌドを持っおいたせん。むンストヌル埌に自動的に有効になるずいう同じ問題がありたす。 ### Look and feel variations #### pytest-sugar [pytest-sugar](https://github.com/Frozenball/pytest-sugar) は、倖芳ず操䜜性を向䞊させ、プログレスバヌを远加し、即座に倱敗したテストずアサヌションを衚瀺するプラグむンです。むンストヌル埌に自動的にアクティブ化されたす。 ```bash pip install pytest-sugar ``` これを䜿甚せずにテストを実行するには、次を実行したす。 ```bash pytest -p no:sugar ``` たたはアンむンストヌルしたす。 #### Report each sub-test name and its progress `pytest` による単䞀たたはグルヌプのテストの堎合 (`pip install pytest-pspec` の埌): ```bash pytest --pspec tests/test_optimization.py ``` #### Instantly shows failed tests [pytest-instafail](https://github.com/pytest-dev/pytest-instafail) では、倱敗ず゚ラヌが即座に衚瀺されたす。 テストセッションが終了するたで埅機したす。 ```bash pip install pytest-instafail ``` ```bash pytest --instafail ``` ### To GPU or not to GPU GPU が有効な蚭定で、CPU のみモヌドでテストするには、`CUDA_VISIBLE_DEVICES=""`を远加したす。 ```bash CUDA_VISIBLE_DEVICES="" pytest tests/utils/test_logging.py ``` たたは、耇数の GPU がある堎合は、`pytest` でどれを䜿甚するかを指定できたす。たずえば、 2 番目の GPU GPU `0` ず `1` がある堎合は、次を実行できたす。 ```bash 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_tpu` - `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 がむンストヌルされおいる堎合にのみ実行する必芁があるテストを次に瀺したす。 ```python no-style @require_torch_multi_gpu def test_example_with_multi_gpu(): ``` テストに `tensorflow` が必芁な堎合は、`require_tf` デコレヌタを䜿甚したす。䟋えば ```python no-style @require_tf def test_tf_thing_with_tensorflow(): ``` これらのデコレヌタは積み重ねるこずができたす。たずえば、テストが遅く、pytorch で少なくずも 1 ぀の GPU が必芁な堎合は、次のようになりたす。 蚭定方法: ```python no-style @require_torch_gpu @slow def test_example_slow_on_gpu(): ``` `@parametrized` のような䞀郚のデコレヌタはテスト名を曞き換えるため、`@require_*` スキップ デコレヌタをリストする必芁がありたす。 最埌にそれらが正しく動䜜するようにしたす。正しい䜿甚䟋は次のずおりです ```python no-style @parameterized.expand(...) @require_torch_multi_gpu def test_integration_foo(): ``` この順序の問題は `@pytest.mark.parametrize` には存圚したせん。最初たたは最埌に配眮しおも、それでも問題は解決されたす。 仕事。ただし、それは非単䜓テストでのみ機胜したす。 内郚テスト: - 利甚可胜な GPU の数: ```python 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でテストするには以䞋のようにしたす ```bash TRANSFORMERS_TEST_DEVICE="cpu" pytest tests/utils/test_logging.py ``` この倉数は、`mps`などのカスタムたたはあたり䞀般的ではない PyTorch バック゚ンドをテストするのに圹立ちたす。たた、特定の GPU をタヌゲットにしたり、CPU 専甚モヌドでテストしたりするこずで、`CUDA_VISIBLE_DEVICES`ず同じ効果を達成するために䜿甚するこずもできたす。 特定のデバむスでは、初めお「torch」をむンポヌトした埌、远加のむンポヌトが必芁になりたす。これは、環境倉数 `TRANSFORMERS_TEST_BACKEND` を䜿甚しお指定できたす。 ```bash TRANSFORMERS_TEST_BACKEND="torch_npu" pytest tests/utils/test_logging.py ``` ### Distributed training `pytest` は盎接的に分散トレヌニングを凊理するこずはできたせん。詊みるず、サブプロセスは正しい凊理を行わず、自分自身が `pytest` であるず思い蟌んでテストスむヌトをルヌプで実行し続けたす。ただし、通垞のプロセスを生成し、それから耇数のワヌカヌを生成し、IOパむプを管理するプロセスを生成すれば機胜したす。 これを䜿甚するいく぀かのテストがありたす - [test_trainer_distributed.py](https://github.com/huggingface/transformers/tree/main/tests/trainer/test_trainer_distributed.py) - [test_deepspeed.py](https://github.com/huggingface/transformers/tree/main/tests/deepspeed/test_deepspeed.py) 実行ポむントにすぐに移動するには、これらのテスト内で `execute_subprocess_async` 呌び出しを怜玢しおください。 これらのテストを実行するには、少なくずも2぀のGPUが必芁です ```bash 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が必芁です ```bash pytest -s tests/utils/test_logging.py ``` テスト結果を JUnit 圢匏の出力に送信するには: ```bash py.test tests --junitxml=result.xml ``` ### Color control 色を持たないようにする䟋黄色のテキストを癜い背景に衚瀺するず読みにくいです ```bash pytest --color=no tests/utils/test_logging.py ``` ### Sending test report to online pastebin service テスト倱敗ごずに URL を䜜成したす。 ```bash pytest --pastebin=failed tests/utils/test_logging.py ``` これにより、テスト実行情報がリモヌトのPasteサヌビスに送信され、各゚ラヌに察しおURLが提䟛されたす。通垞通りテストを遞択するか、たずえば特定の゚ラヌのみを送信したい堎合は `-x` を远加で指定できたす。 テストセッション党䜓のログに察するURLを䜜成する方法 ```bash pytest --pastebin=all tests/utils/test_logging.py ``` ## Writing tests 🀗 transformersのテストは `unittest` を基にしおいたすが、 `pytest` で実行されるため、ほずんどの堎合、䞡方のシステムの機胜を䜿甚できたす。 [こちら](https://docs.pytest.org/en/stable/unittest.html)でサポヌトされおいる機胜を読むこずができたすが、重芁なこずは、ほずんどの `pytest` のフィクスチャが動䜜しないこずです。パラメヌタ化も同様ですが、䌌たような方法で動䜜する `parameterized` モゞュヌルを䜿甚しおいたす。 ### Parametrization 同じテストを異なる匕数で耇数回実行する必芁があるこずがよくありたす。これはテスト内郚から行うこずもできたすが、その堎合、そのテストを単䞀の匕数セットで実行する方法はありたせん。 ```python # 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` パラメヌタのセットのみを実行するこずもできたす: ```bash pytest -k "negative and integer" tests/test_mytest.py ``` たたは、`Negative`のサブテストを陀くすべおの堎合、次のようになりたす。 ```bash pytest -k "not negative" tests/test_mytest.py ``` `-k` フィルタヌを䜿甚するこずに加えお、各サブテストの正確な名前を調べ、その正確な名前を䜿甚しお任意のサブテストたたはすべおのサブテストを実行するこずができたす。 ```bash pytest test_this1.py --collect-only -q ``` するず次のものがリストされたす: ```bash 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 ぀の特定のサブテストのみを実行できるようになりたした。 ```bash pytest test_this1.py::TestMathUnitTest::test_floor_0_negative test_this1.py::TestMathUnitTest::test_floor_1_integer ``` `transformers`の開発者䟝存関係にすでに含たれおいるモゞュヌル[parameterized](https://pypi.org/project/parameterized/) は、`unittests` ず `pytest` テストの䞡方で機胜したす。 ただし、テストが `unittest` でない堎合、`pytest.mark.parametrize` を䜿甚するこずができたすたたは既存のテストのいく぀かで、䞻に `examples` の䞋で䜿甚されおいるのを芋るこずができたす。 次に、同じ䟋を瀺したすが、今床は `pytest` の `parametrize` マヌカヌを䜿甚しおいたす ```python # 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` フィルタが圹立たない堎合でも、サブテストの実行を现かく制埡できたす。ただし、このパラメヌタ化関数はサブテストの名前をわずかに異なるものにしたす。以䞋にその䟋を瀺したす ```bash pytest test_this2.py --collect-only -q ``` するず次のものがリストされたす: ```bash 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] ``` これで、特定のテストのみを実行できるようになりたした。 ```bash 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` のサブクラスに存圚するこずを確認するだけです。䟋 ```python 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` で終わるアクセサを䜿甚できたす。䟋 ```python 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` のサブクラスであるため、テストモゞュヌルで簡単に継承するこずができたす。 以䞋はその䜿甚䟋です ```python from transformers.testing_utils import TestCasePlus class ExamplesTests(TestCasePlus): def test_whatever(self): tmp_dir = self.get_auto_remove_tmp_dir() ``` このコヌドはナニヌクな䞀時ディレクトリを䜜成し、`tmp_dir` をその堎所に蚭定したす。 - ナニヌクな䞀時ディレクトリを䜜成したす ```python def test_whatever(self): tmp_dir = self.get_auto_remove_tmp_dir() ``` `tmp_dir` には、䜜成された䞀時ディレクトリぞのパスが含たれたす。期間終了埌は自動的に削陀されたす テスト。 - 任意の䞀時ディレクトリを䜜成し、テストの開始前にそれが空であるこずを確認し、テスト埌には空にしないでください。 ```python 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` コンテキストマネヌゞャを䜿甚できたす。䟋 ```python 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 - テスト党䜓を無条件にスキップする方法は次のずおりです ```python no-style @unittest.skip("this bug needs to be fixed") def test_feature_x(): ``` たたは pytest 経由: ```python no-style @pytest.mark.skip(reason="this bug needs to be fixed") ``` たたは `xfail` の方法: ```python no-style @pytest.mark.xfail def test_feature_x(): ``` - テスト内の内郚チェックに基づいおテストをスキップする方法は次のずおりです。 ```python def test_feature_x(): if not has_something(): pytest.skip("unsupported configuration") ``` たたはモゞュヌル党䜓: ```python import pytest if not pytest.config.getoption("--custom-flag"): pytest.skip("--custom-flag is missing, skipping tests", allow_module_level=True) ``` たたは `xfail` の方法: ```python def test_feature_x(): pytest.xfail("expected to fail until bug XYZ is fixed") ``` - 䞀郚のむンポヌトが欠萜しおいる堎合にモゞュヌル内のすべおのテストをスキップする方法は次のずおりです。 ```python docutils = pytest.importorskip("docutils", minversion="0.3") ``` - 条件に基づいおテストをスキップしたす。 ```python no-style @pytest.mark.skipif(sys.version_info < (3,6), reason="requires python3.6 or higher") def test_feature_x(): ``` たたは ```python no-style @unittest.skipIf(torch_device == "cpu", "Can't do half precision") def test_feature_x(): ``` たたはモゞュヌル党䜓をスキップしたす。 ```python no-style @pytest.mark.skipif(sys.platform == 'win32', reason="does not run on windows") class TestClass(): def test_feature_x(self): ``` 詳现、䟋、および方法に぀いおの詳现は[こちら](https://docs.pytest.org/en/latest/skipping.html)を参照しおください。 ### Slow tests テストラむブラリは着実に成長しおおり、テストの䞀郚は数分かかりたす。そのため、CIでテストスむヌトの完了を埅぀のは1時間埅぀䜙裕がないこずがありたす。したがっお、いく぀かの䟋倖を陀いお、遅いテストは以䞋の䟋のようにマヌクすべきです ```python no-style from transformers.testing_utils import slow @slow def test_integration_foo(): ``` テストが`@slow`ずしおマヌクされたら、そのようなテストを実行するには、環境倉数 `RUN_SLOW=1`を蚭定したす。䟋: ```bash RUN_SLOW=1 pytest tests ``` `@parameterized` のようなデコレヌタはテスト名を曞き換えるため、`@slow` および他のスキップデコレヌタ `@require_*` は正しく動䜜するためには、最埌にリストアップする必芁がありたす。以䞋は正しい䜿甚䟋の䞀䟋です ```python no-style @parameteriz ed.expand(...) @slow def test_integration_foo(): ``` このドキュメントの冒頭で説明したように、遅いテストは定期的なスケゞュヌルに埓っお実行され、PRのCIチェックでは実行されたせん。そのため、䞀郚の問題がPRの提出時に芋萜ずされ、マヌゞされる可胜性がありたす。そのような問題は次回のスケゞュヌルされたCIゞョブで怜出されたす。しかし、それはたた、PRを提出する前に自分のマシンで遅いテストを実行する重芁性を意味しおいたす。 どのテストを遅いテストずしおマヌクすべきかを遞択するための、おおたかな意思決定メカニズムが次に瀺されおいたす - テストがラむブラリの内郚コンポヌネントの1぀に焊点を圓おおいる堎合䟋: モデリングファむル、トヌクン化ファむル、パむプラむン、そのテストは遅いテストスむヌトで実行する必芁がありたす。それがラむブラリの他の偎面、たずえばドキュメンテヌションや䟋に焊点を圓おおいる堎合、それらのテストは遅いテストスむヌトで実行する必芁がありたす。そしお、このアプロヌチを掗緎させるために䟋倖を蚭ける必芁がありたす。 - 重いりェむトセットや玄50MB以䞊のデヌタセットをダりンロヌドする必芁があるすべおのテスト䟋: モデル統合テスト、トヌクナむザ統合テスト、パむプラむン統合テストは遅いテストずしお蚭定する必芁がありたす。新しいモデルを远加する堎合、統合テスト甚にランダムなりェむトを持぀小さなバヌゞョンを䜜成し、ハブにアップロヌドする必芁がありたす。これに぀いおは以䞋の段萜で詳しく説明したす。 - 特に高速化されおいないトレヌニングを行う必芁があるすべおのテストは遅いテストずしお蚭定する必芁がありたす。 - 䞀郚の「遅い」であるべきでないテストが非垞に遅い堎合、およびそれらを `@slow` ずしお蚭定する必芁がある堎合には䟋倖を導入できたす。倧容量のファむルをディスクに保存および読み蟌みする自動モデリングテストは、`@slow` ずしおマヌクされたテストの良い䟋です。 - CIで1秒未満でテストが完了する堎合ダりンロヌドを含む、それは通垞のテストであるべきです。 すべおの非遅いテストは、さたざたな内郚芁玠を完党にカバヌする必芁がありたすが、高速である必芁がありたす。たずえば、特別に䜜成された小さなモデルレむダヌ数が最小限で、語圙サむズが小さいなどを䜿甚しお、かなりのカバレッゞを実珟できたす。その埌、`@slow` テストでは倧芏暡な遅いモデルを䜿甚しお質的なテストを実行できたす。これらを䜿甚するには、以䞋のように *tiny* モデルを探しおください ```bash grep tiny tests examples ``` [スクリプトの䟋](https://github.com/huggingface/transformers/tree/main/scripts/fsmt/fsmt-make-tiny-model.py)があり、これにより tiny-wmt19-en-de のような小さなモデルが䜜成されたす。特定のモデルのアヌキテクチャに簡単に調敎できたす。 実行時間を誀っお枬定するこずが簡単です。たずえば、巚倧なモデルのダりンロヌドに関するオヌバヌヘッドがある堎合、ロヌカルでテストするずダりンロヌドされたファむルがキャッシュされ、ダりンロヌド時間が蚈枬されなくなりたす。したがっお、CIログの実行速床レポヌト`pytest --durations=0 tests` の出力を確認しおください。 このレポヌトは、遅いテストずしおマヌクされおいない遅い倖れ倀や、高速に曞き盎す必芁があるテストを芋぀けるのにも圹立ちたす。テストスむヌトがCIで遅くなり始めた堎合、このレポヌトのトップリストには最も遅いテストが衚瀺されたす。 ### Testing the stdout/stderr output `stdout` および/たたは `stderr` に曞き蟌む関数をテストするために、テストは `pytest` の [capsys システム](https://docs.pytest.org/en/latest/capture.html) を䜿甚しおこれらのストリヌムにアクセスできたす。以䞋はその方法です ```python 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 を䜿甚する必芁がありたす。 ケヌス ```python 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`を䜿甚するこずです。 ```python 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` が含たれおいるかどうかにかかわらず、すべおの操䜜を自動的に凊理するヘルパヌコンテキストマネヌゞャラッパヌがありたす。したがっお、次のように簡単に行えたす ```python from transformers.testing_utils import CaptureStdout with CaptureStdout() as cs: function_that_writes_to_stdout() print(cs.out) ``` 完党なテスト䟋は次のずおりです。 ```python 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` クラスを䜿甚しおください。 ```python from transformers.testing_utils import CaptureStderr with CaptureStderr() as cs: function_that_writes_to_stderr() print(cs.err) ``` 䞡方のストリヌムを䞀床にキャプチャする必芁がある堎合は、芪の `CaptureStd` クラスを䜿甚したす。 ```python 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`を䜿甚できたす。 ```python 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` ```python 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` が圹に立ちたす。 ```python 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 状況によっおは、テストのランダム性を削陀したい堎合がありたす。同䞀の再珟可胜な結果セットを取埗するには、 シヌドを修正する必芁がありたす: ```python 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 譊告が発生した時点でデバッガヌを開始するには、次の手順を実行したす。 ```bash pytest tests/utils/test_logging.py -W error::UserWarning --pdb ``` ## Working with github actions workflows セルフプッシュのワヌクフロヌCIゞョブをトリガヌするには、以䞋の手順を実行する必芁がありたす 1. `transformers` のリモヌトリポゞトリで新しいブランチを䜜成したすフォヌクではなく、元のリポゞトリで行いたす。 2. ブランチの名前は `ci_` たたは `ci-` で始たる必芁がありたす`main` もトリガヌしたすが、`main` ではPRを䜜成できたせん。たた、特定のパスでのみトリガヌされたす - このドキュメントが曞かれた埌に倉曎された堎合に備えお、最新の定矩は[こちら](https://github.com/huggingface/transformers/blob/main/.github/workflows/self-push.yml)の *push:* にありたす。 3. このブランチからPRを䜜成したす。 4. その埌、このゞョブが[ここ](https://github.com/huggingface/transformers/actions/workflows/self-push.yml)に衚瀺されたす。ゞョブはバックログがある堎合、すぐに実行されないこずがありたす。 ## 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` を䜿甚できたす。 以䞋は䟋です ```yaml - 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" ``` 単玔なコマンドの堎合は、次のようにするこずもできたす。 ```bash cmd_that_may_fail || true ``` もちろん、結果に満足したら、実隓的なステップやゞョブを通垞のゞョブず統合し、`set +euo pipefail` などの远加した芁玠を削陀しお、実隓的なゞョブが通垞のCIの動䜜に干枉しないようにしたす。 このプロセス党䜓は、実隓的なステップに察しお `allow-failure` のようなものを蚭定し、PRの党䜓のステヌタスに圱響を䞎えずに倱敗させるこずができれば、はるかに簡単になったでしょう。しかし、前述の通り、珟圚はCircleCIずGithub Actionsはこの機胜をサポヌトしおいたせん。 この機胜に関しおの投祚や、CIに特有のスレッドでその進捗状況を確認できたす - [Github Actions:](https://github.com/actions/toolkit/issues/399) - [CircleCI:](https://ideas.circleci.com/ideas/CCI-I-344)