0

Как узнать время, затраченное на каждый тест при использовании unittest?

11

Unittest отображает только общее время, затраченное на выполнение всех тестов, но не предоставляет информации о времени, затраченном на каждый отдельный тест.

Как можно добавить время выполнения каждого теста при использовании unittest?

5 ответ(ов)

0

Судя по всему, реализовать это на данный момент невозможно: https://github.com/python/cpython/issues/48330.

Тем не менее, вы можете сделать что-то подобное:

import unittest
import time

class SomeTest(unittest.TestCase):
    def setUp(self):
        self.startTime = time.time()
    
    def tearDown(self):
        t = time.time() - self.startTime
        print('%s: %.3f' % (self.id(), t))
        
    def testOne(self):
        time.sleep(1)
        self.assertEqual(int('42'), 42)
    
    def testTwo(self):
        time.sleep(2)
        self.assertEqual(str(42), '42')

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(SomeTest)
    unittest.TextTestRunner(verbosity=0).run(suite)

Результат будет таким:

__main__.SomeTest.testOne: 1.001
__main__.SomeTest.testTwo: 2.002
----------------------------------------------------------------------
Ran 2 tests in 3.003s

OK

Таким образом, вы можете измерять время выполнения тестов, используя методы setUp и tearDown.

0

Вот вариант скрипта из ответа horejsek. Он будет изменять поведение Django TestCase так, что каждый тест будет выводить общее время выполнения.

Вы можете разместить этот скрипт в __init__.py вашего корневого пакета, где находится settings.py. После этого вы можете запускать тесты с помощью команды ./manage.py test -s.

from django import test
import time

@classmethod
def setUpClass(cls):
    cls.startTime = time.time()

@classmethod
def tearDownClass(cls):
    print("\n%s.%s: %.3f" % (cls.__module__, cls.__name__, time.time() - cls.startTime))

test.TestCase.setUpClass = setUpClass
test.TestCase.tearDownClass = tearDownClass

Обратите внимание, что в данной реализации используется print, чтобы вывести результат в консоль после завершения теста. Убедитесь, что вы используете Python 3, так как синтаксис print изменился.

0

Решение только с использованием командной строки:

  1. Установите nose (популярный альтернативный тест-раннер) и расширение pinocchio:
$ pip install nose pinocchio
  1. Запустите тесты с записью времени (временные метрики будут сохранены в файл .nose-stopwatch-times):
$ nosetests --with-stopwatch
  1. Отобразите имена тестов, отсортированные по убыванию времени:
$ python -c "import pickle,operator,signal; signal.signal(signal.SIGPIPE, signal.SIG_DFL); print '\n'.join(['%.03fs: %s'%(v[1],v[0]) for v in sorted(pickle.load(open('.nose-stopwatch-times','r')).items(), key=operator.itemgetter(1), reverse=True)])" | less
0

Вы правы, использование time.perf_counter() вместо time.time() действительно может быть более точным для измерения времени выполнения. time.perf_counter() предоставляет более высокую разрешающую способность и предназначен для измерения времени, что делает его более подходящим для этой задачи.

Ваши примеры отлично иллюстрируют это. Разница в измерениях действительно незначительна в данном случае, но в некоторых ситуациях, особенно в высокочувствительных приложениях, такая точность может иметь значение.

Более того, ваш декоратор для измерения времени выполнения функций выглядит очень полезным. Он позволяет легко отслеживать время выполнения различных функций и может стать хорошей практикой для тестирования производительности. Использование time.perf_counter() внутри вашего декоратора также гарантирует, что вы будете получать наиболее точные результаты:

def time_func(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__}: {end - start:.3}s")
        return result
    return wrapper

Наконец, если вы хотите использовать этот декорирующий метод в тестах, как вы сделали в вашем классе TestCase, это может значительно упростить мониторинг производительности тестов. Это решение может быть полезно для всех, кто хочет улучшить точность своих измерений времени выполнения и следить за тем, как изменения в коде влияют на производительность.

0

unittest теперь поддерживает измерение времени выполнения тестов на миллисекунды с помощью опции --durations 0. Эта функция позволяет вам видеть, какие тесты выполняются дольше всего, и может помочь в оптимизации кода.

Вы можете запустить тесты с этой опцией следующим образом:

$ python -m unittest Lib.test.test_ftplib --durations 0

После выполнения команды вы увидите вывод, который включает список наиболее медленных тестов вместе с их временем выполнения. Например:

Slowest test durations
----------------------------------------------------------------------
0.000s     test__all__ (Lib.test.test_ftplib.MiscTestCase)
0.002s     test_pwd (Lib.test.test_ftplib.TestFTPClass)
...
1.281s     test_mlsd (Lib.test.test_ftplib.TestTLS_FTPClassMixin)

В этом примере всего было выполнено 88 тестов за 5.396 секунд, и один из тестов был пропущен. Как видно, самый долгий тест занял 1.281 секунды, что может быть сигналом для оптимизации.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь