数据驱动测试思想 DDT(data driven testing)
注意:ddt只是实现数据驱动测试的手段,不等同于DDT数据驱动思想
数据驱动框架的意义?
- 代码复用率高。同一测试逻辑编写一次,可以被多条测试数据复用,提高了测试代码的复用率,同时可以提高测试脚本的编写效率。
- 异常排查效率高,测试框架依据测试数据,每条数据生成一条测试用例,用例执行过程相互隔离,在其中一条失败的情况下,不会影像其他的测试用例。
- 代码的可维护性高。清晰的测试框架,提高可读性,提高了代码的可维护性。
数据驱动测试适用什么自动化测试场景?
- 大量的测试用例都可以共用一套逻辑的:接口测试
- ui 测试是否适合用数据驱动:不太合适
实现方式:
一、ddt 模块
1.安装第三方库:pip install ddt
2.导包:from ddt import ddt,data,unpack
3.测试类中使用@ddt:声明ddt类的装饰器
4.测试函数当中使用@data(*excel_data):excel_data有多组测试数据
5.测试函数参数使用case_data:用变量case_data去接收excel_data中的一组数据
举例说明:
case.xlsx
login.py
1 def login(username=None, password=None):
2 if username is None or password is None:
3 return {"code": "400", "msg": "用户名或密码为空"}
4 if username == 'yuz' and password == '123':
5 return {"code": "200", "msg": "登录成功"}
6 return {"code": "300", "msg": "用户名或密码错误"}
test_login.py
1 import unittest
2 from ddt import ddt,data,unpack
3 import login as l
4 from open_excel import read_excel
5
6 login_data = read_excel('case.xlsx', 'login')
7 # 声明ddt类的装饰器
8 @ddt
9 class TestLogin(unittest.TestCase):
10 # data(*excel中的数据),注意测试方法中需要有个参数接收从excel中获取的每组测试数据
11 @data(*login_data)
12 def test_case(self,case_info):
13 14 #print(case_info)
15 user_info = eval(case_info['data']) #excel读取出来的是字符串,需要用eval转换成字典类型
16 username = user_info['username']
17 password = user_info['password']
18 expected = eval(case_info['expected'])
19 actual = l.login(username,password)
20 self.assertEqual(expected,actual)
二、unittestreport ddt
1.导包:from unittestreport import ddt,list_data
2.测试类中使用@ddt
3.测试函数当中使用@list_data(excel_data):excel_data有多组测试数据,不需要加*
4.测试函数参数使用case_data:每次从excel_data中获取一组数据赋值给case_data
1 import unittest
2 import login as l
3 from open_excel import read_excel
4 from unittestreport import ddt,list_data
5
6 login_data = read_excel('case.xlsx', 'login')
7
8 @ddt
9 class TestLogin(unittest.TestCase):
10
11 @list_data(login_data) #相当于for case_info in login_data,添加装饰器@list_data标识需要执行len(login_data)次测试函数
12 def test_case(self,case_info):
13 # case_info = login_data[0]
14 print(case_info)
15 user_info = eval(case_info['data'])
16 username = user_info['username']
17 password = user_info['password']
18 expected = eval(case_info['expected'])
19 actual = l.login(username,password)
20 self.assertEqual(expected,actual)
三、配置文件
1、配置文件是什么:配置文件本质上是包含成功操作程序所需信息的文件,这些信息以特定方式构成。
它们不是在程序中进行硬编码,而是用户可配置的,通常存储在纯文本文件中。
2、配置文件的作用:用于存储程序运行的初始化参数。做到无代码化修改,环境变化只需修改配置文件,不需要修改代码。
3、配置文件格式:yaml,json,xml,ini,toml
三种主要使用的配置文件格式:
- yaml:现在最主要使用的配置文件,读取方便,支持多种数据类型,跨平台。
- ini :支持的数据类型非常有限,只支持数字,字符串,比较老。
- python 文件:python项目当中比较方便,数据类型多,在java中不能用。
1、yaml 配置文件:key,value的形式存储,跟字典很像。
- key 不加引号
- value 如果是字符串,建议加“ ”
- :后面要加空格
- 字典、列表的表示
demo.yaml文件:
host: "http://api.lenmonban.com"
port: 5556
# 嵌套
db:
database: "127.0.0.1"
sit: "10.12.11.198"
uat: "10.12.11.199"
db1: {"database":"127.0.0.1","sit":"10.12.11.198","uat":"10.12.11.199"}
users: ["yuz","mengxiaotian","banbutianya"]
users1:
- "yuz"
- "mengxiaotiao"
- "banbutianya"
读取yaml文件:pip install pyyaml
1 import yaml
2
3 with open('demo.yaml',encoding='utf8') as f:
4 data = yaml.safe_load(f)
5 print(data) #读取出来是一个字典
2、ini 配置文件:[ ]分组,ini中不需要“”,默认都为字符串,key和value的分隔符为 =
比较老牌,需要频繁通过section,option参数获取值,不能一次获取所有数据。
支持的数据类型有限,int类型需要转换。
config.ini
# -*-coding:uft-8 -*-
[HTTP]
scheme = http
baseurl = 10.1.11.198
port = 8080
timeout = 10.0
[EMAIL]
on_off = on
subject = 接口自动化测试报告
app = Outlook
addressee = yuxue@fulan.com.cn
cc = wangjin@fulan.com.cn
[DATABASE]
读取ini文件
class ReadConfig():
def get_http(self, name):
value = config.get('HTTP', name)
return value
def get_email(self, name):
value = config.get('EMAIL', name)
return value
def get_mysql(self, name):
value = config.get('DATABASE', name)
return value
if __name__ == '__main__':
print('HTTP中baseurl的值为:',ReadConfig().get_http('baseurl'))
print('EMAIL中on_off的值为:',ReadConfig().get_email('on_off'))
3.python 配置文件,推荐使用,方便
py_config文件:
# 变量直接命名
host:="http://api.lenmonban.com"
port:=5556
db1={"database":"127.0.0.1","sit":"10.12.11.198","uat":"10.12.11.199"}
users= ["yuz","mengxiaotian","banbutianya"]