Pytest自动化框架

[复制链接]
发表于 2025-10-19 09:06:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次

Pytest简朴先容
第一章:Pytest console下令 
1.pytest
-v 参数
-h 参数
其他一些参数:仅供参考
第二章. mark标记 
@pytest.mark.skip
@pytest.mark.skipif
@pytest.mark.xfail 
​编辑 @pytest.mark.patametrize
单个参数
多个参数 
直接标记 
暗昧匹配标记 
 使用mark自界说标记
 第三章 固件Fixture
fixture的使用
​编辑fixture参数 
fixture的作用域 
@pytest.mark.usefixtures()
autouse(自动使用)
yeild的使用
注意点:
​编辑
 共享Fixture功能
参数化
内置Fixture
总结


Pytest简朴先容


下载pytest
  1. pip install pytest
复制代码
第一章:Pytest console下令 

默认必要test开头的py模块,test_开头的方法
1.pytest

实行pytest下令会自动匹配到test开头大概末了的文件
将其作为测试用例文件实行,在测试用例文件中自动匹配到test开头的类,类中匹配到test开头的方法,然后实行
pass代表断言乐成

失败:

-v 参数

会表现是哪个测试用例,信息更加详细一点

-h 参数

help 这是代表资助的参数

其他一些参数:仅供参考


第二章. mark标记 

pytest.mark是用来对测试方法举行标记的一个装饰器,重要作用是在测试用例实行过程中跳过标记的测试用例或做出判断以选择性的实行
标记测试函数
使用pytest --markers检察官方提供的mark

各个mark的详细寄义如下: 

mark寄义
@pytest.mark.filterwarings(warning)在标记的测试方法上添加告诫过滤    
@pytest.mark.skip(reason=None)实行时跳过标记的测试方法,reason默以为空
@pytest.mark.skipif(condition)通过条件判断是否跳过标记的测试方法,如果condition为真跳过,否则不跳过
@pytest.mark.xfail(condition,reason=None,run=True,
raises=None,strict=False)
如果条件的condition为True,则将预期结果标记为False
@pytest.mark.parametrize(argnames,argvalues)测试函数参数化,即调用多次测试函数,依次通报差别的参数
@pytest.mark.usefixtures(argnames,argvalues)将测试用例标记为必要指定的全部fixture,和直接使用fixture的结果一样。
@pytest.mark.tryfirst标记一个挂钩实现函数,使得所标记的测试方法可以起首或尽早地实行
@pytest.mark.trylast标记一个挂钩实现函数,使得标记的测试方法可以末了或尽大概晚实行,和tryfrist相反
@pytest.mark.skip

创建一个test_skip.py 添加这两个测试方法
使用pytest  -v实行
  1. import pytest
  2. # 如果在测试方法前添加了@pytest.mark.skip(reason=None),则在执行过程中遇到该测试方法
  3. # 时,跳过不执行
  4. @pytest.mark.skip
  5. def test_skip1():
  6.     assert 1 == 2
  7. @pytest.mark.skip(reason="跳过该条测试用例")
  8. def test_skip2():
  9.     assert 3 == 4
复制代码
运行结果:

@pytest.mark.skipif

condition为True,跳过测试
condition为False, 不跳过
  1. import pytest
  2. import sys
  3. my_list = [1, 3, 4, 5]
  4. """
  5. 源码解析:
  6.     class _SkipifMarkDecorator(MarkDecorator):
  7.         def __call__(  # type: ignore[override]
  8.             self,
  9.             condition: str | bool = ...,
  10.             *conditions: str | bool,
  11.             reason: str = ...,
  12.         ) -> MarkDecorator: ...
  13. condition 可以是字符串也可以是bool类型
  14. """
  15. # skipif对一些事物进行判断从而决定是否跳过测试方法,只有在满足条件下才会跳过
  16. # condition = True, 跳过测试
  17. @pytest.mark.skipif(condition=lambda: 1 in my_list, reason="1 在 my_list 中,跳过测试")
  18. def test_skipif1():
  19.     assert 1 == 1
  20. # condition为False, 所以不跳过
  21. @pytest.mark.skipif('sys.platform != "win32" ')
  22. def test_skipif2():
  23.     assert 2 == 2
  24. # if __name__ == '__main__':
  25. # print(sys.platform)  # win32
