1. Introduction
Little loser: brother fish, why don't you talk about the technology of test development recently, such as
Xiaoyu: I'll go ~ ~ you've agreed to bring up this matter together?
Little loser: why do you say that?
Xiaoyu: because recently, a sister complained to me about why she didn't talk about the knowledge of test development, which was developed by the whole
Loser: isn't it?
Xiaoyu: brother, I have difficulties too ~~
Little loser: don't fix those useless ones, just one today!!!
Fish: exactly~~
Xiaoyu's blog said unittest framework , there are also many examples in it. If you don't understand it, you can have a look.
Today, let's share the framework, but this time it's the unit test framework: Pytest.
Xiaoyu remembers writing an article on the composition of the test framework,
This includes the necessary knowledge of the test framework composition in various stages such as function, performance and automation,
If you don't understand, you can take a look at Xiaoyu's blog< Test framework composition of test development knowledge>.
First cut a picture and see:
Here, let's just talk about the unit test framework of Pytest. Let's not talk about anything else!!
2. Introduction to Pytest
2.1 introduction stage
2.1. 1 run test cases
All theories are prepared for actual combat,
Therefore, our first step is to give examples and direct actual combat!
Write a simple test case with the file name "test_sample.py"
# pytest test_sample.py def inc(x): return x + 1 def test_answer(): assert inc(3) == 5
Both methods are very simple,
- test_answer() asserts the objective function inc;
- pytest test_sample.py run test case
Let's look at the running results
The test results show that a test case is run, and the result is red, indicating failure. The error message shows that AssertionError is thrown on 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 to test_ Prefix naming
- Test cases (functions) are also represented by test_ Prefix naming
- The result can be judged by assert
2.1. 2. Exception handling
Catching exceptions and exception handling are necessary conditions in each piece of code,
Of course, pytest also supports exception capture,
Method: use with + pytest Raises caught an exception in the objective function:
# -*- coding:utf-8 -*- # @Time : 2021-09-05 # @Author : Carl_DJ import pytest def f(): raise SystemExit(1) def test_mytest(): #Catch exception with pytest.raises(SystemExit): f()
2.1. 3 test class
Of course, pytest also supports test classes,
Function of test class: used for test grouping
# -*- coding:utf-8 -*- # @Time : 2021-09-05 # @Author : Carl_DJ class TestClass: #test_ start def test_one(self): x = "this" assert "h" in x #test_ start def test_two(self): x = "hello" assert hasattr(x, "check")
Here, it's all based on test_ At the beginning, it's the same as unittest.
If not test_ At the beginning, it cannot be called.
2.1. 4 run test scripts automatically
If a suit folder has multiple test case scripts,
We just need to enter a pytest to run all the test scripts.
As shown below
This is the lazy mode.
2.2 advanced skills
2.2.1 parametrize
As the saying goes, the code does not have parameters, but changes parameters in two lines!
Therefore, when you can parameters, try to parameters, regardless of whether the reconstruction is bitter or not.
Let's look at the usage of parameter first, as follows:
Add the following before the test case:
@pytest. mark. Parameter ("parameter name", list data)
Parameter name: used to receive each item of data and serve as the parameter of the test case.
List data: a set of test data.
Look at the example
Without adding parameter, let's see how to write test cases
def test_eval(): assert eval("3+5") == 8 assert eval("'2'+'4'") == "24" assert eval("6*9") == 54
It looks troublesome,
Let's optimize the parameter again to see if it's much simpler
#Parameterize test cases using parameterize @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
After reading this code, it is very concise.
Let's see what parametrize does.
- First, adjust the parameters of the test function as input and expectation;
- Then fill in the parameter value in parameter;
- Function parameters will be assigned automatically at run time.
In this way, the test conditions are added, and there is no need to change the test_eval_1, add the condition array.
2.2.2. mark
mark is a label that marks which test cases are executed and which are not executed.
#label @pytest.mark.slow def test_mark(): print("test mark") # Simulate test cases that are time-consuming to run time.sleep(10) assert 5 == 5
Then add pytest. Exe to the directory INI file to configure pytest:
[pytest] markers = slow: marks tests as slow (deselect with '-m "not slow"')
Use the following command to skip marked functions and speed up the test:
pytest test_sample.py -m "not slow"
You can also run only marked functions
pytest -m slow
2.2.3 fixture
fixture is similar to setup/teardown of unittest, but it is more powerful than this.
for instance
# -*- coding:utf-8 -*- # @Time : 2021-09-05 # @Author : Carl_DJ import pytest #Set fixture @pytest.fixture def first_entry(): return "a" #Set fixture @pytest.fixture def second_entry(): return 2 #Set fixture @pytest.fixture def order(first_entry, second_entry): return [first_entry, second_entry] #Set fixture @pytest.fixture def expected_list(): return ["a", 2, 3.0] def test_string(order, expected_list): order.append(3.0) # Assert assert order == expected_list
Of course, fixture s can also be nested, and order nested first_entry and second_entry.
Little loser: what should I do if I need a database link to test the case written in the database?
Little fish, it's not difficult. fixture can also be done.
Write conf test. In the test case directory py
@pytest.fixture def database_connection(): # coding... ...
2.2.4 plugin&&hook
You can write plug-ins plugin and hook of pytest to extend pytest.
First create a directory a, and then create conf test. In directory a Py and test_sub.py two files.
#Create conf test. In directory a py def pytest_runtest_setup(item): # Run each use case under directory a print("setting up", item) # Create test under directory a_ sub.py def test_sub(): pass
Using pytest a/test_sub.py --capture=no will load the plugin and hook written by us. You can see the following words in the console:
... a/test_sub.py setting up <Function test_sub>
Knock on the blackboard:
Using pytest_runtest_setup can implement similar functions in the test framework.
3. Summary
The above are some common functions of pytest summarized by Xiaoyu. Is it also very simple.
In retrospect, we talked about those postures today!
- Test directories are generally named by tests and src
- The test module uses test_ prefix
- The Test class uses the Test prefix and does not need to inherit other parent classes
- Test cases also use test_ prefix
- Parameterize can be used for parameterization
- You can use mark to label test cases
- You can use fixture to simulate test conditions
- Use pytest INI file to configure pytest
- You can write plug-ins and hoo extensions to pytest
More about pytest,
Can continue to pay attention Xiaoyu's blog,
You can also read the official documents, Click download.