当前位置: 代码迷 >> 综合 >> pytest(1): 入门篇
  详细解决方案

pytest(1): 入门篇

热度:102   发布时间:2023-11-21 17:41:28.0

执行

 

1.在控制台执行 pytest

2.在控制台指定执行范围
a.指定某个模块 pytest test_module.py
b.指定某个目录及其子目录的所有测试文件 pytest testcase
c.指定某个某块的某个方法 pytest test_module::test_function
d.指定执行某模块的某个类中的某个用例 用“::”分割 pytesy test_model.py::test_class::test_method
更多指定范执行范围样例,请参考官网

3.通过python代码执行pytest
1.直接执行pytest.main() 【自动查找当前目录下,以test_开头的文件或者以_test结尾的py文件】
2.设置pytest的执行参数 pytest.main(['--html=./report.html','test_login.py'])【执行test_login.py文件,并生成html格式的报告】
方式2中,执行参数和插件参数,通过[]进行分割,[]内的多个参数通过‘逗号,’进行分割

Pytest 查找测试策略

默认情况下,pytest 会递归查找当前目录下所有以 test 开始或结尾的 Python 脚本,并执行文件内的所有以 test 开始或结束的函数和方法。

mark 标记执行

# test_with_mark.py@pytest.mark.finished
def test_func1():assert 1 == 1@pytest.mark.unfinished
def test_func2():assert 1 != 1cmd:pytest -m finished tests/test-function/test_with_mark.py

skip 需要跳过执行的case: 

@pytest.mark.skip(reason='out-of-date api')
def test_connect():pass

@pytest.mark.skip() #1、跳过方法或用例,未备注原因

@pytest.mark.skip(reason='跳过一个方法或一个测试用例') #2、跳过方法或用例,备注了原因

@pytest.mark.skipif(1==1,reason='跳过一个方法或一个测试用例')   #3、当条件满足,跳过方法或用例,备注了原因
 

参数化

在 pytest 中,我们有更好的解决方法,就是参数化测试,即每组参数都独立执行一次测试。使用的工具就是 pytest.mark.parametrize(argnames, argvalues)

单参数

@pytest.mark.parametrize('passwd',['123456','abcdefdfs','as52345fasdf4'])
def test_passwd_length(passwd):assert len(passwd) >= 8

多参数


@pytest.mark.parametrize('user, passwd',[('jack', 'abcdefgh'),('tom', 'a123456a')])
def test_passwd_md5(user, passwd):db = {'jack': 'e8dc4081b13434b45189a720b77b6818','tom': '1702a132e769a623c1adb78353fc9503'}import hashlibassert hashlib.md5(passwd.encode()).hexdigest() == db[user]

注意:

1.parametrize中字符串指定参数名必须与testcase中指定参数名一致(user,passwd)

2.parametrize中实际参数以 列表形式,多个参数则列表每项为元组

测试类的参数化

固件(fixture)

@pytest.fixture()
def postcode():return '010'def test_postcode(postcode):assert postcode == '010'

 yield:预处理和后处理

Pytest 使用 yield 关键词将固件分为两部分,yield 之前的代码属于预处理,会在测试前执行;yield 之后的代码属于后处理,将在测试完成后执行。

@pytest.fixture()
def db():print('Connection successful')yieldprint('Connection closed')def search_user(user_id):d = {'001': 'xiaoming'}return d[user_id]def test_search(db):assert search_user('001') == 'xiaoming'@pytest.fixture()
def my_fix():print(123)yield 1234   #调用固件时返回值print(432)def test_my(my_fix):print(my_fix)

固件作用域

在定义固件时,通过 scope 参数声明作用域,可选项有:function: 函数级,每个测试函数都会执行一次固件;
class: 类级别,每个测试类执行一次,所有方法都可以使用;
module: 模块级,每个模块执行一次,模块内函数和方法都可使用;
package,表示 fixture 函数在测试包(文件夹)中第一个测试用例执行前和最后一个测试用例执行后执行一次。
session: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。

固件自动执行

目前为止,所有固件的使用都是手动指定,或者作为参数,或者使用 usefixtures

如果我们想让固件自动执行,可以在定义时指定 autouse 参数。

@pytest.fixture(scope='session', autouse=True)

固件参数化

与函数参数化使用 @pytest.mark.parametrize 不同,固件在定义时使用 params 参数进行参数化。

固件参数化依赖于内置固件 request 及其属性 param

conftest

  • pytest会默认读取conftest.py
  • conftest.py 文件名称是固定的,不能改动
  • conftest.py只对同一个package下的所有测试用例生效
  • 不同目录可以有自己的conftest.py,一个项目中可以有多个conftest.py
  • 测试用例文件中不需要手动import conftest.py,pytest会自动查找
  • conftest.py文件所在目录必须存在__init__.py文件

参考:

Pytest 使用手册 — learning-pytest 1.0 文档

Pytest全局用例共用之conftest.py详解_专业资深测试者,多年质量管理经验,浪迹网游、金融、房产、招聘及海外行业多年,CDSN百万原创阅读,公众号500+原创文章,提倡测试左移、风险、越权、假设、探索测试,喜欢用抽象思维模式思考和技术探讨,自动化、性能、安全测试实施者,感谢关注!-CSDN博客_pytest的conftest