复制代码
@pytest.mark.xfail 

xfail可以拆分成x和fail明确,x表现可以预期到的结果,fail为失败,合起来可以表告竣可以预期到的失败的测试。xfail装饰器办理的是对于很清晰的知道他的记过是失败的,但是又不想直接跳过的测试方法,通过添加xfail装饰器可以在结果中给出显着的标识
新建一个test_xfail.py

  1. import pytest
  2. """
  3.    # 源码
  4.    def __call__(
  5.    self,
  6.    condition: str | bool = False,  # 主要条件参数,可以是字符串或布尔值,默认值为 False
  7.    *conditions: str | bool,  # 可变参数,允许传递多个条件,每个条件可以是字符串或布尔值
  8.    reason: str = ...,  # 字符串参数,用于说明标记的原因,默认值为未指定
  9.    run: bool = ...,  # 布尔值参数,用于控制是否运行测试,默认值为未指定
  10.    raises: None | type[BaseException] | tuple[type[BaseException], ...] = ...,  # 异常类型参数,用于指定测试是否应该抛出特定异常,默认值为未指定
  11.    strict: bool = ...,  # 布尔值参数,用于控制是否严格匹配异常,默认值为未指定
  12. ) -> MarkDecorator:  # 返回一个 MarkDecorator 对象,用于标记测试
  13.    这是一个特殊方法 __call__,用于定义对象被调用时的行为。
  14.    在 pytest 中,它被用于实现标记装饰器(MarkDecorator)的功能。
  15.    参数说明:
  16.    - condition: 主要条件参数,可以是字符串或布尔值。如果条件为 True 或非空字符串,标记会生效。
  17.    - *conditions: 可变参数,允许传递多个条件。所有条件会被组合起来,决定标记是否生效。
  18.    - reason: 字符串参数,用于说明标记的原因。例如,跳过一个测试时,可以提供一个跳过的原因。
  19.    - run: 布尔值参数,用于控制是否运行测试。如果为 False,测试会被跳过。
  20.    - raises: 异常类型参数,用于指定测试是否应该抛出特定异常。如果测试没有抛出指定异常,测试会失败。
  21.    - strict: 布尔值参数,用于控制是否严格匹配异常。如果为 True,测试抛出的异常必须完全匹配 raises 参数指定的异常类型。
  22.    返回值:
  23.    - 返回一个 MarkDecorator 对象,用于标记测试。
  24. """
  25. @pytest.mark.xfail()
  26. def test_xfail1():
  27.     assert 11 + 1 == 12
  28. @pytest.mark.xfail(reason="运算错误")
  29. def test_xfail2():
  30.     assert 5 + 5 == 11
  31. # condition为True, 一定要加上reason
  32. # strict 参数用于控制是否将 XPASS 视为失败。如果 strict=True,XPASS 会被视为失败
  33. @pytest.mark.xfail(strict=True)
  34. def test_xfail3():
  35.     assert 1 + 1 == 2
复制代码
strict为True 

 @pytest.mark.patametrize


使用pytest -k 测试方法名  只运行该测试方法
代码:
单个参数

  1. # parametrize 用于对测试方法进行数据参数化,使得同一个测试方法结合
  2. # 不同的测试数据也可以达到同时测试的目的
  3. import pytest
  4. list_one = [1, 2, 3, 4]
  5. """
  6. 1. 如果argnames只有一个名称, 则argvalues要以列表的形式给出值
  7. 2. 如果argnames有多个名称,则argvalues需要以列表嵌套元组的形式给出值
  8. 3. 如果parametrize的参数名称和fixture一样,会覆盖掉fixture
  9. e.g:
  10. @parametrize('arg1',[1,2]) 将对测试函数调用两次
  11. ...第一次调用arg1=1, 第二次调用arg1=2
  12. @parametrize('arg1','arg2',[(1,2),(3,4)] 将对测试函数调用两次
  13. ...第一次调用: arg1=1, arg2=2 第二次调用arg1=3, arg2=4
  14. """
  15. @pytest.mark.parametrize('number', list_one)
  16. def test_parametrize1(number):
  17.     assert number in list_one
