2018年1月14日 星期日

[ Python 文章收集 ] Pytest - Parametrizing fixtures and test functions

Source From Here 
Preface 
pytest enables test parametrization at several levels: 
* pytest.fixture() allows one to parametrize fixture functions.
* @pytest.mark.parametrize allows one to define multiple sets of arguments and fixtures at the test function or class.
* pytest_generate_tests allows one to define custom parametrization schemes or extensions.


@pytest.mark.parametrize: parametrizing test functions 
The builtin pytest.mark.parametrize decorator enables parametrization of arguments for a test function. Here is a typical example of a test function that implements checking that a certain input leads to an expected output: 
- test.py 
  1. # content of test_expectation.py  
  2. import pytest  
  3. @pytest.mark.parametrize("test_input,expected", [  
  4.     ("3+5"8),  
  5.     ("2+4"6),  
  6.     ("6*9"42),  
  7. ])  
  8. def test_eval(test_input, expected):  
  9.     assert eval(test_input) == expected  
Here, the @parametrize decorator defines three different (test_input,expected) tuples so that the test_eval function will run three times using them in turn: 


As designed in this example, only one pair of input/output values fails the simple test function. And as usual with test function arguments, you can see the input and output values in the traceback. Note that you could also use the parametrize marker on a class or a module (see Marking test functions with attributes) which would invoke several functions with the argument sets. 

It is also possible to mark individual test instances within parametrize, for example with the builtin mark.xfail
- test2.py 
  1. # content of test_expectation.py  
  2. import pytest  
  3. @pytest.mark.parametrize("test_input,expected", [  
  4.     ("3+5"8),  
  5.     ("2+4"6),  
  6.     pytest.param("6*9"42,  
  7.                  marks=pytest.mark.xfail),  
  8. ])  
  9. def test_eval(test_input, expected):  
  10.     assert eval(test_input) == expected  
Let’s run this: 


The one parameter set which caused a failure previously now shows up as an “xfailed (expected to fail)” test. To get all combinations of multiple parametrized arguments you can stack parametrize decorators: 
  1. import pytest  
  2. @pytest.mark.parametrize("x", [01])  
  3. @pytest.mark.parametrize("y", [23])  
  4. def test_foo(x, y):  
  5.     pass  
This will run the test with the arguments set to x=0/y=2,``x=1/y=2``, x=0/y=3, and x=1/y=3 exhausting parameters in the order of the decorators. 

Basic pytest_generate_tests example 
Sometimes you may want to implement your own parametrization scheme or implement some dynamism for determining the parameters or scope of a fixture. For this, you can use the pytest_generate_tests hook which is called when collecting a test function. Through the passed in metafunc object you can inspect the requesting test context and, most importantly, you can call metafunc.parametrize() to cause parametrization. 
- test_strings.py 
  1. # content of test_strings.py  
  2.   
  3. def test_valid_string(stringinput):  
  4.     assert stringinput.isalpha()  
Now we add a conftest.py file containing the addition of a command line option and the parametrization of our test function: 
- conftest.py 
  1. # content of conftest.py  
  2.   
  3. def pytest_addoption(parser):  
  4.     parser.addoption("--stringinput", action="append"default=[],  
  5.         help="list of stringinputs to pass to test functions")  
  6.   
  7. def pytest_generate_tests(metafunc):  
  8.     if 'stringinput' in metafunc.fixturenames:  
  9.         metafunc.parametrize("stringinput",  
  10.                              metafunc.config.getoption('stringinput'))  
If we now pass two stringinput values, our test will run twice: 
# pytest -q --stringinput='hello' --stringinput='world' test_strings.py
..
2 passed in 0.01 seconds

Let’s also run with a stringinput that will lead to a failing test: 


As expected our test function fails. If you don’t specify a stringinput it will be skipped because metafunc.parametrize() will be called with an empty parameter list: 
# pytest -q -rs test_strings.py
s
==================================================================== short test summary info
SKIP [1] test_strings.py:3: got empty parameter set ['stringinput'], function test_valid_string at /root/tmp/test_strings.py:2
1 skipped in 0.01 seconds


Note that when calling metafunc.parametrize multiple times with different parameter sets, all parameter names across those sets cannot be duplicated, otherwise an error will be raised. For further examples, you might want to look at more parametrization examples.

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...