Pytest就是为了测试已经完成的Python功能代码符不符合。但测试和开发一样,需要极具规范的流程,即覆盖广(广不是全100%)且精准。
相当于pip一个python库
pip install pytest
Pytest之所以称之为全功能测试框架,得益于它能通过外部插件或者自定义插件的形式扩展所需的功能,其它插件安装:
pip install pytest-json-report: 生成json
pip install pytest-ordering
pip install allure-pytest: 生成可视化报告
pip install pytest-xdist: 分布式测试
pip install pytest-cov: 生成测试覆盖率报告
pip install pytest-pep8: 检测代码是否符合 PEP8 规范
pip install pytest-flakes: 检测代码风格
pip install pytest-html: 生成 html 报告
pip install pytest-randomly: 测试顺序随机
pip install pytest-rerunfailures: 失败重试
pip install pytest-timeout: 超时测试
用例python文件:所有文件名为 test_ 开头 或者 _test 开头的文件会被识别为用例文件。
用例类:测试文件中每个test开头的类就是一个测试用例类。
测试用例:测试类中每个test开头的方法就是一条测试用例,测试文件中每个test开头的函数也是一条测试用例,
推荐的书写:
test_demo1.py …test_demo1.py …test_demo1.py (文件)
class Test_demo1:…class Test_demo2:…class Test_demo3:(类形式编写用例)
def test_demo1():…def test_demo2():…def test_demo3():…(函数形式编写用例)
assert是pytest中的关键词,必须使用的,专业称为断言,个人理解就是特殊的IF判断语句,例如:
def test_demo1():
assert 100 == 100
输出:
collected 1 item
test_demo1.py . [100%]
====================== 1 passed in 0.25s ======================
附:
pip install pytest-repeat
使用:
–count命令,指定要运行测试用例和测试次数:pytest --count=10 test_demo.py
注:
–repeat-scope类似于 @pytest fixture()的scope参数,
–repeat-scope也可设置参数: 默认的function、module、session 、class
使用:pytest test_demo.py -s --count=5 --repeat-scope=session
另:
结合使用mark标记来重复执行:
@pytest.mark.repeat(count)
参数
python3 -m pytest [...]
usage: py.test [options] [file_or_dir] [file_or_dir] [...]
py.test --version 查看版本
py.test --fixtures, --funcargs 查看可用的 fixtures
pytest --markers 查看可用的 markers
py.test -h, --help 命令行和配置文件帮助
# 失败后停止
py.test -x 首次失败后停止执行
py.test --maxfail=2 两次失败之后停止执行
# 调试输出
py.test -l, --showlocals 在 traceback 中显示本地变量
py.test -q, --quiet 静默模式输出
py.test -v, --verbose 输出更详细的信息
py.test -s 捕获输出, 例如显示 print 函数的输出
py.test -r char 显示指定测试类型的额外摘要信息
py.test --tb=style 错误信息输出格式
- long 默认的traceback信息格式化形式
- native 标准库格式化形式
- short 更短的格式
- line 每个错误一行
# 运行指定 marker 的测试
pytest -m MARKEXPR
# 运行匹配的测试
py.test -k stringexpr
#执行选择用例
# 只收集并显示可用的测试用例,但不运行测试用例
py.test --collect-only
#或者
pytest --co
# 失败时调用 PDB
py.test --pdb
#如果要从默认的查找规则中忽略查找路径,可以加上 --ingore 参数,例如:
pytest --ignore=test_case/xxx.py
#执行选择用例
#1、执行单个模块中的全部用例:
py.test test_demo.py
#2、执行指定路径下的全部用例:
py.test somepath
#3、执行字符串表达式中的用例:
py.test -k stringexpr
#4、运行指定模块中的某个用例,如运行 test_demo.py 模块中的 test_func 测试函数:
pytest test_demo.py::test_func
#5、运行某个类下的某个用例,如运行 TestClass 类下的 test_method 测试方法:
pytest test_demo.py::TestClass::test_method
详解(该部分为转载+部分改正):
(1) collect-only选项
使用–collect-only选项可以展示在给定的配置下哪些测试用例会被运行
pytest --collect-only
或者
pytest --co
(2) -k选项
-k选项允许你使用表达式指定希望运行的测试用例,【根据某些条件筛选测试用例指定运行】
这个功能非常实用,如果测试名是唯一的,或者多个测试方法名/测试文件名的前缀或者后缀相同,那么则可以使用表达式快速定位
假设希望选中 test_judge_user_login_or_not.py 和 test_get_banner_HomePage 两个测试文件中的用例【可以根据筛选条件同时选择匹配多个测试】:
pytest -k "user or banner" --collect-only
当然也可以运行所有的测试,根据用例名称筛选排除掉某些用例: pytest -k “not user” --collect-only
(3) -m选项
标记(marker)用于标记测试并分组,以便快速选中并运行用例。
只能运行有相应标识的测试用例,使用这个参数,测试用例要使用@pytest.mark.【marker】修饰。【maker是标记测试方法的装饰器@pytest.mark.【maker】】
如下实例:【marker】为slow
# content of test.py
import pytest
class TestClass(object):
def test_one(self):
'''new_etests'''
x = "this"
assert 'h' in x
@pytest.mark.slow
def test_two(self): # teste_two使用了@pytest.mark.slow来修饰
'''new_sssetests'''
x = "hello"
assert hasattr(x, 'check')
def test_a(self):
assert 1==2
结果只运行了一个带有标识的用例。
如果要运行多个标识的话,用表达式,如下:
pytest -m "slow or faster" 运行有slow标识或 faster标识用例
pytest -m "slow and faster" 运行有slow和faster标识的用例
pytest -m "slow and not faster" 运行有slow和没有faster标识的用例
(4) -x选项
-x选项,当运行时候碰到一个测试用例运行失败,全局就停止,不运行其他的测试用例。
pytest -x
(5) --maxfail=num选项
-x选项的特点是,一旦遇到运行失败,整个测试就会全局停止,而–maxfail选项为允许失败的次数
pytest --maxfail=num
(6) -s选项
-s选项允许终端在测试运行时输出某些结果,包括任何符合标准的输出流信息,即print语句、log将会打印在终端上。
pytest -s
(7) --lf或者–last-failed选项
当一个或多个测试用例运行失败时,如果希望能够定位失败的测试用例并且重新运行, --lf 或者 --last-failed 可以派上用场。
即重跑上次失败的所有测试用例,如果没有失败就重跑全部。
pytest --last-failed
或者
pytest --lf
(8) --ff或者–failed-first选项
–ff(–failed-first)选项与–last-failed选项的作用基本相同。
pytest命令行运行–ff(–failed-first)时,会首先运行上一次失败的测试用例,然后才会运行剩下被选中的所有的测试用例。
pytest --ff
或者
pytest --failed-first
(9) -v(–verbose)选项
使用-v/–verbose选项,输出的信息会更详细。最明显的区别就是每个文件中的每个测试用例都占一行(而简化输出或者默认输出的终端控制台显示为一个文件一行且测试用例的成功或失败是由./F/E等区分)。
使用-v/–verbose选项,测试的名字和结果都会显示出来,而不仅仅是一个点或字符。用例执行成功或者失败会在每行【即每一个测试用例】后显示PASSED/FAILED
pytest -v
如下:每一个测试用例在终端控制台都会占一行。
(10) -q(–quiet)选项
-q(–quiet)选项与-v(–verbose)的作用相反,-q的作用是简化输出信息。
-q(–quiet)选项不显示每个用例的详细信息,可以与–tb=line(进打印异常代码的位置)结合使用
pytest -q --tb=line
例如:一个测试文件中有多个测试用例,有一个测试用例执行失败,则只会打印那一个失败的测试用例异常代码:
(11) --tb=style选项
信息回溯:某个测试用例执行失败后,pytest会列举出失败信息,包括失败出现在哪一行、是什么失败、怎么失败的、此过程我们称之为【信息回溯】
–tb=style选项决定捕捉到失败时输出信息的显示方式。
使用 --tb=no 屏蔽全部回溯信息:
使用 --tb=line ,仅仅告诉我们错误的用例执行时发生错误的位置:
使用 --tb=short ,显示的回溯信息比前面两种模式的更详细:
使用 --tb=long ,输出最为详尽的回溯信息:
使用 --tb=auto 是默认值,如果有多个测试用例执行失败,进打印第一个和最后一个测试用例的回溯信息(格式与long模式的一致):
使用 --tb=native 只输出Python标准库的回溯信息,不显示额外信息:
(12) -r(chars)选项
-r 选项不但可以帮助用户了解某些测试的原因,还可以用于查看其他测试结果。
显示 failed 的信息:pytest -r f
显示 Error 的信息:pytest -r E
显示 skipped 的信息:pytest -r s
显示 xfailed 的信息:pytest -r x
显示 Xpassed 的信息: pytest -r X
显示 passed 的信息: pytest -r p
显示 Passed with output 的信息:pytest -r P
显示 all except passed 的信息:
pytest -r a
pytest -r A
显示 warnings are enabled by default (–disable-warnings) 的信息:pytest -r w
重置 list: pytest -r N
不知为何内容没了
该部分为转载+部分改正
前言:pytest.ini文件是pytest的主配置文件,pytest.ini文件必须放在项目的根目录下,不能更改名字。该文件是一个固定的文件pytest.ini文件,通过改变、读取配置信息,可以改变pytest的运行方式;通过pytest -h查看配置选项。
常用的配置选项
(1)markers
作用:测试用例中使用@pytest.mark.slow装饰器,如果不添加markers选项就会报warning
格式:list列表类型
写法:
# file_name: pytest.ini
[pytest]
markers =
slow: run slow mark case
fast: run fast mark case
举例:
①当使用 @pytest.mark. 标记名称时,如果使用的自定义标记,当在执行测试用例追加命令行参数 -m= 标记名称时,虽然不会影响测试执行,但是在执行后会出现告警提示。
②此时可以在 pytest.ini 配置文件中增加 markers 字段注册标记名称。【将自定义的标签注册,注册后pytest可以识别出来后就不会报出警告信息】
[pytest]
# 注册标记名称
markers =
smoke: 冒烟测试用例
normal: 正常用例
③添加后字段注册标记名称后,使用 pytest --markers 命令行参数运行可以查看到添加的标记名称。
④再次执行用例:运行结果在控制台没有告警提示
【注意】:在自定义标签的的同时应该尽量避免使用如下关键字:【pytest测试框架的内置标签,可以直接使用,不需要重新在pytest.ini文件中注册】
① usefixtures ② usefixtures ③ skip ④ skipif ⑤ xfail ⑥ parametrize
(2)xfail_strict
作用:设置xfail_strict=true可以让那边标记为@pytest.mark.xfail 但实际通过显示为XPASS 的测试用例被报告为失败。
格式:True、False(默认)、1、0
# file_name: pytest.ini
[pytest]
markers =
slow: run slow mark case
fast: run fast mark case
xfail_strict = true
举例:
# file_name: test_xfail.py
import pytest
class Test_C:
@pytest.mark.xfail
def test_c(self):
print('\n------------------> test_c has ran')
a = 'hello'
b = 'hello world'
assert a != b
if __name__ == '__main__':
pytest.main(['-s', 'test_xfail.py'])
没有设置xfail_strict = True 时,测试结果显示XPASS
设置xfail_strict = True 时,测试结果显示failed
(3)addopts
作用:addopts参数可以更改默认的命令行选项,可以配置文件中配置这个参数来代替,省掉很多重复的工作。
例如:在测试结束之后,生成测试报告,失败的测试用例重跑两次,如果通过命令行输入指令来执行的话,指令会很长: pytest -v --reruns 2 --html=report.html --self-contained-html
如果每次执行都要输入上面的指令会很繁琐,可以通过配置addopts参数来解决这个问题:
# file_name: pytest.ini
[pytest]
markers =
slow: run slow mark case
fast: run fast mark case
xfail_strict = True
addopts = -v --reruns=2 --html=report.html --self-contained-html # 多个命令行参数用空格分隔开,可以添加多个命令行参数
这样加上addopts后,再次进入cmd命令行执行时,只要输入pytest就可以默认带上这些参数了。
(4)log_cli
作用:控制台实时输出日志
格式: log_cli=True 或 log_cli=False(默认),或者 log_cli=1 或 log_cli=0
①设置 log_cli=True 时,运行结果为:
② 设置 log_cli=False时,运行结果为:
结论:
当设置 log_cli=True时,在控制台使用命令行参数运行测试用例时可以看到程序里写入的日志;可以非常清晰的看出具体的是哪个package下的哪个module下的哪个测试用例是passed还是failed;
所以在调试代码是否有问题时推荐加上 log_cli=True ,当测试用例调试通过之后批量执行时就可以去掉了。
(5)norecursedirs
①norecursedirs作用:pytest在收集测试用例的时候,会递归遍历当前目录下的所有子目录,当我们需要某些目录下的用例不要执行时,就可以通过设置norecursedirs参数来实现这个功能。
# file_name: pytest.ini
[pytest]
markers =
slow: run slow mark case
fast: run fast mark case
xfail_strict = True
addopts = -v --reruns=2 --html=report.html --self-contained-html
log_cli = False
norecursedirs = venv report util log # 多个目录需要空格分开,可以配置多个
上面的配置表示venv report util log这4个目录下的用例需要过滤掉不执行。
②pytest之命令行参数 --ignore 用法
文件目录结构如下:
├── demo
├── all
│ ├── a_a_test
│ │ └── test_1.py
│ ├── b_a_test
│ │ └── test_2.py
│ └── c
│ └── test_2.py
1、忽略 c 文件夹下的脚本:
# demo.py
pytest --ignore=all/c
# c后面不要有/,也不要写成c/*
# 注意,多个目录忽略,加多个--ignore即可,中间用空格做间隔。
2、忽略某一类脚本:
# demo.py
pytest --ignore-glob='*_a_test' # glob模糊匹配文件夹
# 会忽略a_a_test 和 b_a_test 目录下的脚本
3、实例:可以作为pytest命令行参数之一集成至pytest.ini文件中的addopts参数中,与上述案例的效果相同
(6)testpaths
testpaths 是一系列相对于根目录的路径,用于限定测试用例的搜索范围。只有在pytest未指定文件目录参数或测试用例标识符时,该选项才会启用
【注意】: ./ 代表根路径,会随着你执行所在目录变化而变化,如果你执行目录下没有TestCase文件夹,那么该命令无效
pytest默认的测试用例收集规则为:
文件名匹配 test_*.py 或 *_test.py
以 test_ 开头的函数
以 Test_ 开头的类,不能包含_init_初始化方法
类中以 test_ 开头的方法
上面的默认规则我们是可以通过配置文件的设置来修改的
# file_name: pytest.ini
[pytest]
testpaths = xdist_study
python_files = test*.py
python_classes = Test*
python_functions = test_*
testpaths:配置在哪个目录下搜索测试用例,可自定义,可以配置多个,多个用空格隔开
python_files:用来配置搜索的测试用例的文件名称,可自定义,可以配置多个,多个用空格隔开
python_classes:配置搜索的测试用例的类名,可自定义,可以配置多个,多个用空格隔开
python_functions:配置搜索的测试用例的方法名,可自定义,可以配置多个,多个用空格隔开
上面的配置表示:在xdist_study目录下,搜索以test开头,以.py结尾的文件,以Test开头的类,以test_开头的方法。
(7)minversion
指定pytest的最低版本
如果使用老版本(小于3.0)pytest运行测试,就会得到一个报错信息。
pytest.ini配置文件的参数值会被命令行覆盖
当ini配置文件的参数与执行测试用例文件的命令行参数重复时,命令行参数值会覆盖ini配置文件中定义的参数值。
举例:命令行参数值为3,pytest.ini参数值为2,实际执行的参数值为3。
不知为何,内容没了。
不知为何,内容没了。
前言:项目的自动化用例有些运行较慢,会影响整体的用例运行速度,因此可以统计出来,再针对用例进行优化。
(1)统计全部用例单个的运行时间; 参数:–durations=0
(2)统计最慢的几个用例; 参数:–durations=n