An easy guide to PyTest
Pytest is a unit testing framework that helps you write better programs. Flask, Werkzeug, Gunicorn, etc. Learn how to use the PyTest framework.
- Introduction to the use case
- Advanced skills
- summary
Introduction to the use case
Simple use case
Write a simple example of test_sample.py:
# cat test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
Copy the code
The two methods defined in the example are very simple. Test_answer asserts the target function inc. Run the test case with pytest test_sample.py:
# pytest test_sample.py ========================================================================================================= test session starts ========================================================================================================== Platform Darwin -- Python 3.7.5, PyTest-6.0.2, py-1.9.0, pluggy-0.13.1 rootdir: /Users/yoo/codes/ft6work/devops-py/tests plugins: The parallel - 0.1.0 from xdist - 2.1.0, Forked -1.3.0 collected 1 item test_sample.py F [100%] =============================================================================================================== FAILURES = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = _____________________________________________________________________________________________________________ test_answer ______________________________________________________________________________________________________________ def test_answer(): print("test_answer") > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) test_sample.py:7: AssertionError --------------------------------------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------------------------------------- test_answer ======================================================================================================= short test summary info ======================================================================================================== FAILED test_sample.py::test_answer - assert 4 == 5 ========================================================================================================== 1 failed in 0.04 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =Copy the code
If pyTest is not already installed, use PIP Install PyTest to install it.
The test results show that a test case was run, and the result is red, indicating failure. The error message shows that an AssertionError is thrown at line 7 of the code. You can change the code to make the test case green.
This test case involves three simple rules of PyTest:
- Test module totest_The prefix name
- The same goes for test cases (functions)test_The prefix name
- Result judgment useassertAssertions can be
Exception handling
Pytest supports the capture of exceptions. Use with + pytest. Raises to catch exceptions to the target function:
# cat test_exception.py
import pytest
def f():
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
Copy the code
The test class
Pytest supports test classes that can be used to group test cases:
# cat test_class.py
class TestClass:
def test_one(self):
x = "this"
assert "h" in x
def test_two(self):
x = "hello"
assert hasattr(x, "check")
Copy the code
- Classes use the Test prefix, and no additional inheritance is required to Test classes.
Automatic test
Our directory has the following three test modules:
# ll
-rw-r--r-- 1 yoo staff 168B Jul 22 21:32 test_class.py
-rw-r--r-- 1 yoo staff 117B Jul 22 21:30 test_exception.py
-rw-r--r-- 1 yoo staff 73B Jul 22 21:09 test_sample.py
Copy the code
Running PyTest – with no extra parameters – automatically tests 3 modules, very conveniently:
# pytest ============================================================================================== test session starts =============================================================================================== platform darwin -- Python 3.8.5, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 rootdir: /Users/yoo/work/yuanmahui/python/ch22-pytest collected 4 items test_class.py .. [ 50%] test_exception.py . [ 75%] test_sample.py . [100%] = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 4 passed in 0.02 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =Copy the code
Advanced skills
After understanding the basic use of PyTest, we’ll learn some advanced techniques that will help us write test cases better.
parametrize
Parametrize reduces the writing of test cases. Consider the following test case:
def test_eval():
assert eval("3+5") == 8
assert eval("'2'+'4'") == "24"
assert eval("6*9") == 54
Copy the code
There are many test conditions for eval, and adding use cases requires adjusting functions. This code is not concise and easy to maintain. Use parametrize to optimize this problem:
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("'2'+'4'", "24"),
("6*9", 54)
])
def test_eval_1(test_input, expected):
assert eval(test_input) == expected
Copy the code
Adjust the parameters of the test function to inputs and expectations, and then set parameter values with parametrize. The function parameter assignment will be performed automatically at runtime. To add a test condition, you don’t need to change the body of test_eval_1.
mark
Mark is a tag that can be configured as follows:
@pytest.mark.slow def test_mark(): print("test mark") # Simulate running a long test case time.sleep(10) assert 5 == 5Copy the code
Add the pytest.ini file to the pytest directory and configure pyTest:
# cat pytest.ini
[pytest]
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
Copy the code
Use the following command to skip the marked functions and speed up the test:
pytest test_sample.py -m "not slow"
Copy the code
You can also just run the tagged function
pytest -m slow
Copy the code
fixture
Fixtures can provide functionality like initialization and mock, and here’s a full example:
import pytest # Arrange @pytest.fixture def first_entry(): return "a" # Arrange @pytest.fixture def second_entry(): return 2 # Arrange @pytest.fixture def order(first_entry, second_entry): return [first_entry, second_entry] # Arrange @pytest.fixture def expected_list(): Return ["a", 2, 3.0] def test_string(order, Expected_list): # Expected_list # Assert Assert order == Expected_listCopy the code
You can see that the order parameter of test_String and the EXPECTED_list are both the result of the function flagged earlier using the Pytest.fixture decorator. Fixtures can also be nested, with order nesting first_entry and second_entry.
Now that you know how fixtures work, you might wonder, what’s the point of writing this? For example, a use case to test database write requires a database connection parameter:
def test_database_insert_record(database_connection):
if database_connection:
print("Insertion Successful. ", database_connection)
...
Copy the code
Using fixtures to solve this problem, write Conftest.py in the test cases directory:
# cat conftest.py @pytest.fixture def database_connection(): # mock... .Copy the code
plugin&&hook
Plugins and hooks can be written to extend PyTest.
Create conftest.py and test-sub.py in a directory:
# cat a/conftest.py
def pytest_runtest_setup(item):
# called for running each test in 'a' directory
print("setting up", item)
# cat a/test_sub.py
def test_sub():
pass
Copy the code
Using pytest a/test_sub.py –capture=no will load the plugin and hook we wrote.
. a/test_sub.py setting up <Function test_sub>Copy the code
- Use system hooks topytest_Is the prefix, namedruntest_setup 。
You can use Pytest_runtest_setup to implement similar functionality to setup in the test framework.
summary
Pytest is a simple and easy to use test case used in flask, Werkzeug, Gunicorn and other projects. The use method is as follows:
- The test directory is generally usedtestsName at the same level as SRC
- Test module usagetest_The prefix
- Test class usesTestPrefix, do not need to inherit from other superclasses
- Test cases are also usedtest_The prefix
- You can parameterize with parametrize
- You can use Mark to tag test cases
- You can use fixtures to simulate test conditions
- Configure PyTest using the pytest.ini file
- You can write plug-ins and HOO extensions to PyTest
There are many more uses for Pytest, and we’ll learn more about that next time.
Refer to the link
- Pytest document docs.pytest.org/en/6.2.x/