PyUnit: остановить после первого неудачного теста? - PullRequest
10 голосов
/ 26 марта 2009

Я использую следующий код в моей среде тестирования:

testModules = ["test_foo", "test_bar"]

suite = unittest.TestLoader().loadTestsFromNames(testModules)
runner = unittest.TextTestRunner(sys.stdout, verbosity=2)
results = runner.run(suite)
return results.wasSuccessful()

Есть ли способ заставить отчет (runner.run?) Прерваться после первого сбоя, чтобы предотвратить чрезмерное многословие?

Ответы [ 4 ]

7 голосов
/ 26 июля 2018

Спустя девять лет после того, как вопрос был задан, это по-прежнему один из лучших результатов поиска для "модульного теста python, который рано не пройден", и, как я обнаружил, просматривая другие результаты поиска, эти ответы больше не соответствуют последним версии модуля unittest.

Документация для модуля unittest https://docs.python.org/3/library/unittest.html#command-line-options и https://docs.python.org/2.7/library/unittest.html#command-line-options показывает, что существует аргумент failfast = True, который можно добавить в unittest.main или, что то же самое, параметр командной строки, - f или --failfast, чтобы остановить тестовый запуск при первой ошибке или сбое. Эта опция была добавлена ​​в версии 2.7. Использовать эту опцию намного проще, чем ранее необходимые обходные пути, предложенные в других ответах.

То есть просто поменяйте

unittest.main()

до

unittest.main(failfast=True)
6 голосов
/ 27 марта 2009

Исходя из указаний Евгения, я придумал следующее:

class TestCase(unittest.TestCase):  
    def run(self, result=None):
        if result.failures or result.errors:
            print "aborted"
        else:
            super(TestCase, self).run(result)

Хотя это работает довольно хорошо, немного раздражает, что каждый отдельный тестовый модуль должен определить, хочет ли он использовать этот пользовательский класс или класс по умолчанию (параметр командной строки, аналогично py.test '--exitfirst было бы идеально) ...

5 голосов
/ 26 марта 2009

Это особенность. Если вы хотите переопределить это, вам нужно создать подкласс TestCase и / или TestSuite классов и переопределить логику в методе run().

P.S .: Я думаю, вы должны создать подкласс unittest.TestCase и переопределить метод run() в вашем классе:

def run(self, result=None):
    if result is None: result = self.defaultTestResult()
    result.startTest(self)
    testMethod = getattr(self, self._testMethodName)
    try:
        try:
            self.setUp()
        except KeyboardInterrupt:
            raise
        except:
            result.addError(self, self._exc_info())
            return

        ok = False
        try:
            testMethod()
            ok = True
        except self.failureException:
            result.addFailure(self, self._exc_info())
            result.stop()
        except KeyboardInterrupt:
            raise
        except:
            result.addError(self, self._exc_info())
            result.stop()

        try:
            self.tearDown()
        except KeyboardInterrupt:
            raise
        except:
            result.addError(self, self._exc_info())
            ok = False
        if ok: result.addSuccess(self)
    finally:
        result.stopTest(self)

(я добавил два result.stop() вызова к определению по умолчанию run).

Тогда вам придется изменить все ваши тестовые сценарии, чтобы они стали подклассами этого нового класса вместо unittest.TestCase.

ПРЕДУПРЕЖДЕНИЕ : я не проверял этот код. :)

0 голосов
/ 13 июля 2012

Опираясь на ответ AnC, это то, что я использую ...

def aborting_run(self, result=None):
    if result.failures or result.errors:
        print "aborted"
    else:
        original_run(self, result)
original_run = unittest.TestCase.run
unittest.TestCase.run = aborting_run
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...