Pytest----修改Pytest默认的用例发现规则

简介: Pytest----修改Pytest默认的用例发现规则

一、命令行使用ignore参数

比如目录结构如下

tests/
|-- example
|   |-- test_example_01.py
|   |-- test_example_02.py
|   '-- test_example_03.py
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py
'-- hello
    '-- world
        |-- test_world_01.py
        |-- test_world_02.py
        '-- test_world_03.py

使用pytest --ignore=tests/foobar/test_foobar_03.py --ignore=tests/hello/ ,可以使用多个ignore参数去忽略,执行结果如下,可以看到tests/foobar/test_foobar_03.py 和hello目录下的都没有执行

$ pytest --ignore=foobar/test_foobar_03.py --ignore=hello/
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 5 items                                                                                                                                                       

example\test_example_01.py .                                                                                                                                      [ 20%]
example\test_example_02.py .                                                                                                                                      [ 40%]
example\test_example_03.py .                                                                                                                                      [ 60%]
foobar\test_foobar_01.py .                                                                                                                                        [ 80%]
foobar\test_foobar_02.py .                                                                                                                                        [100%]

========================================================================== 5 passed in 0.05s ===========================================================================

$

二、Unix Shell风格的命令行使用ignore-glob参数支持正则

比如目录结构如下

tests/
|-- example
|   |-- test_example_01.py
|   |-- test_example_02.py
|   '-- test_example_03.py
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py
'-- hello
    '-- world
        |-- test_world_01.py
        |-- test_world_02.py
        '-- test_world_03.py

在Unix shell风格下,使用--ignore-glob参数,可以通过正则匹配的方式忽略用例,如下,以“_01.py”结尾的用例均已被忽略

$ pytest --ignore-glob='*_01.py'
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 6 items

example\test_example_02.py .                                             [ 16%]
example\test_example_03.py .                                             [ 33%]
foobar\test_foobar_02.py .                                               [ 50%]
foobar\test_foobar_03.py .                                               [ 66%]
hello\workd\test_world_02.py .                                           [ 83%]
hello\workd\test_world_03.py .                                           [100%]

============================== 6 passed in 0.06s ==============================

三、命令行使用deselect参数

比如目录结构如下

tests/
|-- example
|   |-- test_example_01.py
|   |-- test_example_02.py
|   '-- test_example_03.py
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py
'-- hello
    '-- world
        |-- test_world_01.py
        |-- test_world_02.py
        '-- test_world_03.py

如下,使用pytest --deselect foobar/test_foobar_01.py --deselect foobar/test_foobar_03.py 命令,即可不执行test_foobar_01.py和test_foobar_03.py 文件的用例,如果忽略多个可以使用多个--deselect参数

$ pytest --deselect foobar/test_foobar_01.py  --deselect foobar/test_foobar_03.py
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 9 items / 2 deselected / 7 selected

example\test_example_01.py .                                             [ 14%]
example\test_example_02.py .                                             [ 28%]
example\test_example_03.py .                                             [ 42%]
foobar\test_foobar_02.py .                                               [ 57%]
hello\workd\test_world_01.py .                                           [ 71%]
hello\workd\test_world_02.py .                                           [ 85%]
hello\workd\test_world_03.py .                                           [100%]

======================= 7 passed, 2 deselected in 0.07s =======================

四、设置重复路径执行多次

比如目录结构如下

tests/
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py

当指定的重复路径为文件级别时,默认支持执行多次,如下,执行了两次

$ pytest  foobar/test_foobar_01.py foobar/test_foobar_01.py
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 2 items

foobar\test_foobar_01.py ..

============================== 2 passed in 0.02s ==============================

指定的重复路径为目录时,默认只会执行一次,如下,只执行了一次

$ pytest  foobar foobar
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 3 items

foobar\test_foobar_01.py .                                               [ 33%]
foobar\test_foobar_02.py .                                               [ 66%]
foobar\test_foobar_03.py .                                               [100%]

============================== 3 passed in 0.03s ==============================