复制代码

多个参数 

  1. # 多个参数
  2. list_two = [(1, 2, 3), (2, 3, 4), (3, 4, 7)]
  3. @pytest.mark.parametrize('num1,num2,sum', list_two)
  4. def test_parametrize2(num1, num2, sum):
  5.     assert num1 + num2 == sum
复制代码

直接标记 

mark标记是通过在测试方法上添加装饰器举行标记,尚有一种标记方法是在下令行中使用参数举行标记
使用参数举行标记的方法有两种:

  • 第一种是直接标记:只运行某个固定的py文件,或在py文件后添加双引号::运行固定的测试方法
  • 通过参数-k举行暗昧匹配标记

    假设是test.example.py

  • pytest   test.example.py 只运行这个py文件

 添加双引号,只运行这一个方法
pytest test.example.py::test_add

也可以实行多个方法

暗昧匹配标记 

在直接标价中一次只能实行一个测试文件大概方法,如果一次实行多个测试方法可以使用暗昧匹配标记,暗昧匹配使用起来很简朴:
   pytest -k 下令 举行匹配标记即可
  pytest -v -k  信息更详细一些
  

 使用mark自界说标记

我们根据mark举行自界说标记,只需在测试方法前添加装饰器 pytest.mark.标记名
标记名发起根据项目取比力容易世标的词,比方:commit, mergerd, done, undo等
在下令模式下使用时:只必要通过参数 -m 加上标记名就可实行被标记的测试方法
创建一个test_customize.py
  1. import pytest
  2. def add_number(a, b):
  3.     return a + b
  4. @pytest.mark.done
  5. def test_add1():
  6.     assert add_number(2, 3) == 5
  7. @pytest.mark.undo
  8. def test_add2():
  9.     assert add_number(2, 3) == 4
  10. @pytest.mark.undo
  11. def test_add3():
  12.     assert add_number(3, 3) == 6
复制代码

pytest在实行通过 -m 参数只实行被done标记的测试方法,使用下令 pytest -v -m 'done'
 第三章 固件Fixture

简介:
   Fixture 中文称为固件大概夹具,用于测试用例实行前的数据准备、环境搭建和测试用例实行后的数据烧毁、环境规复等工作,与单元测试框架UnitTest中的setup、teardown功能雷同,但是pytest框架提供的fixture更机动,不但答应代码在运行时旨在某些特定测试用例前实行,而且还可以在测试用例和测试用例之间通报参数和数据
  fixture的使用

如果要将一个方法作为fixture使用,只必要在该方法前添加装饰器@pytest.fixture()即可
  1. import pytest
  2. @pytest.fixture()
  3. def fixture_prepare():
  4.     print("\nthis is fixture prepare")
  5. def test_fixture1(fixture_prepare):
  6.     print('test_fixture1')
  7. def test_fixture2(fixture_prepare):
  8.     print('test_fixture2')
  9. if __name__=='__main__':
  10.     pytest.main(['-s','test.fixture.py'])
复制代码
实行结果:可以看到每一个case实行之前都实行了fixture_prepare
fixture参数 



  • scope:界说fixture的作用域,有4组可选参数:function,class, module,package/session,默以为function
  • params:一个可选的参数列表,会使多个参数调用fixture函数和全部测试使用它
  • autouse:如果为True,则全部方法都会实行固件方法,如果为False(默认值),则支队天界了固件方法的测试方法实行固件方法
  • ids:每个参数都与列表中的字符串id对应,因此他们是测试id的一部门,如果没有提供id将会从参数中自动天生
  • name: Fixture的名称,默以为装饰器的名称,如果Fixture在与他界说的模块中使用,那么这个fixture的功能名称将被哀求的fixture功能参数掩蔽。可以用该国将装饰函数定名为”fixture_fixturename" 然后使用“@pytest.fixture(name='fixturename')办理这个标题
