注明此处使用版本为pytest 3.10.1(个人使用5.1.1有些问题)
首先安装用pip安装即可
pip install pytest==3.10.1
安装完成后可以查看版本是否安装成功
pytest --version
然后安装完成后就是简单的入门小例子
import pytest
import random
def func(x):
return x + 1
def test_answer():
num = random.randint(0,2)
assert func(num) == 3
if __name__ == '__main__':
pytest.main(['PyTest_Demo.py'])
直接运行就会显示运行结果
也可以通过命令行执行
pytest PyTest_Demo.py #当前目录在此py文件,如果py文件在其他路径应写相对路径或绝对路径
同上上述例子可以看到,pytest是直接用arrsert来断言的,这点与unittest不同
运行多个测试
pytest
将在当前目录及其子目录中运行test _ * .py或* _test.py形式的所有文件。更一般地,它遵循标准测试发现规则。
也就是说当前目录下有test_a.py,test_b.py,add_test.py,在当前目录直接运行pytest时,他会运行所有文件。
断言引发了某个异常
import pytest
def f():
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
使用“安静”报告模式执行测试功能:( -q)
pytest -q test_sysexit.py
. [100%]
1 passed in 0.00s
在类中组合多个测试
一旦开发了多个测试,您可能希望将它们分组到一个类中。pytest可以很容易地创建一个包含多个测试的类:
class TestClass:
def test_one(self):
x = "this"
assert "h" in x
def test_two(self):
x = "hello"
assert hasattr(x, "check")
pytest
发现遵循其Python测试发现约定的所有测试,因此它找到两个test_
前缀函数。没有必要继承任何东西。我们可以通过传递文件名来运行模块:
$ pytest -q test_class.py
.F [100%]
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass object at 0xdeadbeef>
def test_two(self):
x = "hello"
> assert hasattr(x, "check")
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
test_class.py:8: AssertionError
1 failed, 1 passed in 0.02s
第一次测试通过,第二次测试失败。您可以在断言中轻松查看中间值,以帮助您了解失败的原因。
请求功能测试的唯一临时目录
pytest
提供Builtin fixture / function参数来请求任意资源,比如一个唯一的临时目录:
def test_needsfiles(tmpdir):
print(tmpdir)
assert 0
列出tmpdir
测试函数签名中的名称,并pytest
在执行测试函数调用之前查找并调用fixture工厂以创建资源。在测试运行之前,pytest
创建一个unique-per-test-invocation临时目录:
pytest -q test_tmpdir.py
F [100%]
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('PYTEST_TMPDIR/test_needsfiles0')
def test_needsfiles(tmpdir):
print(tmpdir)
> assert 0
E assert 0
test_tmpdir.py:3: AssertionError
--------------------------- Captured stdout call ---------------------------
PYTEST_TMPDIR/test_needsfiles0
1 failed in 0.02s
有关tmpdir处理的更多信息,请参见临时目录和文件。
找出该命令存在哪种内置pytest灯具:
pytest --fixtures # shows builtin and custom fixtures
请注意,_
除非-v
添加选项,否则此命令将省略带有前导的灯具。
——————————————————————————————————————————————————
Pytest的fixture用法
import pytest
import random
@pytest.fixture()
def one():
print('我开启了') #setUp
yield
print('我完事了') #tearDown
def func(x):
return x + 1
@pytest.mark.usefixtures("one")
def test_answer():
num = random.randint(0,2)
print(num)
assert func(num) == 3
用法就是在指定的方法加入注解,然后再在需要的方法上指定该方法。
yield前是setup方法,后面是teardown方法。
这样设置肯定不方便所以还有其他设置参数来指定需求。
强大的fixtures(测试准备/清理)方法
Pytest提供会话(一次测试运行为一个会话)/包/模块/类/方法级别以及用例单独的fixtures方法, 并且支持unittest/nose中的setUpModule/tearDownModule
,setUpClass/tearDownClass
,setUp/tearDown
方法,并且使用更加灵活
unittest/nose中没有会话级的fixtures方法, 同时没有个别用例单独使用的fixtures方法
fixture参数支持scope(生效范围)和autouse(自动使用)
生效范围
session: 会话级, 所有执行的用例
package: 包级, 当前包所有执行的用例
module: 模块级
class: 类级
function: 方法级
一般使用function
import pytest
import random
@pytest.fixture(scope="function", autouse=True)
def one():
print('我开启了') #setUp
yield
print('我完事了') #tearDown
def func(x):
return x + 1
#@pytest.mark.usefixtures("one")
def test_answer():
num = random.randint(0,2)
print(num)
assert func(num) == 3
def test_answerTwo():
assert 2 == 3
如果yield前的setup操作出现异常,teardown操作将不再执行, 如果setup操作不稳定,可以使用addfinalizer
方法确保teardown操作一定被执行
这里提供一个方便查看控制台调试的命令参数 -s ,默认运行正常时控制台不显示打印信息。
pytest -s PyTest_Demo.py
https://www.jianshu.com/p/b07d897cb10c还有其他友好命令。
用例失败重新执行
pytest对比unittest目前的优势就在这里
pytest失败重试很简单,首先安装
pip3 install pytest-rerunfailures
然后首先有两种方法
命令行方法
pytest PyTest_Demo.py --reruns 2 --reruns-delay 5
#reruns 是指定重试的次数 reruns-delay是重试时间 可不写
注解方法
@pytest.mark.flaky(reruns=5, reruns_delay=1) # 如果失败则延迟1s后重跑
def test_user_reg() # 最多重跑5次, reruns_delay可以不传
....
还有其他注解的用法https://www.jianshu.com/p/b07d897cb10c
https://www.cnblogs.com/yoyoketang/tag/pytest/default.html?page=2大佬解释