私は知っているpytest-timeout
テストケースごとにtiemoutを指定できますが、1回の失敗でテストケース全体が終了し、テストケースがスラックしません。pytest-timeout - テスト全体を終了する代わりにテストを失敗する
私は自分自身でこれを解決する必要がありますか、それを提供するすぐに使えるツールがありますか?
私は知っているpytest-timeout
テストケースごとにtiemoutを指定できますが、1回の失敗でテストケース全体が終了し、テストケースがスラックしません。pytest-timeout - テスト全体を終了する代わりにテストを失敗する
私は自分自身でこれを解決する必要がありますか、それを提供するすぐに使えるツールがありますか?
私はずっと前にこの問題を検討していましたが、自己解決の方が良いとの結論に達しました。
私のプラグインはpytestプロセス全体を終了させていましたが、単一の(現在の)テストだけが失敗するように調整することができます。ここでは、調整案されて:あなたは、各試験時間が原因プリセットアラームに個別kill -ALRM $pid
場合、またはを行うと、唯一の現在のテストは
import pytest
import signal
class Termination(SystemExit):
pass
class TimeoutExit(BaseException):
pass
def _terminate(signum, frame):
raise Termination("Runner is terminated from outside.")
def _timeout(signum, frame):
raise TimeoutExit("Runner timeout is reached, runner is terminating.")
@pytest.hookimpl
def pytest_addoption(parser):
parser.addoption(
'--timeout', action='store', dest='timeout', type=int, default=None,
help="number of seconds before each test failure")
@pytest.hookimpl
def pytest_configure(config):
# Install the signal handlers that we want to process.
signal.signal(signal.SIGTERM, _terminate)
signal.signal(signal.SIGALRM, _timeout)
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item, nextitem):
# Set the per-test timeout (an alarm signal).
if item.config.option.timeout is not None:
signal.alarm(item.config.option.timeout)
try:
# Run the setup, test body, and teardown stages.
yield
finally:
# Disable the alarm when the test passes or fails.
# I.e. when we get into the framework's body.
signal.alarm(0)
失敗しますが、他のテストは継続されます。
このTimeoutExit
は、BaseException
から継承されているため、except Exception: pass
のライブラリでは表示されません。
したがって、この側面ではSystemExit
です。しかし、SystemExit
またはKeyboardInterruption
とは異なり、pytestはそれをキャッチせず、そのような例外で終了しません。
time.sleep(...)
(信号のように)を行っても、アラームの瞬間にテストが実行されるどこにでも例外が注入されます。
プロセスには1つのアラーム(OS制限)しか設定できないことに注意してください。また、同じ目的でALRM信号も使用するため、pytest-timeout
と互換性がありません。
&テストごとのタイムアウトを設定する場合は、スマートアラームマネージャを実装する必要があります。スマートアラームマネージャは、ほとんどのアラームを追跡し、OSアラームを最も早く設定し、アラーム信号が受信されます。場合
、あなたがkill -TERM $pid
またはちょうどkill $pid
(優雅な終了を)やる、それが直ちに終了されます - それはBaseException
であり、通常のコードまたはpytestでキャッチされていないSystemExit
から継承するため。
後者のケースは、異なる反応をさまざまな信号に設定する方法の大部分を示しています。 USR1 & USR2と他のキャッチ可能な信号でも同様のことができます。クイックテストについて
、conftest.py
ファイル(擬似プラグイン)に上記プラグインコードを置きます。
このテストファイル考えてみましょう:タイムアウトなしpytestを実行
import time
def test_this():
try:
time.sleep(10)
except Exception:
pass
def test_that():
pass
は何もしない、との両方のテストに合格:タイムアウトでそれを実行する
$ pytest -s -v
.........
collected 2 items
test_me.py::test_this PASSED
test_me.py::test_that PASSED
======= 2 passed in 10.02 seconds =======
は最初のテストに失敗しますが、2番目に合格します1つ:
$ pytest -s -v --timeout=5
.........
collected 2 items
test_me.py::test_this FAILED
test_me.py::test_that PASSED
============== FAILURES ==============
______________ test_this _____________
def test_this():
try:
> time.sleep(10)
test_me.py:5:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
signum = 14, frame = <frame object at 0x106b3c428>
def _timeout(signum, frame):
> raise TimeoutExit("Runner timeout is reached, runner is terminating.")
E conftest.pytest_configure.<locals>.TimeoutExit: Runner timeout is reached, runner is terminating.
conftest.py:24: TimeoutExit
======= 1 failed, 1 passed in 5.11 seconds =======
私は時間があったとすれば、実装の詳細を深く掘り下げるとは思いませんが、これはiです本当に啓発です!私はそれを参考にしておきます。 – JCode