Вывод данных из юнит-теста в python - PullRequest
104 голосов
/ 12 ноября 2008

Если я пишу юнит-тесты на python (используя модуль unittest), возможно ли вывести данные из неудачного теста, чтобы я мог проверить их, чтобы определить, что вызвало ошибку? Мне известна возможность создания настраиваемого сообщения, которое может содержать некоторую информацию, но иногда вы можете иметь дело с более сложными данными, которые не могут быть легко представлены в виде строки.

Например, предположим, что у вас есть класс Foo, и вы тестировали панель методов, используя данные из списка с именем testdata:

class TestBar(unittest.TestCase):
    def runTest(self):
        for t1, t2 in testdata:
            f = Foo(t1)
            self.assertEqual(f.bar(t2), 2)

Если проверка не удалась, я мог бы захотеть вывести t1, t2 и / или f, чтобы понять, почему именно эти данные привели к ошибке. Под выводом я подразумеваю доступ к переменным, как и к любым другим переменным, после запуска теста.

Ответы [ 14 ]

1 голос
/ 13 сентября 2013

inspect.trace позволит вам получить локальные переменные после возникновения исключения. Затем вы можете обернуть модульные тесты декоратором, подобным следующему, чтобы сохранить эти локальные переменные для проверки во время вскрытия.

import random
import unittest
import inspect


def store_result(f):
    """
    Store the results of a test
    On success, store the return value.
    On failure, store the local variables where the exception was thrown.
    """
    def wrapped(self):
        if 'results' not in self.__dict__:
            self.results = {}
        # If a test throws an exception, store local variables in results:
        try:
            result = f(self)
        except Exception as e:
            self.results[f.__name__] = {'success':False, 'locals':inspect.trace()[-1][0].f_locals}
            raise e
        self.results[f.__name__] = {'success':True, 'result':result}
        return result
    return wrapped

def suite_results(suite):
    """
    Get all the results from a test suite
    """
    ans = {}
    for test in suite:
        if 'results' in test.__dict__:
            ans.update(test.results)
    return ans

# Example:
class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.seq = range(10)

    @store_result
    def test_shuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))
        # should raise an exception for an immutable sequence
        self.assertRaises(TypeError, random.shuffle, (1,2,3))
        return {1:2}

    @store_result
    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)
        return {7:2}

    @store_result
    def test_sample(self):
        x = 799
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)
        return {1:99999}


suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity=2).run(suite)

from pprint import pprint
pprint(suite_results(suite))

В последней строке будут напечатаны возвращенные значения, где тест прошел успешно, и локальные переменные, в данном случае x, если он не пройден:

{'test_choice': {'result': {7: 2}, 'success': True},
 'test_sample': {'locals': {'self': <__main__.TestSequenceFunctions testMethod=test_sample>,
                            'x': 799},
                 'success': False},
 'test_shuffle': {'result': {1: 2}, 'success': True}}

Har det Gøy: -)

0 голосов
/ 27 августа 2015

Признавая, что я не пробовал, функция ведения журнала testfixtures выглядит весьма полезной ...

0 голосов
/ 23 октября 2013

Расширение @ F.C. ответ, это работает довольно хорошо для меня:

class MyTest(unittest.TestCase):
    def messenger(self, message):
        try:
            self.assertEqual(1, 2, msg=message)
        except AssertionError as e:      
            print "\nMESSENGER OUTPUT: %s" % str(e),
0 голосов
/ 12 ноября 2008

Как насчет перехвата исключения, которое генерируется из-за ошибки подтверждения? В вашем блоке catch вы можете выводить данные так, как вам угодно. Затем, когда вы закончите, вы можете повторно выдать исключение. Бегун теста, вероятно, не будет знать разницу.

Отказ от ответственности: я не пробовал это с платформой модульного тестирования python, но имел с другими платформами модульного тестирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...