fixture的作用域 

fixture的作用域用来指定固件使用的范围,固件的使用范围可以通过scope参数举行声明
   function:函数级别,默认级别,每个测试方法实行前都会实行一次
  class:类界别,每个测试类实行前实行一次
  module:模块级别,每个模块实行前实行一次,也就是每个.py文件实行前都会实行一次
  session:会话级别,一次测试只实行一次,即多个文件调用一次,可以跨.py文件
  1. import pytest
  2. @pytest.fixture(scope='session')
  3. def sesseion_fixture():
  4.     pass
  5. @pytest.fixture(scope='module')
  6. def module_fixture():
  7.     pass
  8. @pytest.fixture(scope='class')
  9. def class_fixture():
  10.     pass
  11. @pytest.fixture(scope='function')
  12. def function_fixture():
  13.     pass
  14. def test_fixture(sesseion_fixture, module_fixture, class_fixture, function_fixture):
  15.     pass
  16. if __name__ == '__main__':
  17.     pytest.main(['--setup-show', 'fixture_scope.py'])
复制代码
下令:
  1. pytest --setup-show fixture_scope.py
复制代码
 

 使用参数 --setup-show(检察详细的setup和teardown)次序,从图中可以看到显着的作用域表现符号
S:session会话级别
M:module
C:class级别
F:function函数级别
@pytest.mark.usefixtures()

当用例必要调用fixture时,可以用过直接在用例里加fixture参数,如果一个测试class类中全部的测试方法都必要用到fixture,美分用例都去传参会比力贫苦,这个时间选择在class类上使用装饰器,@pytest.mark.usefixtures修饰,使整个class都调用Fixture
在运行 pytest 时,添加 -s 选项以表现 print 语句的输出:
  1. import pytest
  2. from fixture_scope import function_fixture
  3. @pytest.mark.usefixtures('function_fixture')
  4. class TestFixture:
  5.     def test_fixture1(self):
  6.         pass
  7.     def test_fixture2(self):
  8.         pass
复制代码
  注意:Fixture有返回值,而usefixtures无法获取到返回值,则不再实用 
  实行结果

autouse(自动使用)

我们可以看到测试方法通过参数名称可以使用测试固件,但是当测试方法特殊多时,每次传入参数特殊贫苦,为了办理这一标题,Fixture提供了autouse,可以自动将测试固件添加到测试方法上。autouse默认是False, 不启用,如果设置为True,则开启自动使用Fixture功能,着用就不必要每次必须传入参数,即可使用测试固件
  1. import pytest
  2. @pytest.fixture(autouse=True)
  3. def autouse_fixture():
  4.     print('this is autouse of fixture')
  5. def test_fixture1():
  6.     print('this is test_fixture1')
  7. def test_fixture2():
  8.     print('this is test_fixture2')
  9. if __name__ == '__main__':
  10.     pytest.main(['-s', '--setup-show', 'fixture_autouse.py'])
复制代码

运行结果可以看出:
test_fixture1和test_fixture2两个测试方法的setup和teardown都实行连固件autouse_fixture,与预期结果同等,可见autouse可以自动将测试固件添加到测试方法上
   注意:测试固件旨在测试方法   前    举行内容输出
  yeild的使用

在UnitTest单元测试框架中,有setup和teardown功能作为数据的准备和烧毁,但是autouse的示例中知道,测试固件只在测试方法运行前举行内容输出
而在测试方法完成之后没有任何输出.
如果想在测试竣过后实行利用,必要使用yield的共同,如果没有yield就相当于只有setup,没有teardown
  1. import pytest
  2. @pytest.fixture()
  3. def fixture_yield():
  4.     print('\nTest started----------我是setup')
  5.     yield
  6.     print('\nEnd of test------------我是teardown')
  7. def test_yield(fixture_yield):
  8.     print('\n数据销毁测试')
