Как остановить все тесты внутри теста или установки с помощью unittest?
я расширяю python 2.7 unittest
framework для тестирования некоторых функций. Одна из вещей, которую я хотел бы сделать, это остановить все тесты от запуска внутри теста и внутри setUpClass()
метод. Иногда, если тест терпит неудачу, программа настолько сломана, что больше нет смысла продолжать тестирование, поэтому я хочу остановить тесты от запуска.
Я заметил, что TestResult имеет и stop()
метод, но я не уверен, как получить доступ к этому внутри испытания.
у кого-нибудь есть идеи? Есть ли лучший способ?
6 ответов
в случае, если вы заинтересованы, вот простой пример, как вы могли принять решение о выходе из тестов чисто с py.тест:
# content of test_module.py
import pytest
counter = 0
def setup_function(func):
global counter
counter += 1
if counter >=3:
pytest.exit("decided to stop the test run")
def test_one():
pass
def test_two():
pass
def test_three():
pass
и если вы запустите это, вы получите:
$ pytest test_module.py
============== test session starts =================
platform linux2 -- Python 2.6.5 -- pytest-1.4.0a1
test path 1: test_module.py
test_module.py ..
!!!! Exit: decided to stop the test run !!!!!!!!!!!!
============= 2 passed in 0.08 seconds =============
вы также можете поставить py.test.exit()
вызов внутри теста или в плагин для конкретного проекта.
Sidenote:py.test
поддерживает py.test --maxfail=NUM
реализовать остановку после сбоев NUM.
Sidenote2:py.test
имеет лишь ограниченное поддержка запуска тестов в традиционном unittest.TestCase
стиль.
вот еще один ответ, который я придумал через некоторое время:
во-первых, я добавил новое исключение:
class StopTests(Exception):
"""
Raise this exception in a test to stop the test run.
"""
pass
затем я добавил новый assert
моему ребенку тестовый класс:
def assertStopTestsIfFalse(self, statement, reason=''):
try:
assert statement
except AssertionError:
result.addFailure(self, sys.exc_info())
и последний раз я переехал run
функция для включения этого прямо под testMethod()
звоните:
except StopTests:
result.addFailure(self, sys.exc_info())
result.stop()
мне это нравится больше, так как любой тест теперь имеет возможность остановить все тесты, и нет кода cpython.
в настоящее время вы можете остановить тесты только на уровне пакета. Как только вы находитесь в TestCase
, the stop()
метод TestResult
не используется при повторении тестов.
несколько связано с вашим вопросом, если вы используете python 2.7, вы можете использовать -f/--failfast
флаг при вызове теста с python -m unittest
. Это остановит тест при первой неудаче.
посмотреть 25.3.2.1. параметры командной строки failfast, catch и buffer
вы можете также рассмотрите возможность использования нос чтобы запустить тесты и использовать -x, --stop
флаг чтобы остановить тест рано.
в тестовом цикле unittest.TestSuite
, есть break
условие на старте:
class TestSuite(BaseTestSuite):
def run(self, result, debug=False):
topLevel = False
if getattr(result, '_testRunEntered', False) is False:
result._testRunEntered = topLevel = True
for test in self:
if result.shouldStop:
break
поэтому я использую пользовательский набор тестов, как это:
class CustomTestSuite(unittest.TestSuite):
""" This variant registers the test result object with all ScriptedTests,
so that a failed Loign test can abort the test suite by setting result.shouldStop
to True
"""
def run(self, result, debug=False):
for test in self._tests:
test.result = result
return super(CustomTestSuite, self).run(result, debug)
с пользовательским классом результатов теста, как это:
class CustomTestResult(TextTestResult):
def __init__(self, stream, descriptions, verbosity):
super(CustomTestResult, self).__init__(stream, descriptions, verbosity)
self.verbosity = verbosity
self.shouldStop = False
и мои тестовые классы как:
class ScriptedTest(unittest.TestCase):
def __init__(self, environment, test_cfg, module, test):
super(ScriptedTest, self).__init__()
self.result = None
при определенных условиях я затем прерываю набор тестов; например, набор тестов начинается с входа в систему, и если это не удается, мне не нужно пробовать остальное:
try:
test_case.execute_script(test_command_list)
except AssertionError as e:
if test_case.module == 'session' and test_case.test == 'Login':
test_case.result.shouldStop = True
raise TestFatal('Login failed, aborting test.')
else:
raise sys.exc_info()
Затем Я используйте набор тестов следующим образом:
suite = CustomTestSuite()
self.add_tests(suite)
result = unittest.TextTestRunner(verbosity=self.environment.verbosity, stream=UnitTestLoggerStream(self.logger),
resultclass=CustomTestResult).run(suite)
Я не уверен, если есть лучший способ сделать это, но он ведет себя правильно для моих тестов.
Я посмотрел на TestCase
class и решил подкласс его. Класс просто переопределяет run()
. Я скопировал метод и, начиная с строки 318 в исходном классе, добавил следующее:
# this is CPython specific. Jython and IronPython may do this differently
if testMethod.func_code.co_argcount == 2:
testMethod(result)
else:
testMethod()
у него есть определенный код CPython, чтобы сказать, Может ли метод тестирования принять другой параметр, но поскольку я использую CPython везде, это не проблема для меня.
хотя вы не получите обычные отчеты о тестах, выполненных до сих пор, очень простой способ остановить тестовый запуск из TestCase
метод просто поднять KeyboardInterrupt
внутри метода.
вы можете видеть, как только KeyboardInterrupt
разрешено пузыриться внутри unittest
тестовый бегун, глядя на код CPython здесь внутри testPartExecutor()
.