规则&setup
文件名规则: test_Name.py or name_test.py
类名规则:ClassName
方法名规则:test_Name
def setup_module():
print("模块开始执行")
def teardown_module():
print("模块结束执行")
def setup_function():
print("每个模块级方法(不在类内)开始执行")
def teardown_function():
print("每个模块级方法(不在类内)结束执行")
def test_function():
print("模块级方法(不在类内)")
def test_function1():
print("模块级方法(不在类内)1")
class TestClassName(object):
def setup_class(self):
print("类开始执行")
def teardown_class(self):
print("类结束执行")
def setup_method(self):
print("每个方法开始执行")
def teardown_method(self):
print("每个方法结束执行")
def test_functionName(self):
print(f"类方法")
scope 声明为fixture(测试准备/清理)方法
import pytest
@pytest.mark.level1
def test_level1(setup_session, setup_module, setup_func, setup_class):
print(f"setup_session: {setup_session}")
print(f"execute case level 1")
@pytest.mark.level2
def test_level2(setup_func, setup_module, setup_class, setup_session):
print(f"execute case level 2")
@pytest.mark.level3
def test_level3():
print(f"execute case level 3")
# autouse 自动调用fixture功能
@pytest.fixture(scope='function', autouse=True) # 声明为fixture(测试准备/清理)方法
def setup_func():
print("function start")
yield
print("function end")
@pytest.fixture(scope='module') # 声明为fixture(测试准备/清理)方法
def setup_module():
print("module start")
yield
print("module end")
@pytest.fixture(scope='class') # 声明为fixture(测试准备/清理)方法
def setup_class():
print("class start")
yield
print("class end")
@pytest.fixture(scope='session') # 声明为fixture(测试准备/清理)方法
def setup_session():
print("session start")
yield 'session start'
print("session end")
skip && skipif
import pytest
skip = False
@pytest.mark.skip
def test_skip():
print("跳过此用例")
@pytest.mark.skipif(skip, reason="")
def test_skip():
print("如果 skip 为 True 跳过此用例")
def test_function():
print("function")
xfail
import pytest
"""
期望测试结果是的失败,但是不影响测试执行
"""
@pytest.mark.xfail
def test_xfail():
print(f"功能尚未完成")
assert 1 == 2
def test_fail():
assert 1 == 2
mark
import pytest
"""
根据标签筛选脚本
"""
@pytest.mark.apple
def test_apple1():
print("apple 1")
@pytest.mark.apple
def test_apple2():
print("apple 2")
@pytest.mark.orange
def test_orange1():
print("orange 1")
@pytest.mark.orange
def test_orange2():
print("orange 2")
if __name__ == '__main__':
# 执行标签为apple的用例
# pytest.main(["-s", "-v", "test_mark.py", "-m=apple"])
# 执行标签不为apple的用例
# # pytest.main(["-s", "-v", "test_mark.py", "-m=not apple"])
# 执行标签为apple或者orange的用例
pytest.main(["-s", "-v", "test_mark.py", "-m=apple or orange"])
pytest.ini
[pytest]
markers=apple
orange
log_cli_level = INFO
log_cli = 1
-k
import pytest
"""
筛选 类名和 方法名: 不区分大小写, 模糊匹配
"""
class TestApple():
def test_apple(self):
print("class Apple: apple")
def test_orange(self):
print("class Apple: orange")
class TestOrange():
def test_orange(self):
print("class Orange: orange")
def test_apple(self):
print("class Orange: apple")
if __name__ == '__main__':
# # 类或者方法任意匹配到执行
# pytest.main(["-s", "-v", "-k", "ple"])
# 类 任意匹配 ple, 且方法不以test_a开头
pytest.main(["-s", "-v", "-k", "ple and not test_a"])
# 类 任意匹配 ple, 或者方法匹配到apple
# pytest.main(["-s", "-v", "-k", "ple or apple"])
参数化
import pytest
"""
参数化
"""
class TestParametrize1():
sumTestData = [(3, eval("1+2")),
(4, eval("1+3"))]
@pytest.mark.parametrize("input,expect", sumTestData)
def test_sum(self, input, expect):
assert input == expect
class TestParametrize2():
test_user_Data = [{'name': "lili", "age": 18}, {'name': "jack", "age": 20}]
@pytest.fixture(scope="function")
def login(self, request):
name = request.param['name']
age = request.param['age']
print(f"login: {name}")
return age
# indirect = True ,login 作为方法调用
@pytest.mark.parametrize("login", test_user_Data, indirect=True)
def test_user(self, login):
print(f"age : {login}")
class TestParametrize3():
test_user_Data = [{'name': "lili", "age": 18}, {'name': "jack", "age": 20}]
test_score_Data = [{'score': 89}, {'score': 90}]
@pytest.fixture(scope="function")
def login(self, request):
name = request.param['name']
age = request.param['age']
print(f"login: {name}")
return age
@pytest.fixture(scope="function")
def score(self, request):
score = request.param['score']
print(f"score: {score}")
return score
# indirect = True ,login 作为方法调用
@pytest.mark.parametrize("score", test_score_Data, indirect=True)
@pytest.mark.parametrize("login", test_user_Data, indirect=True)
def test_user(self, login, score):
assert score > 85
if __name__ == '__main__':
# -x 遇到失败则停止
# -maxfail 失败2个则停止
pytest.main(["-s", "-v", "-x", "--maxfail", "2"])
coverage 测试覆盖度
import pytest
# 安装pytest-cov
pytest.main(["-s", "-v", dirname,
'--html=reports/report.html',
"--self-contained-html",
f"--cov={scriptPath}",
"--cov-report=html",
f"--cov-config=.coveragerc"
])
# --cov 代码路径
# --cov-config 跳过某些脚本的覆盖率测试
.coveragerc
[run]
omit =
__init__.py
*/__init__.py
执行方式
if __name__ == '__main__':
pytest.main(["-s", "-v", dirname, '--html=Outputs/reports/report.html'])
# pytest.main(["-s", r"文件路径"]) # 执行文件的所有测试用例
# pytest.main(["-s", r"文件路径::类名"]) # 执行文件的指定类的测试用例
# pytest.main(["-s", r"文件路径::类名::方法名"]) # 执行文件的指定类指定方法的测试用例
# pytest.main(["目录"]) # 搜目录所有测试用例
#-m=xxx: 运行打标签的用例
#-reruns=xxx,失败重新运行
#-q: 安静模式, 不输出环境信息
#-v: 丰富信息模式, 输出更详细的用例执行信息
#-s: 显示程序中的print/logging输出
#--resultlog=./log.txt 生成log
#--junitxml=./log.xml 生成xml报告
#--html=./clockOperation.html 生成html报告,需要插件pytest-html
#-x: 遇到错误停止执行
#--maxfil: 遇到几个错结束 --maxfil=3
# --self-contained-html html 样式包含在html中