复制代码
运行下令: pytest -s --setup-show test_yield.py
 

可以看出:测试用例在实行前实行连yield关键词之前的语句,测试用例实行后实行了yield关键词之后的语句
注意点:



 共享Fixture功能

很多测试用例的前置条件都存在雷同的内容,好比一个配景管理体系的测试,登录是绕不外去的,如果每一个测试用例都要复写一边登录显然不公道。因此将登录写成一个方法,然后共享给全部必要使用的测试用例即可到达服用的目标;在pytest框架下提供了一个共享fixture的功能
   只必要创建一个名为conftest.py的文件,将共享的功能在内里界说,其他测试文件在运行时会自动查找
  在使用conftest.py文件时的注意点:


  • conftest.py文件名称必要固定,不能更改
  • conftest.py必要与运行的用例文件在同一个package下,而且存在__init__.py文件
  • 使用conftest.py时不必要import导入,pytest用例会自动辨认
  • 如果conftest.py放在项目标根目次下,则对全局见效。如果放在某个package下,则只对package下的用例文件神效,答应存在多个conftest.py文件
  • conftest.py文件不能被其他文件导入
  • 全部同目次测试文件运行前都会实行conftest.py文件
创建文件:FileConftest

conftest.py
  1. # 定义一个登录退出功能,在测试方法运行前进行登录,测试方法结束后退出登录
  2. # 并且给登录退出方法加上Fixture装饰器@pytest.fixture
  3. import pytest
  4. @pytest.fixture()
  5. def signin_signout():
  6.     print('\n成功登陆到系统') #setup
  7.     yield
  8.     print('\n退出系统') #teardown
复制代码
test_file1:
  1. import pytest
  2. def test_conftest1(signin_signout):
  3.     print("第一个测试方法进行操作")
复制代码
test_file2:
  1. import pytest
  2. def test_conftest2(signin_signout):
  3.     print("第2个测试方法进行操作")
  4. def test_conftest3(signin_signout):
  5.     print("第3个测试方法进行操作")
复制代码

 在下令行模式下进入FileConftest目次,使用pytest  -v -s运行脚本,在控制台输出测试结果

conftest.py的登录退出的作用域是函数级别的,以是步调运行中每个测试方法都会实行
如果想过要登录退出功能在步调运行过程中只运行一次,那么只必要将Fixture的作用域改成session 
参数化

在mark标记中已经相识到可以用@pytest.mark.parametrize对测试方法举行参数化,那么在固件中也可以同样对其举行参数化,由于固件Fixture也是函数。与pytest.mark.parametrize差别的是,Fixture参数化是通过参数params实现的
同一个测试方法大概必要差别的参数来构造逻辑根本雷同,环境大概结果稍微有所差别的场景,这时间可以使用Fixture的参数化([arametrizing)来镌汰重复工作。比方测试两个数的和的一个测试方法,则可使用参数化举行测试
  1. import pytest
  2. # params: Iterable[object] | None = None,
  3. @pytest.fixture(params=[(1, 3, 4), (2, 4, 6), (12, 33, 45)])
  4. def test_params(request):
  5.     print(request)
  6.     return request.param
  7. def test_add(test_params):
  8.     assert test_params[2] == test_params[0]+test_params[1]
复制代码
 实行固件参数化会使用pytest中内置的固件request,并通过request.param来获取参数,代码竣过后,可以看到运行了3次,有3组测试数据

内置Fixture

# 如果有空会继承更新,感谢你的支持~ 
后续是:
pytest插件
插件的安装和卸载
检察活动插件
插件的注销
allure测试陈诉
allure的安装
脚本应用
陈诉天生

总结

路漫漫其修远兮,后续更新自动化项目实战,一些列子





回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表