Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cProfile module doesn't work with unittest?

Tags:

I would to use cProfile module to profile my unit tests. But when I run

python -mcProfile mytest.py 

I got 'Ran 0 tests in 0.000s'. Here is the source code of mytest.py

import unittest  class TestBasic(unittest.TestCase):     def testFoo(self):         assert True == True  if __name__ == '__main__':     unittest.main() 

I've tested with other more complex unittests as well. Always got 'Ran 0 tests' if I run it with cProfile. Please help.

UPDATE: My OS is MacOS 10.7 with built-in python 2.7. The same code works properly on ubuntu.

like image 898
Ryan Ye Avatar asked Jul 25 '12 08:07

Ryan Ye


People also ask

Is Pytest compatible with unittest?

pytest supports running Python unittest -based tests out of the box. It's meant for leveraging existing unittest -based test suites to use pytest as a test runner and also allow to incrementally adapt the test suite to take full advantage of pytest's features.

What is the cProfile module used for?

Python includes a built-in module called cProfile which is used to measure the execution time of a program. The cProfiler module provides all information about how long the program is executing and how many times the function gets called in a program.

What is the module to import unittest in Python?

In this method, we will use the unittest module and filename to run the tests. The command to run the tests is python -m unittest filename.py . In our case, the command to run the tests is python -m unittest test_utils.py .

Is PyUnit and unittest same?

PyUnit is an easy way to create unit testing programs and UnitTests with Python. (Note that docs.python.org uses the name "unittest", which is also the module name.)


2 Answers

You have to initialize the cProfiler in the Constructor of the test, and use the profile data in destructor -- I use it like that:

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 

In case that a test waits for input, one needs to call self.pr.disable() before that call, and re-enable it afterwards.

If you prefer pytest the method names are a bit different:

import cProfile import time  class TestProfile:     """ test to illustrate cProfile usage """      def setup_class(self):         self.pr = cProfile.Profile()         self.pr.enable()      def teardown_class(self):         self.pr.disable()         self.pr.print_stats(sort="tottime")      def test_sleep(self):         time.sleep(2) 
like image 62
alinsoar Avatar answered Oct 19 '22 08:10

alinsoar


Specifying the module explicitly fixed this for me. That is, replacing...

    unittest.main() 

...(which tried to auto-discover what tests it should be running) with...

    unittest.main(module='mytest')  # if in 'mytest.py', or as appropriate for your filename/module 

...allowed proper profiling as python -m cProfile mytest.py.

like image 27
gojomo Avatar answered Oct 19 '22 09:10

gojomo