Как остановить все тесты изнутри теста или настройки, используя Unittest?

StackOverflow https://stackoverflow.com/questions/3806695

Вопрос

Я расширяю Python 2.7 unittest Рамки для выполнения некоторого тестирования функций. Одна из вещей, которые я хотел бы сделать, это остановить все тесты, бегающие внутри теста, а внутри setUpClass() метод. Иногда, если тест терпит неудачу, программа настолько сломана, это больше не имеет никакого использования для продолжения тестирования, поэтому я хочу остановить пробег тестов.

Я заметил, что TestResult имеет shouldStop атрибут и stop() Метод, но я не уверен, как получить доступ к этому внутри теста.

У кого-нибудь есть идеи? Есть ли способ лучше?

Это было полезно?

Решение 2

Вот еще один ответ, с которым я пришел через некоторое время:

Во-первых, я добавил новый исключение:

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()

Мне это нравится, так как любой тест теперь имеет возможность остановить все тесты, и нет CPY-специфического кода.

Другие советы

Если вы заинтересованы, вот простой пример того, как вы могли бы принять решение о выходе в тестовой набор. пишет:

# 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() Вызов внутри теста или в плагин, специфичный проект.

Примечание: py.test родом поддерживает py.test --maxfail=NUM реализовать остановку после сбоев Num.

Sidenote2: py.test имеет только ограниченную поддержку для беговых испытаний в традиционном unittest.TestCase стиль.

В настоящее время вы можете остановить только тесты на уровне набора. Как только вы находитесь в TestCase, то stop() метод для TestResult не используется при итерации через тесты.

Несколько связан с вашим вопросом, если вы используете Python 2.7, вы можете использовать -f/--failfast Флаг при вызове вашего теста с python -m unittest. Отказ Это остановит тест по первой неудаче.

Видеть 25.3.2.1. Опции командной строки Failfaff, Catch и Buffer

Вы также можете рассмотреть вопрос Нос Чтобы запустить свои тесты и использовать -x, --stop флаг остановить тест рано.

В тестовой петле unittest.TestSuite, Eсть 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 Класс и решил подклассно это. Класс просто переопределяет run(). Отказ Я скопировал метод и начиная с линии 318 в исходном классе, добавил это:

# this is CPython specific. Jython and IronPython may do this differently
if testMethod.func_code.co_argcount == 2:
    testMethod(result)
else:
    testMethod()

В нем есть какой-то код CPY-CEMPHON, чтобы сказать, может ли метод теста принять другой параметр, но поскольку я использую CPYthon везде, это не проблема для меня.

Хотя вы не получите обычные тестовые отчеты о прогонах тестов, очень простой способ остановить тестовый прогон из TestCase Метод просто поднять KeyboardInterrupt внутри метода.

Вы можете увидеть, как только KeyboardInterrupt разрешено пузыми внутрь unittestТестовый бегун, глядя на код Cpython здесь внутри testPartExecutor().

Использовать:

if condition: 
   return 'pass'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top