目录
第 2 章 fixture
Fixture 是 pytest 的核心功能,本章单独拿出来详细讲解。只有熟练掌握了 fixture 的用法才 是真正的懂了 pytest 框架,写起用例来也就得心应手了。
2.1fixture 作为参数传入
fixture 是 pytest 的核心功能,也是亮点功能,必须熟练掌握 fixture 的使用方法。
fixture 简介
fixture 的目的是提供一个固定基线,在该基线上测试可以可靠的和重 复的执行。fixture 提供了区别于传统单元测试(setup/teardown)有 显著改进:
- 有独立的命名,并通过声明它们从测试函数、模块、类或整个项 目中的使用来激活。
- 按模块化的方式实现,每个 fixture 都可以互相调用。
- fixture 的范围从简单的单元扩展到复杂的功能测试,允许根据配 置和组件选项对 fixture 和测试用例进行参数化,或者跨函数 function、类 class、模块 module 和整个测试会话 sessio 范围。
fixture 作为参数传入
定义 fixture 跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(), fixture 命名不要用 test_开头,跟用例区分开。用例才是 test_开头的命名。 fixture 是可以有返回值的,如果没 return 默认返回 None。用例调用 fixture 的返回值,直接 就是把 fixture 的函数名称当成变量名称,如下案例:
运行结果
2.2 error 和 failed 区别
用例出现 error 和 failed 有什么区别呢?很多初学者会有返个疑惑,本 篇详细讲解什么情况会出现 error。
error 和 failed 区别
测试结果一般有三种:passed、failed、error。(skip(跳过) 的用例除外)
如果在 test_用例里面断言失败,那就是 failed
如果在 fixture 里面断言失败了,那就是 error
还有一种情况也会出现 error,那就是自己代码写的有问题,自己本身代码报错, 那就是 error 了。测试报告里面应该尽量少出现 error,报告里面 error 越多, 说明测试用例质量越差
2.3 使用多个 fixture
使用多个 fixture
如果用例需要用到多个 fixture 的返回数据,fixture 也可以 return 一个元组、 list 或字典,然后从里面取出对应数据。
ps:此处代码有误,应该为return(a,b)返回一个元组,u和p取元组下标
当然也可以分开定义成多个 fixture,然后 test_用例传多个 fixture 参数
2.4 fixture 与 fixture 互相调用
fixture 与 fixture 直接也能互相调用的
运行结果
2.5 fixture 作用范围
fixture 作用范围
fixture 里面有个 scope 参数可以控制 fixture 的作用范围:session > module > class > function
fixture(scope="function", params=None, autouse=False, ids=None, name=None): """使用装饰器标记 fixture 的功能:
可以使用此装饰器(带或不带参数)来定义 fixture 功能。 fixture 功能 的名称可以在以后使用
引用它会在运行测试之前调用它:test 模块或类可以使用 pytest.mark.usefixtures(fixturename) fixtuer的名称标记。需要在用例前声明调用
测试功能可以直接使用 fixture 名称作为输入参数,在这种情况下,夹具 实例从 fixture 返回功能将被注入:在方法中传入fixture名称
- :arg scope: scope 有四个级别参数 "function" (默认), "class", "module" or "session".
- :arg params: 一个可选的参数列表,它将导致多个参数调用 fixture 功能 和所有测试使用它
- :arg autouse: 如果为 True,则为所有测试激活 fixture func 可以看到 它。 如果为 False(默认值)则显式需要参考来激活 fixture
- :arg ids: 每个字符串 id 的列表,每个字符串对应于 params 这样他们就 是测试 ID 的一部分。 如果没有提供 ID 它们将从 params 自动生成
- :arg name: fixture 的名称。 这默认为装饰函数的名称。 如果 fixture 在定义它的同一模块中使用,夹具的功能名称将被请求夹具的功能 arg 遮蔽; 解 决这个问题的一种方法是将装饰函数命名:“fixture_ <fixturename>”然后使用”@ pytest.fixture(name='<fixturename>')
- function 每一个函数或方法都会调用
- class 每一个类调用一次,一个类可以有多个方法
- module,每一个.py 文件调用一次,该文件内又有多个 function 和 class
- session 是多个文件调用一次,可以跨.py 文件调用,每个.py 文件就是 module
scope="function"
@pytest.fixture()如果不写参数,默认就是 scope="function",它的作用范围 是每个测试用例来之前运行一次,销毁代码在测试用例运行之后运行。
运行结果
用例放到类里面也一样
运行结果
scope="class"
fixture 为 class 级别的时候,如果一个 class 里面有多个用例,都调用了此 fixture,那么此 fixture 只在该 class 里所有用例开始前执行一次
运行结果
scope="module"
fixture 为 module 级别时,在当前.py 脚本里面所有用例开始前只执行一次
运行结果
scope="session"
fixture 为 session 级别是可以跨.py 模块调用的,也就是当我们有多个.py 文件 的用例时候,如果多个用例只需调用一次 fixture,那就可以设置为 scope="session",并且写到 conftest.py 文件里
conftest.py 文件名称是固定的,pytest 会自动识别该文件。放到工程的根目录 下,就可以全局调用了,如果放到某个 package 包下,那就只在该 package 内有 效
cnoftest.py
test04.py
运行结果
2.6 装饰器 usefixture
当用例需要调用 fixture 时,前面讲到可以直接在用例里加 fixture 参数,如果 一个测试 class 都需要用到 fixture,每个用例都去传参,会比较麻烦,这个时 候,可以在 class 外面加 usefixture 装饰器,让整个 class 都调用 fixture 调用 fixture 三种方法
- 函数或类科目方法直接传 fixture 的函数参数名称
- 使用装饰器@pytest.mark.usefixtures()修饰
- autouse=True 自动使用
用例传 fixture 参数
方法一:先定义 start 功能,用例全面传 start 参数,调用该功能
装饰器 usefixtures
方法二:使用装饰器@pytest.mark.usefixtures()修饰需要运行的用例
叠加 usefixtures
如果 class 用例需要同时调用多个 fixture,可以使用 @pytest.mark.usefixtures()叠加。 注意叠加顺序,先执行的放底层,后执行的放上层
运行结果
usefitures 与传 fixture 区别
提供上面 2 个案例,对 usefixtures 使用基本方法已经掌握了,但是你 会发现,上面给的 2 个案例的 fixture 是没有返回值的。如果 fixture 有返回值,那么 usefixtures 就无法获取到返回值了,这个是它与用例 直接传 fixture 参数的区别。
也就是说当 fixtire 的 return 值需要使用时,叧能在用例里面传 fixture 参数了。
当 fixture 没有 return 值时候,两种方法都可以
2.7 fixture 自动使用 autouse=True
平常写自动化用例会写一些前置的 fixture 操作,用例需要用到就 直接传该函数的参数名称就行了。当用例很多的时候,每次都传这个参 数,会比较麻烦。
fixture 里面有个参数 autouse,默认是 Fasle 没开启的,可以设置为 True 开启自动使用 fixture 功能,返样用例就补用每次都去传参了
调用 fixture 三种方法
1.函数或类里面方法直接传 fixture 的函数参数名称
2.使用装饰器@pytest.mark.usefixtures()修饰
3.autouse=True 自动使用
1和2方法前面有讲到
设置 autouse=True
方法三、autouse 设置为 True,自动调用 fixture 功能
start 设置 scope 为 module 级别,在当前.py 用例模块叧执行一 次,autouse=True 自动使用
open_home 设置 scope 为 function 级别,每个用例前都调用 一次,自动使用
运行结果
上面是函数去实现用例,写的 class 里也是一样可以的
2.8 conftest.py 作用范围
一个测试工程下是可以有多个 conftest.py 的文件,一般在工程根目录放一个 conftest.py 起到全局作用。 在不同的测试子目录也可以放 conftest.py,作用范围只在该层级以及以下目录 生效。
conftest 层级关系
在 web_conf_py 项目工程下建两个子项目 baidu、blog,并且每个目录下都放一 个 conftest.py 和__init__.py(python 的每个 package 必须要有__init__.py)
层级关系总结:工程文件的conftest.py>子模块的
子模块可以调用 工程文件的conftest.py
子模块之间的conftest.py不能相互调用