列表、元组、字典
1.列表:
1>单维列表取值
a = [1, 2, 3]
print(a[0], a[1])
运行结果:
1 2
2>多维列表取值
a = [[1, 2, 3], [4, 5, 6]]
print(a[0][2], a[1][1])
运行结果:
3 5
元组中的多维列表取值a = ([1, 2, 3], [4, 5, 6])
print(a[0][2], a[1][1])
运行结果:
3 5
2.元组:
1>单维元组取值
a = (1, 2, 3)
print(a[0], a[1])
运行结果:
1 2
2>多维元组取值
a = ((1, 2, 3), (4, 5, 6))
print(a[0][2], a[1][1])
运行结果:
3 5
列表中的多维元组取值a = [(1, 2, 3), (4, 5, 6)]
print(a[0][2], a[1][1])
运行结果:
3 5
小结:列表与元组的取值形式一致
3.字典:
1>非键值对字典取值 需先转化为列表(采用list)再取值
a = {7, 8, 9}
print(list(a)[0])
运行结果:8
2>键值对字段取值
a = {"id": 15, "idd": 19, "iddd": 199}
# 获取key
print(list(a.keys())[0], list(a.keys())[1])
运行结果:
id idd
# 获取valueprint(list(a.values())[0], list(a.values())[1])
运行结果:
15 19
# 直接获取指定key的value
print(a.get('id'))print('\n')
print(a['iddd'])
运行结果:
15199
# 遍历字典的所有key并获取对应的value
values = []for key in a:
values.append(a[key])
print(values)
运行结果:
[15, 19, 199]
# 使用items()方法,结合列表推导式获取所有的key或valuekeys = [key for key, value in a.items()]
values = [value for key, value in a.items()]
print(keys, values)
运行结果:
['id', 'idd', 'iddd'] [15, 19, 199]
一、DDT前置用法
1.安装导入ddt模块
pip install ddt
安装完成后可能调用时会存在调用报错的情况,解决方法如下:
file ---> setting ---> Project: ---> Python Interpreter ---> 右边小齿轮 ---> show all ---> 点击加号 ---> Virtualenv Environment ---> 选择New environment ---> Base interpreter选择安装的python.exe
2.在类前先添加注解@ddt;在方法参数用例前添加对应注解,如@data 此子类的父类为ddt
@ddt
class TestCrm(unittest.TestCase):
@data('第一次运行')
def test_case(self, yx1):
示例如下(unittest_ddt.py):
import unittest
from ddt import ddt, data
@ddt
class TestCrm(unittest.TestCase):
@data('第一次运行')
def test_case(self, yx1):
print(yx1)
运行结果:
Ran 1 test in 0.002s
OK
第一次运行Process finished with exit code 0
二、DDT的入参方法以及多次运行方法
1.单次传入的变量为单个
1>运行一次:(运行单次只需添加一个值即可)
import unittest
from ddt import ddt, data
@ddt
class TestCrm(unittest.TestCase):
@data('第一次运行')
def test_case(self, yx1):
print(yx1)
运行结果:
Ran 1 test in 0.002s
OK
第一次运行Process finished with exit code 0
2>运行多次:(运行几次就需要添加几个值)
import unittest
from ddt import ddt, data
@ddt
class TestCrm(unittest.TestCase):
@data('第一次运行', '第二次运行')
def test_case(self, yx1):
print(yx1)
运行结果:
Ran 2 tests in 0.003s
OK
第一次运行
第二次运行Process finished with exit code 0
2.单次传入的变量为多个
单次运行传入多个变量需要运用到:采用列表/元组/字典封装多个值,如果要运行多次,即需要添加多个列表/元组/字典即可运行多次。
注意:封装值的数量严格等于方法测试用例定义变量的数量,不然会导致维度不一致而报错!!!
因为传入的是列表/元组/字典,且一个列表/元组/字典中封装了多个值,所以需要采用解包注解:@unpack 此子类的父类为ddt
1>运行一次:(运行单次只需添加一个封装了多个值的列表/元组/字典即可)
1.1、列表 [ ]
注意:封装值的数量严格等于方法测试用例定义变量的数量,不然会导致维度不一致而报错!!!
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data(['值1', '值2']) # 列表有几个值则对应几个变量
@unpack
def test_case(self, yx1, yx2):
print(yx1, yx2)
运行结果:
Ran 1 test in 0.008s
OK
值1 值2Process finished with exit code 0
1.2、元组 ( )
注意:封装值的数量严格等于方法测试用例定义变量的数量,不然会导致维度不一致而报错!!!
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data(('值1', '值2')) # 元组有几个值则对应几个变量
@unpack
def test_case(self, yx1, yx2):
print(yx1, yx2)
运行结果:
Ran 1 test in 0.008s
OK
值1 值2Process finished with exit code 0
1.3、字典{ }
注意:封装值的数量严格等于方法测试用例定义变量的数量,不然会导致维度不一致而报错!!!
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data({'Id': 'key为id的值', 'car': 'key为car的值'}) # 字典有几个键值对则对应几个变量,特别注意:方法变量名称只能和字典key保持一致
@unpack
def test_case(self, Id, car):
print(Id, car)
运行结果:
Ran 1 test in 0.001s
OK
key为id的值 key为car的值Process finished with exit code 0
方法的传值变量与字典中的key名不一致:
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data({'Id': 'key为id的值', 'car': 'key为car的值'}) # 字典有几个键值对则对应几个变量,特别注意:方法变量名称只能和字典名称保持一致
@unpack
def test_case(self, yx1, yx2):
print(yx1, yx2)
运行结果:
Ran 1 test in 0.016s
FAILED (errors=1)
Error
Traceback (most recent call last):
File "", line 59, in testPartExecutor
yield
File "", line 628, in run
testMethod()
File "", line 221, in wrapper
return func(self, *args, **kwargs)
TypeError: test_case() got an unexpected keyword argument 'Id'
Assertion failed
方法传参变量的数量不等于封装值的数量:
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data(('值1', '值2')) # 字典有几个键值对则对应几个变量,特别注意:方法变量名称只能和字典名称保持一致
@unpack
def test_case(self, Id):
print(Id)
运行结果:
Ran 1 test in 0.002s
FAILED (errors=1)
Error
Traceback (most recent call last):
File "", line 59, in testPartExecutor
yield
File "", line 628, in run
testMethod()
File "", line 221, in wrapper
return func(self, *args, **kwargs)
TypeError: test_case() takes 2 positional arguments but 3 were given
Assertion failed
2>运行多次(运行几次就添加几个封装了多个值的列表/元组/字典即可)
示例如下:
import unittest
from ddt import ddt, data, unpack
@ddt
class TestCrm(unittest.TestCase):
@data(('值1', '值2'), ('值3', '值4'))
@unpack
def test_case(self, yx1, yx2):
print(yx1, yx2)
print('\n')
运行结果:
Ran 2 tests in 0.002s
OK
值1 值2
值3 值4
3.yaml文件形式入参
yaml形式文件的样式为:1.以键值对的形式定义
2. - 代表一整个列表
示例(JieKo.yaml):
'''
1. - 为一个列表
2.以键值对的形式记录数据
'''
- name: 获取学员信息
request: # 请求
url: https://cent.rrrr.com/app/aiop
method: get
param: # 传参
sfzh: xysfz
phone: dianhua
xyname: xymc
validate: None # 返回结果断言
方法获参入参方式:
1.方法用例前采用注解 @file_data 此子类的父类为ddt
2.采用yaml文件形式入参,方法定义变量前需要双重指针(**),代表:变量是为可变长度的变量
def test_case(self, **value): # **为代表可变长度
3.普通获参入参具体示例(unittest_ddt):(取值方式可参考:列表、元组、字典的3.2)
import unittest
from ddt import ddt, file_data
@ddt
class TestCrm(unittest.TestCase):
@file_data('JieKo.yaml') # 以字典形式展示
def test_case(self, **value): # **为代表可变长度
print(value)
运行结果:
Ran 1 test in 0.002s
OK
Process finished with exit code 0
{'name': '获取学员信息', 'request': {'url': 'https://cent.rrrr.com/app/aiop', 'method': 'get', 'param': {'sfzh': 'xysfz', 'phone': 'dianhua', 'xyname': 'xymc'}}, 'validate': 'None'}
可能会出现运行报错,异常情况分析:
如果直接粘贴修改文件后运行,有一定几率会报错
Ran 1 test in 0.002s
FAILED (errors=1)
Error
Traceback (most recent call last):
File "", line 59, in testPartExecutor
yield
File "", line 628, in run
testMethod()
File "", line 34, in testFailure
raise self._exception
File "", line 169, in loadTestsFromName
parent, obj = obj, getattr(obj, part)
AttributeError: type object 'TestCrm' has no attribute 'test_case'
Assertion failed
错误原因分析:
查看方法函数定义
def file_data(value, yaml_loader=None):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
``yaml_loader`` can be used to customize yaml deserialization.
The default is ``None``, which results in using the ``yaml.safe_load``
method.
"""
信息提取:
value should be a path relative to the directory of the file containing the decorated unittest.TestCase
value应该是一个相对于包含修饰过的unittest.TestCase的文件目录的路径。
解决办法:
出现以上描述的报错时,可查看右上角下拉框文件选择,会发现有两个测试方法的路径,其中一个会报此错误,故只需要选择路径为需要运行文件的位置或类的位置然后运行即可
可对应精确取值:(取值方式可参考:列表、元组、字典的3.2)
import unittest
from ddt import ddt, file_data
@ddt
class TestCrm(unittest.TestCase):
@file_data('JieKo.yaml') # 以字典形式展示
def test_case(self, **value): # **为代表可变长度
print(value['name']) # 获取最外层的key 打印对应value
print(value['request']['url']) # 逐层获取对应的key 打印对应key的value
print(value['request']['param']['phone']) # 逐层获取对应的key 打印对应key的value
运行结果:
Ran 1 test in 0.002s
OK
Process finished with exit code 0
获取学员信息
https://cent.rrrr.com/app/aiop
dianhua
还可采用 json、excel、csv等文件形式
4.接口自动化示例:
1.安装导入requests模块
pip install requests
2.接口文档转化,此示例采用yaml文件格式,get请求
注意:get请求入参:params post请求入参:json 或 data(表单)
文件格式入参:files: media:'路径'
JieKo.yaml
- name: 获取学员信息
request: # 请求
url: https://cent.rrrr.com/app/aiop
method: get
param: # 传参
sfzh: xysfz
phone: dianhua
xyname: xymc
validate: None # 返回结果断言
unittest_ddt.py
import unittest
from ddt import ddt, file_data
import requests
@ddt
class TestCrm(unittest.TestCase):
@file_data('JieKo.yaml') # 以字典形式展示
def test_case(self, **value): # **为代表可变长度
url = value['request']['url']
param = value['request']['param']
# url:传入url params:传入对应需要的入参
requests.get(url=url, params=param)