当指定的路径为目录时,如果希望也执行多次,需要使用 --keep-duplicates参数,如下目录中的用例执行了2次

$ pytest  foobar foobar --keep-duplicates
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 6 items

foobar\test_foobar_01.py .                                               [ 16%]
foobar\test_foobar_02.py .                                               [ 33%]
foobar\test_foobar_03.py .                                               [ 50%]
foobar\test_foobar_01.py .                                               [ 50%]
foobar\test_foobar_02.py .                                               [ 50%]
foobar\test_foobar_03.py .

============================== 6 passed in 0.04s ==============================

五、通过pytest.ini设置用例的搜索目录

比如目录结构如下,设置用例搜索目录可以在pytest.ini文件中进行设置

tests/
|-- pytest.ini
|-- example
|   |-- test_example_01.py
|   |-- test_example_02.py
|   '-- test_example_03.py
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py
'-- hello
    '-- world
        |-- test_world_01.py
        |-- test_world_02.py
        '-- test_world_03.py

在pytest.ini中可以通过testpaths指定搜索目录

如pytest.ini内容如下

[pytest]
testpaths=foobar hello

执行结果如下,即指定了当执行pytest命令的时候只会去搜索foobar和hello目录

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests, configfile: pytest.ini, testpaths: foobar, hello
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collected 6 items

foobar\test_foobar_01.py .                                               [ 16%]
foobar\test_foobar_02.py .                                               [ 33%]
foobar\test_foobar_03.py .                                               [ 50%]
hello\workd\test_world_01.py .                                           [ 66%]
hello\workd\test_world_02.py .                                           [ 83%]
hello\workd\test_world_03.py .                                           [100%]

============================== 6 passed in 0.05s ==============================

在pytest.ini文件中可以通过norecursedirs指定目录不搜索

pytest.ini内容如下:

[pytest]
norecursedirs=foobar hello

执行结果如下,明显foobar和hello目录都没有搜索

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: G:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfaiures-10.1, xdist-2.3.0
collected 3 items

example\test_example_01.py .                                             [ 33%]
example\test_example_02.py .                                             [ 66%]
example\test_example_03.py .                                             [100%]

============================== 3 passed in 0.04s ==============================

六、自定义测试文件测试类测试函数的命名规则

通过pytest.ini可以自定义测试文件、测试类、测试函数的命名规则,如下pytest.ini文件声明了测试文件匹配check_.py,测试类以Check开头,测试函数匹配check_,这样就相当于重写了pytest默认的测试文件测试类和测试函数命名规则,这种用法一般在一些大公司会有要求命名符合自己公司的命名规范而去使用,在一般情况下,尽量不要去修改默认的命名规则

[pytest]
python_files = check_*.py
python_classes = Check
python_functions = check_*

编写check_demo.py测试文件如下:

def check_func():
    assert 1==1

class CheckDemo():
    def check_func2(self):
        assert 1==1

执行结果如下,可以看出这里因为pytest.ini重新定义了规则,因此这里的check_demo.py以及CheckDemo类和测试函数才会被pytest识别

$ pytest -v
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\python39\python.exe
cachedir: .pytest_cache
rootdir: G:\src\blog\tests\demo, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collecting ... collected 2 items

check_demo.py::check_func PASSED                                         [ 50%]
check_demo.py::CheckDemo::check_func2 PASSED                             [100%]

============================== 2 passed in 0.02s ==============================

七、自定义pytest命令

所谓自定义pytest命令其实是在一些场景下,比如执行pytest的命令的时候,希望都带有-v -s参数执行,这样每次执行命令都要输入这个参数,这时候就感觉有那么一点点的麻烦了,此时就可以使用pytest.ini来自定义pytest命令,类似与linux命令中的alias命令,将新的pytest命令定义为pytest -s -v,这样在执行pytest命令的时候,不需要加参数则默认就把-s -v两个参数带上了

比如目录结构如下

