pytest 教程(2)之前后置方法和 fixtur机制


前言
苦练七十二变,才能笑对八十一难
各位读者朋友你们好,我是软件测试凡哥,首先很感谢在茫茫文海中的你点进了这篇文章,我希望在我的文章里你能得到你想要的了解的知识,但不管收获多少你让我们感谢这次相遇,好了话不多说,我们开始进入正题。
上一篇文章入门篇咱们介绍了pytest的基本使用,这一篇文章专门给大家讲解pytest中关于用例执行的前置步骤处理,pytest中用例执行的前后置处理既可以通过测试夹具(fixtrue)来实现,也可以通过xunit 风格的前后位置方法来实现。接下来我们一起看看如何使用。

一、xunit 风格的前后置方法

1、函数用例的前后置方法

在模块中以函数形式定义用例,可以通过 setup_function 和 teardown_function 来定义函数用例的前后置方法,使用案例如下:

	
def setup_function(function): print("函数用例前置方法执行") def teardown_function(function): print("函数用例后置方法执行") def test_01(): print('----用例方法01------')
运行结果:

	
C:\testcases>pytest -s ========================= test session starts ========================= platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 cachedir: .pytest_cache rootdir: C:\testcases plugins: testreport-1.1.2 collected 1 item test_demo.py 函数用例前置方法执行 ----用例方法01------ . 函数用例后置方法执行 ========================= 1 passed in 0.27s =========================

2、测试类中用例的前后置方法

  • 类级别的前后位置方法
  • pytest 测试类级别的前后位置方法 setup_class和teardown_class,分别在测试类中的用例执行之前执行,和测试类中所有用例执行完毕之后执行,具体使用如下:
  • class TestDome: def test_01(self): print('----测试用例:test_01------') def test_02(self): print('----测试用例:test_02------') @classmethod def setup_class(cls): print("测试类前置方法---setup_class---") @classmethod def teardown_class(cls): print("测试类后置方法---teardown_class---")
  • 用比例级别的前后位置方法
  • pytest 测试类中用例级别的的前后置方法 setup_method和teardown_method,分别在测试类中的用例执行之前执行,和测试类中所有用例执行完毕之后执行,具体使用如下:
  • class TestDome: def test_01(self): print('----测试用例:test_01------') def test_02(self): print('----测试用例:test_02------') @classmethod def setup_class(cls): print("测试类前置方法---setup_class---") @classmethod def teardown_class(cls): print("测试类后置方法---teardown_class---") def setup_method(function): print("测试用例前置方法---setup_method---") def teardown_method(function): print("测试用例后置方法---teardown_method---")
运行结果:

	
C:\testcases>pytest -s ==================== test session starts ==================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins: testreport-1.1.2 collected 2 items test_demo.py 测试类前置方法---setup_class--- 测试用例前置方法---setup_method--- ----测试用例:test_01------. 测试用例后置方法---teardown_method--- 测试用例前置方法---setup_method--- ----测试用例:test_02------. 测试用例后置方法---teardown_method--- 测试类后置方法---teardown_class--- ==================== 2 passed in 0.30s =======================

3、模块级别的前后置方法

pytest 中还有 setup_module和teardown_module 这两个用来设置模块级别前后置方法的函数,定义在模块中,会在整个模块中所有的用例执行前和用例全部执行完毕之后会执行,具体使用如下:

	
class TestDome: def test_01(self): print('----测试用例:test_01------') class TestDome2: def test_02(self): print('----测试用例:test_02------') def setup_module(module): print("测试模块的前置方法---setup_module---") def teardown_module(module): print("测试模块的前置方法---teardown_module---")
运行结果:

	
C:\testcases>pytest -s ====================== test session starts ====================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins:testreport-1.1.2 collected 2 items test_demo.py 测试模块的前置方法---setup_module--- ----测试用例:test_01------ .----测试用例:test_02------ .测试模块的前置方法---teardown_module--- ====================== 2 passed in 0.27s ======================

二、fixture 机制

前面我们介绍了 pytest 中 xunit 风格的前后置方法,接下来我们来看一下 pytest ***能更加强大的 fixture 机制(测试夹具)的使用。

1、测试夹具的级别和定义

测试夹具需要使用 pytest.fixture 这个装饰器来定义,pytest 中的测试夹具有如下几个级别:用例级别、测试类级别、模块级别,包级别,会话级别。接下来我们一起来看看夹具的定义语法。
夹具定义可以通过参数 scope 指定夹具的级别,如果不指定夹具级别,scope 默认值为 function(用例级别) 用例级别:scope = function 测试类型:scope = class 模块级别:scope = module 包级别: scope = package 会话级别:scope = session

	
@pytest.fixture(scope='指定夹具的级别') def work(): # 前置执行脚本 yield # 后置执行脚本
测试夹具本质上是一个生成器函数,生产器函数在使用 next 进行迭代时,执行到 yeild 会返回数据,暂停执行,等待下一次进行迭代时才会继续执行,pytest 夹具就是利用的生成器的机制,通过 yeild 在测试夹具将前后置代码分开执行。
注意点: 夹具只有在定义夹具的范围内才能使用。如果夹具是在类中定义的,则只能由该类内的测试用例使用。但是如果在模块的全局范围内定义的夹具,那么该模块中的每个测试用例,即使它是在一个类中定义的,都可以使用它。
知道了怎么定义夹具,那么接下来我们来看看如何使用夹具。

