Closed3
pytest の並列実行(pytest-xdist)
Python のバッチ系プログラムを書いていて、システムテストの一つ一つが長いためテストを並列実行できるようにしたくて調べていたところ、 pytest-xdist
が良さそうだったので導入してみた。
pytest-xdist
pytest は機能拡張にオープンでプラグインを作って簡単に機能追加ができます。
pytest のプラグインは PyPI に 963 個あるらしい。
pytest-xdist も pytest のプラグインでインストールするとオプション指定するだけで並列テストを実行できます。
インストール
pip コマンドでインストールできます。
pip install pytest-xdist
利用方法
3秒待って文字列を返す関数を 3つテストするテストケースを作ります。
test_sleep.py
import time
def sleep_three_sec():
time.sleep(3)
return "three sec sleeped"
def test_sleep_three_sec_1():
actual = sleep_three_sec()
assert actual == "three sec sleeped"
def test_sleep_three_sec_2():
actual = sleep_three_sec()
assert actual == "three sec sleeped"
def test_sleep_three_sec_3():
actual = sleep_three_sec()
assert actual == "three sec sleeped"
通常通り指定すると 9秒かかります。
$ pytest test_sleep.py
======================================= test session starts =======================================
platform darwin -- Python 3.9.13, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/fujimoto.shinji/Techs/python/python3-sandbox
plugins: xdist-2.5.0, forked-1.4.0
collected 3 items
test_sleep.py ... [100%]
======================================== 3 passed in 9.05s ========================================
3並列で実行すると 4秒で終わります(マルチプロセス起動してテストを振り分けるオーバーヘッドがあるっぽい)
pytest -n 3 test_sleep.py
======================================= test session starts =======================================
platform darwin -- Python 3.9.13, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/fujimoto.shinji/Techs/python/python3-sandbox
plugins: xdist-2.5.0, forked-1.4.0
gw0 [3] / gw1 [3] / gw2 [3]
... [100%]
======================================== 3 passed in 4.20s ========================================
非常に簡単です。テスト実装は一切変更する必要なく、pytest の実行オプションを指定するだけで並列テストを実現できました。
オプション
pytest-xdist
をインストールすることで以下がオプションに追加されます。
$ pytest --help
...
distributed and subprocess testing:
-n numprocesses, --numprocesses=numprocesses
Shortcut for '--dist=load --tx=NUM*popen'. With 'auto', attempt to detect
physical CPU count. With 'logical', detect logical CPU count. If physical
CPU count cannot be found, falls back to logical count. This will be 0 when
used with --pdb.
--maxprocesses=maxprocesses
limit the maximum number of workers to process the tests when using
--numprocesses=auto
--max-worker-restart=MAXWORKERRESTART
maximum number of workers that can be restarted when crashed (set to zero
to disable this feature)
--dist=distmode set mode for distributing tests to exec environments.
each: send each test to all available environments.
load: load balance by sending any pending test to any available
environment.
loadscope: load balance by sending pending groups of tests in the same
scope to any available environment.
loadfile: load balance by sending test grouped by file to any available
environment.
loadgroup: like load, but sends tests marked with 'xdist_group' to the same
worker.
(default) no: run tests inprocess, don't distribute.
--tx=xspec add a test execution environment. some examples: --tx
popen//python=python2.5 --tx socket=192.168.1.102:8888 --tx
ssh=user@codespeak.net//chdir=testcache
-d load-balance tests. shortcut for '--dist=load'
--rsyncdir=DIR add directory for rsyncing to remote tx nodes.
--rsyncignore=GLOB add expression for ignores when rsyncing to remote tx nodes.
--boxed backward compatibility alias for pytest-forked --forked
--testrunuid=TESTRUNUID
provide an identifier shared amongst all workers as the value of the
'testrun_uid' fixture,
,if not provided, 'testrun_uid' is filled with a new unique string on every
test run.
-f, --looponfail run tests in subprocess, wait for modified files and re-run failing test
set until all pass.
-n numprocesses, --numprocesses=numprocesses
並列数(起動するプロセス数)の指定です。
テスト実行環境の CPU コア数、テストの負荷次第で指定します。
今回の私の利用方法ではテスト実行環境が 2 CPU コアですが、外部処理がメインなため、8並列で実行しています。
--dist=distmode
テストケースの分散方法の指定です。
指定値 | 挙動 |
---|---|
each | すべての環境にすべてのテストを送信します(使い道がわからない) |
load | テストケースレベルで分散します |
loadscope | テストモジュール、テストクラスレベルで分散します 同じクラスのテストケースは同じ環境で実行することを保証します |
loadfile | テストファイルレベルで分散します 同じファイルのテストケースは同じ環境で実行することを保証します |
loadgroup | 任意のテストケースをグループ化して分散します グループ指定しないテストケースは load と同じ挙動です |
このスクラップは2022/05/24にクローズされました