1. pytest.ini
pytest的主配置文件,可以改变pytest的默认行为
不能使用中文、空格、引号、冒号
addopts配置:配置命令行参数
-vs:打印详细调试信息
-n:支持多线程或分布式运行(pytest-xdist插件)
-html:生成html测试报告(pytest-html插件)
-x:出现失败则停止执行
-k:模糊匹配
-maxfail:出现几条失败则停止执行
注册mark标记
markers =
demo:explain
xfail_strict = True
@pytest.mark.xfail()
制定pytest最低版本
minversion = 5.0
testpaths配置
python_files = test_* *_test test*
python_classes = Test* test*
python_functions = test_* test*
log_cli配置
控制台实时输出日志
log_cli=True 或False,log_cli=1 或 0
加了log_cli=1,可以清晰看到哪个package下的哪个module下的哪个测试用例是否passed还是failed,批跑不建议添加
norecursedirs配置
收集测试用例一般会遍历testpaths,可用norecursedirs简化
2. conftest.py
- 测试用例的一些fixture配置,不需要import即可实现数据共享
- 可结合fixtures使用
- conftest.py与用例在一个包下,并需要有_init_.py文件
- 一个项目可以有多个conftest.py
场景:每个用例的setup和teardown,token,测试数据,配置信息,数据库连接等
import pytest
import pymysql
@pytest.fixture
def db_connection():
db = pymysql.connect(
host='10.70.32.12',
port=3306,
user='root',
password='Aa123456!',
db='iap'
)
yield db
db.close()
3. init.py
- python检测到目录下存在_init_.py,就会把这个目录当成一个module
- init.py可以是一个空文件
- 可在_init_.py中对核心子模块重新命名,引用的时候就可以from module import * 调用所有该模块下方法
4. 夹具fixtures
@pytest.fixture
def test_test():
pass
- scope:有四个级别参数"function"(默认),"class","module","session"
-function:每一个函数或方法都会调用
-class:每一个类调用一次,一个类中可以有多个方法
-module:每一个.py文件调用一次,该文件内又有多个function和class
-session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module
def test_db_query(db_connection):
pass
5. 覆盖率pytest_cov
安装pytest_cov,执行pytest --cov=myproject,运行并提供myproject的覆盖率报告
6. @pytest.mark.parametrize
输入数据集
def readsql():
# 读取SQL数据
with open('AT_RT_data/getinfo.sql', 'r', encoding='utf-8') as f:
sql_list = f.readlines()
return sql_list
@pytest.mark.parametrize('sql', readsql())
@pytest.mark.parametrize(
'input_value,expected_output',
[(4,8),(3,6),(2,4),(1,2)]
)
7. pytest_generate_tests
允许动态的生产测试数据,适用于复杂的逻辑或者外部数据
import pytest
def pytest_generate_tests(metafunc):
if "input_value" in metafunc.fixturenames:
metafunc.parametrize('input_value,expected_output',
[(4, 8), (3, 6), (2, 4), (1, 2)])
def test_compute(input_value, expected_output):
assert input_value * 2 == expected_output
8. 钩子函数Hooks和插件Plugins
9. Pytest-xdist 并行测试
执行命令使用pytest -n 6 #跨4个cpu甚至不同机器执行
#并发不等于并行
10. Pytest-asyncio 并发异步测试
https://liaoxuefeng.com/books/python/async-io/asyncio/
async def hello(name):
print("hello %s! (%s)" % (name, threading.current_thread()))
# 通过await调用另一个async函数,由async内不消息循环调用
await asyncio.sleep(1)
print("hello %s again! (%s)" % (name, threading.current_thread()))
return name
async def main():
# 通过asyncio.gather()并发执行若干个async函数
L = await asyncio.gather(hello("Bob"), hello("Alice"))
print(L)
# 使用asyncio.run()调度一个协程
asyncio.run(main())
11. 测量执行时间
@pytest.mark.timing
def test_execution_time():
start_time = time.time()
elapsed_time = time.time() - start_time
assert elapsed_time < 2
12.基准性能测试
python自带timeit
pyperf
pytest-benchmark
运行pytest --benchmark-save=benchmark_data,保存基准测试结果,以便后续进行比较
运行pytest --benchmark-histogram 直接图表展示结果
- name: 测试函数的名称。每个测试函数都有自己的名称,用于区分不同的测试。
- min: 执行测试函数的最小时间。这是在所有运行中观察到的最短时间。
- max: 执行测试函数的最大时间。这是在所有运行中观察到的最长时间。
- mean: 执行测试函数的平均时间。这是所有运行时间的平均值。
- stddev: 执行测试函数的标准差。标准差用于衡量运行时间的离散程度。较小的标准差表示运行时间更稳定。
- median: 执行测试函数的中位数时间。中位数是将所有运行时间按大小排序后,位于中间位置的值。
- IQR: 四分位距(InterQuartile Range)。这是一种不同的测量方差的方法。
- outliers: 执行测试函数时观察到的异常值数量。异常值是指与其他观测值相比明显偏离的值。
- OPS: 表示在一定时间内(比如1秒)测试方法被调用了多少次。
- rounds: 执行测试函数的运行次数。pytest-benchmark默认会多次运行测试函数,并根据这些运行结果计算出平均时间等统计数据。
- iterations: 每个运行中执行测试函数的迭代次数。pytest-benchmark会在每个运行中多次迭代执行测试函数,并计算每次迭代的时间。
13.模拟外部服务或者API
https://www.cnblogs.com/goldsunshine/p/15265187.html
13.1 unittest.mock
import requests
from unittest.mock import MagicMock
def test_external_api():
requests.get = MagicMock(
return_value=MagicMock(
status_code=200,
json=lambda: {"key": "value"}
)
)
requests.get.assert_called_with('https://api.external-service.com/endpoint')
13.2 pytest-mock
提供比unittest.mock更简单、强大的功能
需要进行pip安装,pip install pytest-mock
def test_fucntion(mocker):
mock = mocker.patch('some_function.external_function', return_value=42)
result = function_to_test()
assert result == 42
mock.assert_called_once()
在上述例子中,使用mocker.patch将some_function.external_function替换成mock对象
14. pytest持续集成
15. 代码覆盖率
pytest-cov插件
pytest --cov=my_project --cov-report HTML term-missing
–cov=my_project:计算my_project的覆盖率
–cov-report:指定覆盖率报告,html或者xml
term-missing:显示覆盖范围并列出缺少覆盖的线路
16. UI代码覆盖率
启用UI测试覆盖率,在Graddle设置一个属性
android {
buildTypes{
testCoverageEnabled = true
}
}
17. 安全测试建议
- 威胁建模:识别潜在安全威胁和漏洞
- 安全编码实践:代码审查、代码规范、用户输入的注入攻击
- 数据加密:加密协议(HTTPS/TLS),对设备存储的敏感数据加密
- 事件响应计划:制定响应安全事件的计划,包括通讯协议和补救步骤,定期演练,更新计划(保证计划有效性