tests/
|-- pytest.ini
|-- example
|   |-- test_example_01.py
|   |-- test_example_02.py
|   '-- test_example_03.py
|-- foobar
|   |-- test_foobar_01.py
|   |-- test_foobar_02.py
|   '-- test_foobar_03.py
'-- hello
    '-- world
        |-- test_world_01.py
        |-- test_world_02.py
        '-- test_world_03.py

pytest.ini如下:

[pytest]
addopts=-s -v

其他测试文件中的内容均为:

def test_example():
    assert 1==1

此时,在tests目录下执行pytest命令,如下,虽然仅执行的pytest命令,从结果可以看出其实是将-s -v的参数已经带上了

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\python39\python.exe
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('G:\\src\\blog\\tests\\.hypothesis\\examples')
rootdir: G:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collecting ... collected 9 items

example/test_example_01.py::test_example PASSED
example/test_example_02.py::test_example PASSED
example/test_example_03.py::test_example PASSED
foobar/test_foobar_01.py::test_example PASSED
foobar/test_foobar_02.py::test_example PASSED
foobar/test_foobar_03.py::test_example PASSED
hello/workd/test_world_01.py::test_example PASSED
hello/workd/test_world_02.py::test_example PASSED
hello/workd/test_world_03.py::test_example PASSED

============================== 9 passed in 0.22s ==============================

八、查看用例集合树

有事需要查看有多少用例,但是又不想通过执行所有用例,此时可以使用--collect-only参数

执行pytest --collect-only 查看当前目录下有多少用例

$ pytest --collect-only
============================= test session starts =============================
platform win32 -- Python 3.9.6, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\python39\python.exe
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('G:\\src\\blog\\tests\\.hypothesis\\examples')
rootdir: G:\src\blog\tests, configfile: pytest.ini
plugins: allure-pytest-2.9.43, caterpillar-pytest-0.0.2, hypothesis-6.31.6, forked-1.3.0, rerunfailures-10.1, xdist-2.3.0
collecting ... collected 9 items

<Package example>
  <Module test_example_01.py>
    <Function test_example>
  <Module test_example_02.py>
    <Function test_example>
  <Module test_example_03.py>
    <Function test_example>
<Package foobar>
  <Module test_foobar_01.py>
    <Function test_example>
  <Module test_foobar_02.py>
    <Function test_example>
  <Module test_foobar_03.py>
    <Function test_example>
<Package workd>
  <Module test_world_01.py>
    <Function test_example>
  <Module test_world_02.py>
    <Function test_example>
  <Module test_world_03.py>
    <Function test_example>

========================= 9 tests collected in 0.22s ==========================
目录
相关文章
|
6月前
pytest添加自定义参数
pytest添加自定义参数
186 0
|
测试技术 Python
pytest--运行指定的测试和参数化
pytest--运行指定的测试和参数化
|
测试技术 Python
02-pytest-用例运行规则
02-pytest-用例运行规则
|
测试技术
15-pytest-自定义用例执行顺序
15-pytest-自定义用例执行顺序
|
测试技术 C++
pytest pytest.ini配置 用例分组 用例跳过
pytest pytest.ini配置 用例分组 用例跳过
|
测试技术 C++ Python
pytest 执行规则_基本用法_常用插件_常用断言_常用参数
pytest 执行规则_基本用法_常用插件_常用断言_常用参数
|
测试技术
pytest学习和使用14-Pytest用例执行结果有哪几种状态?
pytest学习和使用14-Pytest用例执行结果有哪几种状态?
91 0
|
测试技术
Pytest----pytest.ini自定义测试文件、测试用例、测试类命名规则
Pytest----pytest.ini自定义测试文件、测试用例、测试类命名规则
319 0
Pytest----pytest.ini自定义测试文件、测试用例、测试类命名规则
|
测试技术 Python
Pytest系列(13)- 重复执行用例插件之pytest-repeat的详细使用
Pytest系列(13)- 重复执行用例插件之pytest-repeat的详细使用
269 0
Pytest系列(13)- 重复执行用例插件之pytest-repeat的详细使用