pytest介绍
pytest是一个非常成熟的全功能的Python测试框架。简单灵活,容易上手;支持参数化;
测试用例的skip和xfail,自动失败重试等处理:
。能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);
pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-allure(完美html测试报告生成),pytest- xdist(多CPU分发)等;
。可以很好的和jenkins集成
文档:https://docs.pytest.org/en/latest/contents.html#toc第三方库:https://pypiorg/search/?q=pytest
pytest测试用例的识别和运行
测试文件
- test_*py
- *_test.py
用例识别 - Test类包含的所有test的方法(测试类不能带有_init方法)
- 不在class中的所有的test_*方法
- pytest也可以执行unittest框架写的用例和方法
常用的终端执行命令:
pytest/py.test
pytest-v(最高级别信息-verbose)打印详细运行日志信息
pytest-s -v 文件名.py(s是带控制台输出结果,也是输出详细)
pytest文件名.py执行单独一个pytest模块
pytest 文件名.py::类名 运行某个模块里面某个类
pytest文件名.py:类名:方法名运行某个模块里面某个类里面的方法
pytest文件名.py-v -k"类名 and not 方法名”跳过运行某个用例
pytest文件名.py-m[标记名] @pytestmark.[标记名]将运行有这个标记的测试用例
pytest文件名.py -x 一旦运行到报错就停止运行
pytest文件名.py -maxfail-[num] 当运行错误达到num的时候就停止运行
创建test_01.py,并输入以下代码
def test_demo01():
print("执行测试demo01")
x = 'zhangshuai'
assert 'h' in x
def test_demo02():
print("执行测试demo02")
a = 'hello'
b = 'hello pytest'
assert a in b
分别执行一下三种pytest的执行语句
pytest test_01.py 只能看到失败的信息(成功的时候显示test_01py..)
pytest -v test_01.py 会显示每个测试方法的执行情况
pytest -s test_01.py 会打印方法的输出语句
结果如下
pytest执行失败重新运行
场景:测试失败后要重新运行n次,要在重新运行之间添加延迟时间,间隔n秒再运行。
安装:pip install pytest-rerunfailures
执行:
pytest --reruns 3 -v -s test_01.py(加入方法demo01出错会重复执行这个方法3次)
pytest -v --reruns 5 --reruns-delay 1 test_01.py(reruns-delay 1表示每次再执行失败的方后法间隔1秒再重复执行下一次)
pytest执行多条断言遇到有失败的断言也能继续执行所有
场景:一个方法中写多条断言,通常第一条过不去,下面就不执行了。我们想报错也执行
安装:pip install pytest-assume
执行:
pytest.assume(14)
pytest.assume(24)
代码:
class TestDemo:
def test_demo01(self):
print("执行测试demo01")
x = 'Changsha'
assert 'a' in x
def test_demo02(self):
print("执行测试demo02")
a = 'helloa'
b = 'hello pytest'
assert a in b
assert 'q' in b
# pytest.assume(1==1)
# pytest.assume(a in b)
# pytest.assume(1==2)
不使用assume的断言
使用assume的断言
文章主要介绍下在pycharm中怎么使用pytest框架进行测试
pycharm配置与执行pytest测试框架
运行方式:pytest.main(['-v',TestClass])(所有参数和pytest命令行方式一样的)
下载pytest第三方包
将运行方式选择pytest
详细可参考这个文章:https://www.cnblogs.com/hpzyang/p/13948048.html
有时候在创建的项目是虚拟环境virtualenv的时候 会发现正常配置pytest的运行方式但是右键运行还是没有出现 pytest for *** 运行,这时候需要在配置中选中项目
避免这种复杂的方式,(这种情况可以能虚拟环境使用的是本地的python的依赖 两者没法互通)我们在创建项目的时候可以创建为conda的项目
参数解析
pytest框架结构
import pytest类似的setupteardown同样更灵活,
模块级(setup_module/teardown_module)模块始末,全局的(优先最高)
函数级(setup_function/teardown_function)只对函数用例生效(不在类中犯法)
类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
方法级(setup_method/teardown_methond)开始于方法始末(在类中的方法)
类里面的(setup/teardown)运行在调用方法的前后(和method方法作用相同,在方法前进行执行但是执行的优先级别低于method)
import pytest
def setup_module():
print('setup_module')
def teardown_module():
print('teardown_module')
def setup_function():
print('setup_function')
def teardown_function():
print('teardown_function')
def test_login():
print('这是个登陆方法')
class TestDemo:
def setup_class(self):
print('setup_class')
print('用户a已经开始登录成功')
def teardown_class(self):
print('teardown_class')
def setup_method(self):
print('setup_method')
def setup(self):
print('setup')
def test_demo01(self):
print("执行测试demo01,需要登陆")
x = 'Changsha'
assert 'a' in x
pass
def test_demo02(self):
print("执行测试demo02,不需要登陆")
a = 'hello'
b = 'hello pytest'
assert a in b
# assert 'q' in b
# pytest.assume(1 == 1)
# pytest.assume(a in b)
# pytest.assume(1 == 2)
pass
def test_demo03(self):
print("执行测试demo03,需要登陆")
x = 'Changsha'
assert 'a' in x
pass
# class TestDemo1:
#
# def test_demo03(self):
# print("执行测试demo03")
# x = 'shanghaied'
# assert 'q' in x
#
# def test_demo04(self):
# print("执行测试demo04")
# a = 'hello'
# b = 'hello pytest'
# assert a in b
if __name__ == '__main__':
pytest.main("-v -x TestDemo")
结果如下
在方法前面加@pytest.fixture()
例子1:前端自动化中应用
用例1需要先登录
用例2不需要登录
用例3需要登录
场景:测试用例执行时,有的用例需要登陆才能执行,有些用例不需要至 setup和teardown无法满足。
fixture可以。默认scope(范围)function
步骤:
导入pytest
在登陆的函数上面加@pytest.fixture()
在要使用的测试方法中传入(登陆函数名称),就先登陆
不传入的就不登陆直接执行测试方法
import pytest
@pytest.fixture()
def test_login():
print('这是个登陆方法')
def test_demo01(test_login):
print('需要登陆')
pass
def test_demo02():
print('需要登陆')
pass
def test_demo03(test_login):
print('需要登陆')
pass
if __name__ == '__main__':
pytest.main()
运行结果如下
例子2场景:
不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也都不需要返回值时可以选择自动应用
解决:使用fixture中参数autouse=True实现
步骤:
在方法上面加@pytest.fixture(autouse=True)
在测试方法上加@pytest.markusefixtures("start")
conftest
场景:
你与其他测试工程师合作一起开发时公共模块要在不同文件中,要在大家都访问到的地方。
解决:
conftest.py这个文件进行数据共享,并且他可以放在不同位置起着不同的范围共享作用。执行:
系统执行到参数login时先从本文件中查找是否有这个名字的变量,之后在conftestpy中找是否有
步骤:
将登陆模块带@pytest.fixture写在conftestpy
- conftestpy配置需要注意:
- conftest文件名是不能换的
- conftest.py与运行的用例要在同一个package下,并且有_init_.py文件
- 不需要import导入conftset.py,pytest用例会自动查找
- 全局的配置和前期工作都可以写在这里,放在某个包下,就是这个包数据共享的地方。
yield
场景:你已经可以将测试方法前要执行的或依赖的解决了,测试方法后销毁清除数据的要如何进行呢?范围是模块级别的。类似setupClass
解决:通过在同一模块中加入yield关键字,yield是调用第一次返 回结果,第二次执行它下面的语句返回。
步骤: 在@pytest.fixture(scope=module)
在登陆的方法中加yield,之后加销毁清除的步骤注意,这种方式没有返回值,如果希望返回使用addfinalizer