1 unittest
单元测试
1.1 组成部分
TestCase: 测试用例,框架的组成部分,真正用来书写用例代码
TestSuite: 测试套件,管理组装多个TestCase
TestRunner: 测试执行,测试运行,执行TestSuite
TestLoader: 测试加载,对TestSuit的功能补充
Fixture: 测试夹具,书写在TestCase代码中,是一个代码结构,在每个方法执行前后都执行的内容
1.2 TestCase
import unittest
class TestDemo(unittest.TestCase):
"""测试类,继承TestCase
测试方法:必须以 test_ 开头
运行:鼠标放在相应的方法上可指定执行相应的方法,放在类上执行所有方法
"""
def test_print(self):
print("测试1")
def test_print2(self):
print("测试2")
1.3 TestSuite、TestRunner
import unittest
from learn_unitest.t1 import TestDemo
from learn_unitest.t2 import TestDemo2
suite = unittest.TestSuite()
suite.addTest(TestDemo('test_print'))
suite.addTest(unittest.makeSuite(TestDemo2))
runner = unittest.TextTestRunner()
runner.run(suite)
1.4 TestLoader
import unittest
loader = unittest.TestLoader().discover("./", "t*.py")
unittest.TextTestRunner().run(loader)
1.5 Fixture
import unittest
def setup_module():
print("+++++模块执行之前+++++")
def teardown_module():
print("+++++模块执行之后+++++")
class TestFixture(unittest.TestCase):
def setUp(self):
print("每个方法执行之前")
def tearDown(self) -> None:
print("每个方法执行之后")
@classmethod
def setUpClass(cls):
print("类中方法执行之前")
@classmethod
def tearDownClass(cls) -> None:
print("类中方法执行之后")
def test_print(self):
print("测试方案1")
def test_print2(self):
print("测试方案2")
1.6 断言
...
def test_print(self):
self.assertIn("abc", "abcdef")
1.7 参数化
import unittest
from parameterized import parameterized
data = [
(1, 2),
(1, 1),
(2, "2"),
([1], [1])
]
class TestDemo(unittest.TestCase):
@parameterized.expand(data)
def test_print(self, a, b):
self.assertEqual(a, b)
1.8 跳过
import unittest
class TestSkip(unittest.TestCase):
@unittest.skipIf(1 == 1, "测试跳过")
def test_sk(self):
print("测试skip")
def test_sk2(self):
print("测试skip2")
1.9 测试报告
import unittest
import HtmlTestRunner
loader = unittest.TestLoader().discover("./", "t_fix*.py")
runner = HtmlTestRunner.HTMLTestRunner(output="static/")
runner.run(loader)
1.10 mock
import unittest
from unittest import mock
from t1 import A
class TestA(unittest.TestCase):
@mock.patch.object(A, "f")
def test_f(self, f):
f.return_value = 2
print(f())
from unittest.mock import patch
import t1
patch("t1.f", None).start()
print(t1.f)
2 pytest
2.1 测试用例
pip install 包名
pytest
pytest-xdist
pytest-html
pytest-ordering
pytest-rerunfailures
allure-pytest
2.2 运行测试用例
pytest.main()
pytest.main(['-vs', '文件名/目录名', '-n=3'])
pytest.main(['-vs', '目录名.文件名::函数名', '--reruns=2'])
pytest.main(['文件名::类名::函数名'])
-s 输出调试信息包括print
-v 显示更详细的信息
-n 多线程执行
--reruns=2
-x
--maxfail=2
--html 路径
pytest
@pytest.mark.run(order=5)
@pytest.mark.skip("原因")
@pytest.mark.skipif(条件, reason="原因")
pytest.ini格式
[pytest]
# 最后文件删除掉中文注释
# 命令行参数,空格分割,-m指定执行的标记类型,--html生成报告指定位置
addopts = -vs -m="smoke or usermanager" --html ./static/a.html
# 指定测试用例位置
testpaths = ./
# 测试模块文件名称
python_files = test*.py
# 测试类名
python_classes = Test*
# 测试函数名
python_functions = test
# 定义标记
markers =
smoke: 冒烟用例
usermanage: 用户管理
test_01.py
import pytest
@pytest.mark.run(order=4)
def test_01():
print("测试 test_01")
class TestO1:
@pytest.mark.run(order=5)
@pytest.mark.usermanager
def test_01(self):
print("测试Test01中的test_01")
@pytest.mark.run(order=3)
@pytest.mark.smoke
@pytest.mark.skipif(False, reason="哈哈哈")
def test_02(self):
print("测试Test01中的test_02")
2.3 前后置夹具
class TestO2:
def test_01(self):
print("测试Test02中的test_01")
def test_02(self):
print("测试Test02中的test_02")
def setup(self):
print("每个测试用例执行之前")
def teardown(self):
print("每个测试用例执行之后")
def setup_class(self):
print("类执行初始化工作, 如开启连接等")
def teardown_class(self):
print("类关闭资源的操作")
2.4 @pytest.fixture实现部分用例前后置
import pytest
@pytest.fixture(scope='function', params=['a', 'b', 'c'])
def my_fixture(request):
print("前置")
yield request.param
print("后置")
class TestO2:
def test_01(self):
print("测试Test02中的test_01")
def test_02(self, my_fixture):
print("测试Test02中的test_02")
print(f"==========={my_fixture}==")
2.5 @pytest.mark.parametrize参数化
import pytest
class Test03:
@pytest.mark.parametrize('a, b', [['a', 'a'], ['b', 'b'], ['c', 'c']])
def test_01(self, a, b):
print(f"---{a}--{b}---")
2.6 yaml格式
info:
name: a
age: b
infos:
- a: a
- b: b
2.7 python读取yaml成字典
pip install pyyaml
import yaml
def read_yaml(path):
with open(path) as f:
value = yaml.load(f, Loader=yaml.FullLoader)
print(value)
if __name__ == '__main__':
read_yaml("./test_yaml.yaml")
2.8 结合yaml
3 pdb
python自带交互式调试模块,无IDE的时候方便调试,比如linux环境下调试
python -m pdb 文件名
import pdb; pdb.set_trace()
class A:
def show(self):
print(dir(self))
if __name__ == '__main__':
import pdb
pdb.set_trace()
a = A()
setattr(a, "a", 1)
if hasattr(a, "show"):
show = getattr(a, "show")
show()
pdb.set_trace()
if hasattr(a, "a"):
print(getattr(a, "a"))
4 responses
4.1 模拟请求预设响应
import unittest
import json
import re
import requests
import responses
class TestA(unittest.TestCase):
def test_api_post_haveibeenpwned_not_reachable(self):
c = requests
data = '{"aaaa": "11111"}'
with responses.RequestsMock() as rsps:
rsps.add(
responses.POST,
re.compile(r"^(http://127.0.0.1:8765/a/).*"),
json=data)
mock_response = json.loads(c.post("http://127.0.0.1:8765/a/").text)
print(mock_response)
|