2、夹具的使用

测试夹具定义好之后,测试函数通过将它们声明为参数,来指定执行用例之前要执行的夹具。
当 pytest 开始运行测试时,它会查看该测试函数定义地形参,然后搜索与这些参数同名的测试夹具。一旦 pytest 找到它们,它就会运行这些夹具,接收它们返回的内容(如果有的话),并将这些返回内容作为参数传递给测试函数。
注意点:当我们使用夹具时,如果夹具的前置脚本执行完,有数据要传递用例,需要传递的数据写在 yield 后面即可,在使用夹具的用例或者方法中,可以通过定义地形参来获取 yeild 返回的数据(章节 2.3 中有使用案例介绍)

2.1、在用例中使用夹具

不管是函数形式定义的测试用例,还是测试类中方法的形式定义的用例,在使用的时候都是一样的,直接定义一个和要使用的夹具同名的形参即可。

	
import pytest # 定义一个用例级别的夹具 @pytest.fixture def my_fixture(): print('------my_fixture---用例前置执行脚本--------') yield print('------my_fixture---用例后置执行脚本--------') # 函数用例 指定测试夹具 def test_func__01(my_fixture): print("测试用例----test_func__01----") class TestDome: # 函数用例 指定测试夹具 def test_02(self, my_fixture): print('----测试用例:test_02------') # 函数用例 指定测试夹具 def test_03(self): print('----测试用例:test_03------')
运行结果

	
C:\testcases>pytest -s ======================== test session starts ======================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins: testreport-1.1.2 collected 2 items test_demo.py ------my_fixture---前置执行脚本-------- 测试用例----test_func__01----. ------my_fixture---后置执行脚本-------- ------my_fixture---前置执行脚本-------- ----测试用例:test_02------. ------my_fixture---后置执行脚本-------- ----测试用例:test_03------ ======================== 2 passed in 0.27s ========================
上面 test_func__01和test_02 这两个用例在定义时指定了测试夹具,而 test_03 则没有指定执行的夹具,执行用例时库看到指定了夹具的用例,执行了对应的夹具。

2.2、测试类和模块指定夹具

上面我们通过给用例方法加形参来给单个测试用例指定测试夹具。如果一个测试类中有很多测试用例或者一个模块中有很多用例,都要指定同一个测试夹具,要我们则可以通过 usefixtures 给测试类或测试模块指定测试夹具。
给测试类中所有的用例指定夹具

	
# TestDome这个测试类的所有测试用例均执行my_fixture这个夹具 @pytest.mark.usefixtures('my_fixture这个夹具') class TestDome: # 函数用例 指定测试夹具 def test_02(self): print('----测试用例:test_01------') # 函数用例 指定测试夹具 def test_03(self): print('----测试用例:test_02------')
使用 pytestmark 在测试模块级别 指定模块所有用例执行的夹具

	
# test_demo.py # 当前模块中所有的用例,均执行my_fixture这个测试夹具 pytestmark = pytest.mark.usefixtures('my_fixture') # 函数用例 指定测试夹具 def test_func__01(my_fixture): print("测试用例————test_func__01——————") class TestDome: # 函数用例 指定测试夹具 def test_02(self): print('----测试用例:test_01------') # 函数用例 指定测试夹具 def test_03(self): print('----测试用例:test_02------')

2.3、在夹具中引用夹具

pytest 的最大优势之一是其极其灵活的夹具系统。通过测试夹具我们可以将极为复杂化的前后置依赖,拆分为更简单单一功能的测试夹具,通过在夹具中引用其他的夹具,来组织不同用例所需的复杂依赖环境。接下来我们通过一个案例来给大家演示如何使用。

	
import pytest # 用户注册的夹具 @pytest.fixture def register_user(): print('---用户注册的夹具前置执行----') # ...注册代码省略,注册的用户信息如下 user_info = {'user': 'lemonban', 'pwd': '123456'} yield user_info print('---用户注册的夹具后置执行----') # 用户登录的夹具,通过定义形参来使用register_user这个夹具 @pytest.fixture def user_login(register_user): print('---用户登录的夹具前置执行----') # 获取register_user结局前置脚本执行完,yeild传递出来的数据 user_info = register_user # ...登录代码省略,下面为登录得到的token token = 'sdjasjdask' yield token print('---用户登录的夹具后置执行----') # 函数用例 指定使用测试夹具user_login def test_func__01(user_login): token = user_login print("测试用例夹具user_login传递过来的token:",token) print("测试用例---test_func__01---")
运行结果

	
C:\testcases>pytest -s ======================== test session starts ======================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins: testreport-1.1.2 collected 1 item test_demo.py ---用户注册的夹具前置执行---- 夹具register_user传递过来的用户信息: {'user': 'lemonban', 'pwd': '123456'} ---用户登录的夹具前置执行---- 测试用例夹具user_login传递过来的token: sdjasjdask 测试用例---test_func__01---. ---用户登录的夹具后置执行---- ---用户注册的夹具后置执行----

