ddt
安装
pip install ddt
使用
在测试类上添加装饰器 @ddt.ddt ;
然后在测试方法(用例)上添加装饰器 @ddt.data(args);
还可以使用 @ddt.unpack 对传入的参数进行解包.
from ddt import data, ddt, unpack
import unittest
import inspect
import os
import sys
@ddt # 首先装饰类
class TestOneClass(unittest.TestCase):
@data(100)
def test_006_ddt(self, args):
print("参数化:", args) # 100
@data("李四")
def test_007_ddt(self, args):
print("参数化:", args) # 李四
@data([1, 2, 3])
def test_008_ddt(self, args):
print("参数化:", args) # [1, 2, 3]
@data({"name": "张三", "age": 18})
def test_009_ddt(self, args):
print("参数化:", args) # {"name": "张三", "age": 18}
@data((10, 9, 8))
def test_010_ddt(self, args):
print("参数化:", args) # (10, 9, 8)
# 上面的都是一组参数数据,用例只会执行一次;下面来看参数为多组数据的例子,用例会根据参数数量执行多次
@data(100, 200) # 参数为2条数据,用例执行2次
def test_011_ddt(self, args):
print("参数化:-----", args) # 第一次输出 100,;第二次输出 200
@data((1, 2), (3, 4)) # 每次执行用例传入多个值
@unpack # 解包多个值
def test_012_ddt(self, arg1, arg2): # 使用多个参数来接收解包后的值
print("参数化解包:", arg1, arg2) # 第一次输出:"参数化解包:" 1, 2 第二次输出:"参数化解包:" 3, 4
@data({"name": "张三", "age": 10}, {"name": "李四", "age": 19})
@unpack # 解包多个值
def test_013_ddt(self, name, age): # 参数如果是字典格式,解包操作后,那么测试方法的参数名就要和字典的key一致
print("参数化字典解包", name, age) # 第一次输出:"参数化字典解包", 张三, 10 第二次输出:"参数化字典解包", 李四, 19
parameterized
parameterized 支持 unittest 和 pytest
安装
pip install parameterized
Unittest使用
from parameterized import parameterized, parameterized_class
import unittest
# 1. 直接给函数参数化,目前还没有找到怎么运行????????
@parameterized([
(2, 2, 4),
(2, 3, 8),
(1, 9, 1),
(0, 9, 0),
])
def test_parameterized(one, two, three): # 函数的形参数量要和实参数量一致
print("对单独的函数参数化 test_parameterized: ", one, two, three)
# 2 在类方法内对单个方法(用例)参数化
def get_case_datas():
retrun [(1, 2, 3), (4, 5, 6)]
class TestUserInfo(MyUnit):
# 还可以用函数将参数封装后,作为参数传递
@parameterized.expand(get_case_datas())
def test_user_info(self, args):
print("test_user_info skip", args)
@parameterized.expand([
("negative", -1.5, -2.0),
("integer", 1, 1.0),
("large fraction", 1.6, 1),
])
def test_parameterized_expand(self, name, num1, num2): # 方法形参数量要和实参数量一致
print("在类方法中参数化 test_parameterized_expand: ", name, num1, num2)
# 3.1 对整个类进行参数化,参数为可迭代对象格式(元组,列表) , 那么此类内的所有方法都会根据参数数据的数量执行多次
@parameterized_class(('a', 'b', 'expected_sum', 'expected_product'), [
(1, 2, 3, 2),
(5, 5, 10, 25),
])
class TestMathClass(unittest.TestCase):
def test_add(self):
assert_equal(self.a + self.b, self.expected_sum)
def test_multiply(self):
assert_equal(self.a * self.b, self.expected_product)
# 3.2 对整个类进行参数化,参数为字典格式 , 那么此类内的所有方法都会根据参数数据的数量执行多次
@parameterized_class([
{"a": 3, "b": 10, "expected": 2},
{"a": 5, "b": 0, "expected": -4},
])
class TestParameterizedClass(unittest.TestCase):
def test_parameterized_class(self):
# 直接将参数化中的key 作为类属性引用即可
print("对整个类参数化 test_parameterized_class: ", self.a, self.expected)
def test_parameterized_class_one(self):
print("对整个类参数化 test_parameterized_class_one: ", self.b)
@pytest.mark.parametrize
安装
pip install pytest
使用
import pytest
class TestOne:
# 使用@pytest.mark.parametrize 装饰器 装饰测试用例方法,第一个参数是没条用例的入参名称字符串格式内多个参数名称用英文逗号分隔;第二个参数为具体参数,格式为可迭代对象内包含多条可迭代对象的数据,里层的数据用逗号分隔,代表多个参数。同时测试用例方法的形参必须和装饰器内第一个参数的名字完全一致!
@pytest.mark.parametrize("name, age", [("张三", 10), ("李四", 19)])
def test_index_params(self, name, age):
print("参数化:", name, age) # 第一条输出:"参数化:",张三,10 第二条输出:"参数化:",李四,19
pytest 中使用 fixture 进行参数化
项目目录下或者当前用例目录下创建 conftest.py 文件,文件内写入fixture 方法如下:
# -*- coding: utf-8 -*-
# conftest.py
import pytest
@pytest.fixture(scope="function", params=[(1, 2), (3, 4)])
def params_console(request):
"""
使用 conftest.py 内的fixture前置进行参数化,定义scope 作用级别为方法级别:function,使用 params 传入参数数据(当然这里可以自定义方法读取参数数据进行处理),然后在函数内返回。函数参数为 request 代表用例请求。然后在用例方法内使用函数名作为形参传递即可
:param request:
:return: 参数化数据
"""
return request.param
测试用例文件内容如下:
# -*- coding: utf-8 -*-
# test_demo.py
class TestDemo:
# 参数化使用 conftest.py 内的 fixture
def test_conftest_params(self, params_console): # 使用 params_console 函数名作为用例方法的形参,也不用导包,pytest会自动识别 conftest.py 文件内的所有被 fixture 装饰的函数
print("使用fixture 进行参数化 test_conftest_params: ", params_console, type(params_console)) # (1, 2) <class 'tuple'>; (3, 4) <class 'tuple'>