Как работать с exitcode'ами в subprocess.run()?

У меня есть структура тестового фреймворка

test_1.py
test_2.py
...
test_N.py

Каждый файл - отдельный независимый тест. Я хочу отдебажить один нестабильный тест. Для этого мне нужно прогнать его 200 раз подряд, чтобы выловить всего слабые места и падения. Дабы не делать этого руками я пишу скрипт.

import subprocess


qty = 200
command = 'pytest'
test = 'test_name.py'

for _ in range(qty):
    subprocess.run([command, test])

Всё работает ровно и прекрасно, но есть нюансы. При таком подходе мне приходится всё это время смотреть в экран и наблюдать экзекьюшен теста раз за разом в течение N минут. Я решал написать небольшой "каунтер" для пройденных и упавших тестов.

import subprocess


qty = 200
command = 'pytest'
test = 'test_name.py'
PASS = 0
FAIL = 0

for _ in range(qty):
    try:
        subprocess.run([command, test])
        PASS = PASS + 1
    except: 
        FAIL = FAIL + 1


print(f'PASSED: {PASS}; FAILED: {FAIL}')

Но, по всей видимости, при падении теста возвращается не исключение, так как при любом проходе теста (пасс или фейл), каунтер FAILED показывал 0. Пытался явно прописывать except AssertionError, но результат тот же.

Подозреваю, что при данном подходе (когда 1 тест = 1 файл), каждый скрипт запускается отдельно друг за другом (пусть и в цикле), так что ловить нужно никакое не исключение, а просто хендлить exitcode. Если 0, то тест прошёл, если НЕ 0, значит тест упал. Но никак не могу придумать, как это сделать и впихнуть в свой небольшой скрипт для дебага.


Ответы (1 шт):

Автор решения: CrazyElf

If check is true, and the process exits with a non-zero exit code, a CalledProcessError exception will be raised. Attributes of that exception hold the arguments, the exit code, and stdout and stderr if they were captured.

Если я правильно понял документацию, чтобы выбросилось исключение при не нулевом exit code, нужно передать параметр check=True:

subprocess.run([command, test], check=True)
                                ^^^^^^^^^^

Из доки по pytest понятно, что действительно exit code равный 0 означает, что все тесты прошли успешно:

Running pytest can result in six different exit codes:

Exit code 0
All tests were collected and passed successfully

Exit code 1
Tests were collected and run but some of the tests failed

Exit code 2
Test execution was interrupted by the user

Exit code 3
Internal error happened while executing tests

Exit code 4
pytest command line usage error

Exit code 5
No tests were collected
→ Ссылка