Source From Here
Preface
I think of pytest as the run-anything, no boilerplate, no required api, use-this-unless-you-have-a-reason-not-to test framework. This is really where testing gets fun. As with previous intro’s on this site, I’ll run through an overview, then a simple example, then throw pytest at my markdown.py project. I’ll also cover fixtures, test discovery, and running unittests with pytest.
Contents
No boilerplate, no required api
The doctest and unittest both come with Python. They are pretty powerful on their own, and I think you should at least know about those frameworks, and learn how to run them at least on some toy examples, as it gives you a mental framework to view other test frameworks.
Note:
With unittest, you a very basic test file might look like this:
The style of deriving from
unittest.TestCase is something unittest shares with it’s xUnit counterparts like JUnit. I don’t want to get into the history of xUnit style frameworks. However, it’s informative to know that inheritance is quite important in some languages to get the test framework to work right.
But this is Python. We have very powerful introspection and runtime capabilities, and very little information hiding. Pytest takes advantage of this. An identical test as above could look like this if we remove the boilerplate:
Yep, three lines of code. (
Four, if you include the blank line.)
This works in pytest. Once you start writing tests like this, you won’t want to go back.
However, you may have a bunch of tests already written for doctest or unittest. Pytest can be used to run doctests and unittests. It also claims to support some twisted trial tests (although I haven’t tried this). You can extend pytest using plugins you pull from the web, or write yourself. I’m not going to cover plugins in this article, but I’m sure I’ll get into it in a future article.
pytest example
Using the same unnecessary_math.py module that I wrote in the doctest intro, this is some example test code to test the ‘multiply’ function.
- pytest_e1.py
Running pytest
To run pytest:
And with verbose:
pytest fixtures
Although unittest does allow us to have setup and teardown, pytest extends this quite a bit. We can add specific code to run:
We can also use pytest style fixtures, which are covered in pytest fixtures nuts and bolts.
I’ve modified our simple test code with some fixture calls, and added some print statements so that we can see what’s going on. Here’s the code:
- pytest_e2.py
To see it in action, I’ll use the
-s option, which turns off output capture. This will show the order of the different fixture calls.
Test discovery
The unittest module comes with a ‘discovery’ option. Discovery is just built in to pytest. Test discovery was used in my examples to find tests within a specified module. However, pytest can find tests residing in multiple modules, and multiple packages, and even find unittest and doctests. To be honest, I haven’t memorized the discovery rules. I just try to do this, and at seems to work nicely:
If I do all of that, pytest seems to find all my code nicely.
If you are doing something else, and are having trouble getting pytest to see your test code, then take a look at the pytest discovery documentation.
Running unittests from pytest
To show how pytest handles unittests, here’s a sample run of pytest on the simple unittests I wrote in the unittest introduction:
As you can see, I didn’t provide any extra options, pytest finds unittests automatically.
More pytest info (links)
Preface
I think of pytest as the run-anything, no boilerplate, no required api, use-this-unless-you-have-a-reason-not-to test framework. This is really where testing gets fun. As with previous intro’s on this site, I’ll run through an overview, then a simple example, then throw pytest at my markdown.py project. I’ll also cover fixtures, test discovery, and running unittests with pytest.
Contents
No boilerplate, no required api
The doctest and unittest both come with Python. They are pretty powerful on their own, and I think you should at least know about those frameworks, and learn how to run them at least on some toy examples, as it gives you a mental framework to view other test frameworks.
Note:
With unittest, you a very basic test file might look like this:
- import unittest
- from unnecessary_math import multiply
- class TestUM(unittest.TestCase):
- def test_numbers_3_4(self):
- self.assertEqual( multiply(3,4), 12)
But this is Python. We have very powerful introspection and runtime capabilities, and very little information hiding. Pytest takes advantage of this. An identical test as above could look like this if we remove the boilerplate:
- from unnecessary_math import multiply
- def test_numbers_3_4():
- assert( multiply(3,4) == 12 )
This works in pytest. Once you start writing tests like this, you won’t want to go back.
However, you may have a bunch of tests already written for doctest or unittest. Pytest can be used to run doctests and unittests. It also claims to support some twisted trial tests (although I haven’t tried this). You can extend pytest using plugins you pull from the web, or write yourself. I’m not going to cover plugins in this article, but I’m sure I’ll get into it in a future article.
pytest example
Using the same unnecessary_math.py module that I wrote in the doctest intro, this is some example test code to test the ‘multiply’ function.
- pytest_e1.py
- from unnecessary_math import multiply
- def test_numbers_3_4():
- assert multiply(3,4) == 12
- def test_strings_a_3():
- assert multiply('a',3) == 'aaa'
To run pytest:
And with verbose:
pytest fixtures
Although unittest does allow us to have setup and teardown, pytest extends this quite a bit. We can add specific code to run:
We can also use pytest style fixtures, which are covered in pytest fixtures nuts and bolts.
I’ve modified our simple test code with some fixture calls, and added some print statements so that we can see what’s going on. Here’s the code:
- pytest_e2.py
- from unnecessary_math import multiply
- def setup_module(module):
- print("setup_module module:%s" % module.__name__)
- def teardown_module(module):
- print("teardown_module module:%s" % module.__name__)
- def setup_function(function):
- print("setup_function function:%s" % function.__name__)
- def teardown_function(function):
- print("teardown_function function:%s" % function.__name__)
- def test_numbers_3_4():
- print('test_numbers_3_4 <============================ actual test code')
- assert multiply(3,4) == 12
- def test_strings_a_3():
- print('test_strings_a_3 <============================ actual test code')
- assert multiply('a',3) == 'aaa'
- class TestUM:
- def setup(self):
- print("setup class:TestStuff")
- def teardown(self):
- print("teardown class:TestStuff")
- def setup_class(cls):
- print("setup_class class:%s" % cls.__name__)
- def teardown_class(cls):
- print("teardown_class class:%s" % cls.__name__)
- def setup_method(self, method):
- print("setup_method method:%s" % method.__name__)
- def teardown_method(self, method):
- print("teardown_method method:%s" % method.__name__)
- def test_numbers_5_6(self):
- print('test_numbers_5_6 <============================ actual test code')
- assert multiply(5,6) == 30
- def test_strings_b_2(self):
- print('test_strings_b_2 <============================ actual test code')
Test discovery
The unittest module comes with a ‘discovery’ option. Discovery is just built in to pytest. Test discovery was used in my examples to find tests within a specified module. However, pytest can find tests residing in multiple modules, and multiple packages, and even find unittest and doctests. To be honest, I haven’t memorized the discovery rules. I just try to do this, and at seems to work nicely:
If I do all of that, pytest seems to find all my code nicely.
If you are doing something else, and are having trouble getting pytest to see your test code, then take a look at the pytest discovery documentation.
Running unittests from pytest
To show how pytest handles unittests, here’s a sample run of pytest on the simple unittests I wrote in the unittest introduction:
As you can see, I didn’t provide any extra options, pytest finds unittests automatically.
More pytest info (links)
沒有留言:
張貼留言