- 简单灵活,
- 容易上手,
- 文档丰富
- 支持参数化,能够支持简单的单元测试和复杂的功能测试
- 具有很多第三方插件,并且可以自定义扩展
- 可以很好的和Jenkins工具结合
$ pip3 install -U pytest
$ pytest --version
#test_sample.py
def func(x):
return x + 1
def test_a():
print("---test_a----")
assert func(3) == 5 #断言失败
def test_b():
print("---test_b---")
assert 1 #断言成功
命令行下执行
$ pytest -s test_sample.py
主函数模式下增加主函数:
if __name__ == ‘__main__‘:
pytest.main(["-s", "test_sample.py"])
#-s 表示支持控制台打印,如果不加,print 不会出现任何内容 #-q 安静模式,不打印信息
结果说明:
. 表示成功
如果需要更多信息,可以使用-v或--verbose
F 表示失败
运行于测试方法的始末,运行一次测试函数会运行一次 setup 和 teardown。
import pytest
class TestLogin:
# 函数级开始
def setup(self):
print("------->setup_method")
# 函数级结束
def teardown(self):
print("------->teardown_method")
def test_a(self):
print("------->test_a")
def test_b(self):
print("------->test_b")
scripts/test_login.py ------->setup_method # 第一次 setup()
------->test_a
.------->teardown_method # 第一次 teardown()
------->setup_method # 第二次 setup()
------->test_b
.------->teardown_method # 第二次 teardown()
运行于测试类的始末,在一个测试内只运行一次 setup_class 和 teardown_class,不关心测试类内有多少个测试函 数。
class TestLogin:
# 测试类级开始
def setup_class(self):
print("------->setup_class")
# 测试类级结束
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
def test_b(self):
print("------->test_b")
scripts/test_login.py
------->setup_class # 第一次 setup_class()
------->test_a
.------->test_b
.------->teardown_class # 第一次 teardown_class()
插件列表网址:https://plugincompat.herokuapp.com 包含很多插件包,大家可依据工作的需求选择使用。
自动化测试脚本最终执行是通过还是不通过,需要通过测试报告进行体现。
$ pip3 install pytest-html
在配置文件中的命令行参数中增加 --html=用户路径/report.html
pytest.ini
addopts = -s --html=report/report.html
在项目目录下会对一个 report 文件夹,里面有个 report.html 即为测试报告
自动化测试脚本可能会使用到网络,如果网络不好可能最终会使脚本不通过。像这种情况可能并不是脚本本身 的问题,仅仅是因为网络忽快忽慢,那么我们可以使用失败重试的插件,当失败后尝试再次运行。一般情况最 终成功可以视为成功,但最好进行进行排查时候是脚本问题。
pip3 install pytest-rerunfailures
在配置文件中的命令行参数中增加 --reruns n
pytest.ini
addopts = -s --reruns 3
test_login.py
class TestLogin:
def test_a(self): # test开头的测试函数
print("------->test_a")
assert 1 # 断言成功
def test_b(self):
print("------->test_b")
assert 0 # 断言失败
scripts/test_login.py
------->test_a
.------->test_b
R------->test_b
R------->test_b
R------->test_b
F
R 表示重试
重试时,如果脚本通过,那么后续不再重试
如果你期望加上出错重试的等待时间,请使用如下命令(reruns-delay是等待时间):
pytest --reruns 5 --reruns-delay 1
如果你只想对某几个测试用例应用重试策略,你可以使用装饰器:
@pytest.mark.flaky(reruns=5, reruns_delay=2)
例如:
import random
@pytest.mark.flaky(reruns=5, reruns_delay=2)
def test_example():
assert random.choice([True, False])
登录功能都是输入用户名,输入密码,点击登录。但登录的用户名和密码如果想测试多个值是没有办法用普通 的操作实现的。数据参数化可以帮我实现这样的效果。
pytest.mark.parametrize
# 数据参数化
# 参数:
# argnames:参数名
# argvalues:参数对应值,类型必须为可迭代类型,一般使用list
@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
import pytest
class TestLogin:
@pytest.mark.parametrize("name", ["xiaoming", "xiaohong"])
def test_a(self, name):
print(name)
assert 1
scripts/test_login.py xiaoming
.xiaohong
.
import pytest
class TestLogin:
@pytest.mark.parametrize(("username", "password"), [("zhangsan", "zhangsan123"), ("xiaoming", "xiaoming123")])
def test_a(self, username, password):
print(username)
print(password)
assert 1
scripts/test_login.py
zhangsan zhangsan123 .
xiaoming xiaoming123 .
多个参数还可以将装饰器写成 @pytest.mark.parametrize("username,password", [("zhangsan", "zhangsan123"), ("xiaoming", "xiaoming123")]) 效果是一样的。
addopts = -s
# 当前目录下的scripts文件夹 -可自定义
testpaths = testcase
# 当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件 -可自定义
python_files = test_*.py
# 当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件中,以Test_开头的类 -可自定义
python_classes = Test_*
# 当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件中,以Test_开头的类内,以test_ 开头的方法 -可自定义
python_functions = test_*
url = "http://211.103.136.242:8064/authorizations/"
data = [{"username":"python",
"password":"12345678"},
{"username":"python1",
"password":"test123"}, ]
@pytest.mark.parametrize("login", data)
def test_login(login):
res= requests.post(url,json=login)
print(res.json())
if __name__ =="__main__":
pytest.main(["-s"])
结果:
{"user_id":1,"username":"python","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiO jE1NjUzNDA5NTcsInVzZXJfaWQiOjEsImVtYWlsIjoiOTUyNjczNjM4QHFxLmNvbSIsInVzZXJuYW1lIjoicHl0a G9uIn0.K0Kx8lKkeX0CjNTuWZ0cA67FU33nkNYBfl_s-5LxNP8"} .{"non_field_errors":["无法使用提供的认证信息登录。"]}
原文:https://www.cnblogs.com/siguadd/p/14830792.html