数据驱动测试思想 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

yaml job 运行镜像里的sh_测试数据

 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"]