2.4、自动使用夹具

在定义测试夹具 我们可以给夹具的装饰器加参数 autouse=True 来使夹具成为自动执行的夹具。具体案例如下:

	
import pytest @pytest.fixture(autouse=True) def my_fixture(): print('------my_fixture---前置执行脚本--------') yield print('------my_fixture---后置执行脚本--------') class TestDome: # 函数用例 指定测试夹具 def test_02(self): print('----测试用例:test_01------') # 函数用例 指定测试夹具 def test_03(self): print('----测试用例:test_02------') class TestDome2: # 函数用例 指定测试夹具 def test_03(self): print('----测试用例:test_03------')
执行结果:

	
C:\testcases>pytest -s ======================== test session starts ======================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins: testreport-1.1.2 collected 3 items test_demo.py ------my_fixture---前置执行脚本-------- ----测试用例:test_01------. ------my_fixture---后置执行脚本-------- ------my_fixture---前置执行脚本-------- ----测试用例:test_02------. ------my_fixture---后置执行脚本-------- ------my_fixture---前置执行脚本-------- ----测试用例:test_03------. ------my_fixture---后置执行脚本-------- ======================== 3 passed in 0.29s ========================
从上面的执行结果我们可以看到,每条用例执行之前都自动执行了测试夹具 my_fixture

3、conftest.py

在一个项目的测试中,大多数情况下会有多个类、模块、或者包要使用相同的测试夹具。这种情况下如果我们把测试夹具定义在某一个模块中则无法实现共享,针对这种情况,我们可以把需要共享的测试夹具放入一个单独的 conftest.py 文件中 ,这样多个可以实现多个测试模块共享了
ps : pytest 运行测试时,如果项目中有 conftest.py,那么 pytest 会自动加载 conftest.py 模块中的内容,可以把 conftest 看出 pytest 会自动加载的插件模块,后续的教程中会涉及到在 conftest.py 中定义 pytest 的 hooks 函数
接下来我们来看一个 conftest.py 定义测试夹具的案例
在 conftest.py 中定义测试夹具 my_fixture

	
# conftest.py import pytest @pytest.fixture def my_fixture(): print('------my_fixture---前置执行脚本--------') yield print('------my_fixture---后置执行脚本--------')
在 test_demo1.py 的用例用使用 conftest.py 中定义的夹具

	
# test_demo1.py class TestDome: # 函数用例 指定测试夹具 def test_02(self,my_fixture): print('----测试用例:test_01------') # 函数用例 指定测试夹具 def test_03(self,my_fixture): print('----测试用例:test_02------')
在 test_demo2.py 的用例用使用 conftest.py 中定义的夹具

	
# test_demo2.py class TestDome2: # 函数用例 指定测试夹具 def test_03(self,my_fixture): print('----测试用例:test_03------')
执行结果:

	
C:\testcases>pytest -s ======================== test session starts ======================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 rootdir: C:\testcases plugins: testreport-1.1.2 collected 3 items test_demo.py ------my_fixture---前置执行脚本-------- ----测试用例:test_01------. ------my_fixture---后置执行脚本-------- ------my_fixture---前置执行脚本-------- ----测试用例:test_02------. ------my_fixture---后置执行脚本-------- test_demo2.py ------my_fixture---前置执行脚本-------- ----测试用例:test_03------. ------my_fixture---后置执行脚本-------- ======================== 3 passed in 0.29s ========================
上述案例中我们可以发现 est_demo.py和est_demo2.py 中的用例可以成功使用 conftest.py 中的测试用例。
pytest基本的入门就给大家介绍到这里了,感谢您的认真阅读,不二也会写出更优质的文章的,敬请期待哦!

写在最后

最后再唠唠一句,如果想以测试为长期发展职业目标,是需要时刻保持学习的,要使自己具备竞争力,无论你现在工作几年,只要行动起来,你就已经占优势了,好啦就到这里了,祝大家2022年能升职加薪,拿到心仪公司的offer,事事顺遂。
这份软件测试学习资源整理起来也不容易,希望大家帮忙给「点赞」「收藏」,咱不做白嫖党!!

#软件测试##Python##测试##测试工程师#
全部评论

相关推荐

不愿透露姓名的神秘牛友
02-14 11:10
点赞 评论 收藏
分享
评论
1
5
分享

创作者周榜

更多
牛客网
牛客企业服务