Python通用测试框架大多用Unittest+HTMLTestRunner,而pytest相对该框架有丰富的plugins;
pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:
A、简单灵活,容易上手,自动化加载函数与模块;
B、支持参数化,支持运行由nose、unittest编写的测试用例,支持失败重跑,支持多线程跑用例;
C、能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appuium等自动化测试、接口测试(pytest+requests);
D、pytest具有很多第三方插件,并且可以自定义扩展,比较好用的pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等;
E、测试用例的skip和xfail处理;
F、可以很好的和Jenkins集成;
G、report---allure也支持pytest。
pytest测试样例:
A、测试文件以test_开头(以_test结尾也可以);
B、测试类以Test开头,并且不能带有init方法;
C、测试函数以test_开头;
D、断言使用基本的assert即可;
pytest运行模式:
pytest的多种运行模式,让测试和调试变得更加得心应手,运行pytest时会找当前目录及其目录中的所有test_*.py或者*_test.py格式的文件及以test开头的方法或者class,不然就会提示找不到可以运行的case;
运行后生成测试报告:
安装pytest-html:pip install -U pytest-html
运行模式:pytest --html=report.html
运行指定的case:
当我们写了较多的cases时,如果每次都要全部运行以便,无疑是浪费时间,通过指定case来运行就很方便;
运行模式:
模式1:直接运行test_se.py文件的所有cases;
模式2:运行rest_se.py文件中TestClassOne这个class下的两个cases;
模式3:运行test_se.py文件中TestClassTwo这个class下的test_one。
定义class时,需要以T开头,不然pytest是不会去执行该class的。
多进程运行cases:
当cases量很多时,运行时间也会变的很长,如果想缩短脚本运行的时长,就可以用多进程来运行;
安装pytest-xdist:pip install -U pytest-xdist
运行模式:pytest test_se.py -n NUM,其中NUM是填写并发的进程数;
重试运行cases:
在做接口测试时,有时会遇到503或短时的网络波动,导致case运行失败,此时可以通过重试运行cases的方式来解决
安装pytest-rerunfailures:pip install -U pytest-rerunfailures;
运行模式:pytest test_se.py --reruns NUM;
显示print内容:
在运行测试脚本时,为了调试或打印一些内容,我们会在代码加些print内容,但在运行pytest时,这些内容不会显示出来,如果带上-s就可以显示了;
pytest test_se.py -s
此外,pytest的多种运行模式是可以叠加的比如让4个进程运行:
pytest test_se.py -s -n 4
测试函数标记:
一个标记可以应用在多个函数上;
一个函数可以有多个标记;
被标记的在不同文件夹下也可以被执行;
应用场景:我们的目的是只做冒烟测试,没必要对全量的case进行执行,我们就可以把需要smoke的case标记为smoke就可以了,到时候我们用pytest -m "smoke" 就ok;
具体标记如下:
语法:@pytest.mark.marker_value,如果标记smoke可以用@pytest.mark.smoke
举例为:
test_assert.py
import tasks,pytest
@pytest.mark.single
@pytest.mark.smoke
def test_smoke1():
with pytest.raises(TypeError):
tasks.add(task="string")
@pytest.mark.smoke
def test_smoke2():
with pytest.raises(TypeError):
tasks.add(task="string")
def test_except():
with pytest.raises(TypeError):
tasks.add(task="string")
@pytest.mark.smoke
def test_smoke03():
with pytest.raises(TypeError):
tasks.add(task="string")
@pytest.mark.smoke
def test_smoke04():
with pytest.raises(TypeError):
tasks.add(task="string")
test_task.py
import tasks
import pytest
@pytest.mark.smoke
def test_add_exception():
with pytest.raises(ValueError):
tasks.start_tasks_db('/','mysql')
def test_smoke05():
with pytest.raises(TypeError):
tasks.add(task="string")
执行结果:
也可以标记之间使用and、or、not关键字
使用and是要有smoke和single标签才能被运行;
or是运行smoke和single标签的全部case;
not smoke是运行没有含smoke的标签;
跳过测试(skip、skipif、xfail)
skip只要标记skip不管是什么都要skip;
skipif是有条件的skip;
xfail是前两个标记之后,不会执行,xfail标记会执行,只是提前告诉pytest预期失败;
from collections import namedtuple
import pytest
Task=namedtuple('Task',['summary','owner','done','id'])
Task.__new__.__defaults__=(None,None,False,None)
@pytest.mark.skip(reason=" please skip,unsupport this case now")
#养成良好的习惯,当跳过的时候一定要加 reason ,同事看了就很明白了
def test_01():
t1=Task()
t2=Task()
assert t1 == t2
@pytest.mark.skipif(1>0,reason="不想执行")
#这个是条件执行,当表达式 True 就跳过,fail 就执行 ,同样也要加上reason
def test_02():
t1=Task()
t2=Task()
assert t1 == t2
@pytest.mark.xfail
#预期是失败的,结果执行通过, 会被标记为 Xpass
def test_03():
t1=Task()
t2=Task()
assert t1 == t2
@pytest.mark.xfail
#预期失败,确实执行失败了,会被标记为 xfail ,
def test_04():
t1=Task()
t2=Task()
assert t1 != t2
python运行脚本的三种模式
通过查阅资料才发现,原来python的运行脚本的方式有多种:
例如普通模式运行,不会自动去加载测试用例执行
unittest 测试框架运行模式,可以自动去发现testcase并执行
pytest 测试框架运行模式,就是我们上面2个步骤都是使用pytest测试框架运行的
重要原则:第一次按照何种模式执行测试用例,后续都会按照这种方式去执行