Почему модуль cProfile не работает с unittest?
Я хотел бы использовать модуль cProfile для профилирования моих модульных тестов. Но когда я запускаю
python -mcProfile mytest.py
Я получил "Ran 0 тестов в 0.000s". Вот исходный код mytest.py
import unittest
class TestBasic(unittest.TestCase):
def testFoo(self):
assert True == True
if __name__ == '__main__':
unittest.main()
Я тестировал и другие более сложные unittests. Всегда получал "Ran 0 tests", если я запускаю его с помощью cProfile. Пожалуйста, помогите.
ОБНОВЛЕНИЕ: Моя ОС - MacOS 10.7 со встроенным python 2.7. Тот же код работает правильно на ubuntu.
Ответы
Ответ 1
Вы должны инициализировать cProfiler в конструкторе теста и использовать данные профиля в деструкторе - я использую его следующим образом:
from pstats import Stats
import unittest
class TestSplayTree(unittest.TestCase):
"""a simple test"""
def setUp(self):
"""init each test"""
self.testtree = SplayTree (1000000)
self.pr = cProfile.Profile()
self.pr.enable()
print "\n<<<---"
def tearDown(self):
"""finish any test"""
p = Stats (self.pr)
p.strip_dirs()
p.sort_stats ('cumtime')
p.print_stats ()
print "\n--->>>"
def xtest1 (self):
pass
В случае, если тест ожидает ввода, необходимо вызвать self.pr.disable()
перед этим вызовом и снова включить его.
Ответ 2
Я не уверен, почему, но явное создание и запуск набора тестов, кажется, работает. Я добавил time.sleep(2)
, чтобы показать что-то определенное в статистике.
import time
import unittest
class TestBasic(unittest.TestCase):
def testFoo(self):
time.sleep(2)
assert True == True
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestBasic)
unittest.TextTestRunner(verbosity=2).run(suite)
Работая в bash, сохраняя только первые 10 строк, мы видим, что {time.sleep}
был самым длинным вызовом:
~ $ python -m cProfile -s tottime so.py | head -n10
testFoo (__main__.TestBasic) ... ok
----------------------------------------------------------------------
Ran 1 test in 2.003s
OK
1084 function calls (1072 primitive calls) in 2.015 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1 2.003 2.003 2.003 2.003 {time.sleep}
1 0.002 0.002 0.003 0.003 case.py:1(<module>)
1 0.002 0.002 0.003 0.003 collections.py:11(<module>)
1 0.001 0.001 2.015 2.015 so.py:1(<module>)
1 0.001 0.001 0.010 0.010 __init__.py:45(<module>)