0


【selenium】数据驱动测试

数据驱动测试

1. DDT 数据驱动测试基本介绍

DDT官方文档
DDT 数据驱动测试装饰器,可实现多个参数作用于一个测试用例,从而生成多个不同的子用例,需要搭配unittest 使用

使用ddt好处: 提高代码复用性、降低测试数据和代码耦合度、便于用例管理

ddt 核心的方法:

  • @data:包含与您想要传给测试用例的参数,一般是:字典、列表、元组等
  • @file_data:将从JSON或YAML文件加载测试数据 (.yml和.yaml结尾的文件会被当做yaml文件加载,其余的都会以json文件加载)
  • @unpack :通常data中的每个值将作为单个参数传递给测试方法。unpack会自动将元组和列表解压缩为多个参数,并将字典解压缩为多个关键字参数

2. @data使用示例

应用场景:测试过程相同,但随着参数的不同,预期结果不同,例如:

  • 如同一个API,参数不同,响应数据也不一致
  • 如登录显示菜单的功能,不同权限的用户登录,菜单展示的内容不同

2.1 元组

import unittest
from ddt import ddt, data, unpack, file_data

# 声明了ddt类装饰器@ddtclassMyddtTest(unittest.TestCase):defsetUp(self):print("setUp:每个用例执行前调用")deftearDown(self):print("tearDown:每个用例执行后调用")@data(1,2,3)deftest_01(self, value):# value用来接受data的数据print(value)if __name__ =="__main__":
    unittest.main()

执行结果:

setUp:每个用例执行前调用
1
tearDown:每个用例执行后调用
setUp:每个用例执行前调用
2
tearDown:每个用例执行后调用
setUp:每个用例执行前调用
3
tearDown:每个用例执行后调用

示例说明:

  • MyddtTest虽然只有一个test_01,但是通过@data(1, 2, 3) 分别将参数传递给test_01test_01会执行三次,每次入参分别是1、2、3
  • setUp在每个测试用例执行前会自动执行、tearDown在每次测试用例执行后会自动执行,此处仅做打印,为了说明test_01 被调用了三次

2.1 列表拆分&未拆分

import unittest
from ddt import ddt, data, unpack, file_data

# 声明了ddt类装饰器@ddtclassMyddtTest(unittest.TestCase):@data([4,5],[6,7],[9,10])deftest_02(self, value):print("test_02未拆分:",value)@data([4,5],[6,7],[9,10])@unpackdeftest_03(self, value1,value2):print("test_03已拆分:", value1,value2)if __name__ =="__main__":
    unittest.main()

执行结果

test_02未拆分: [4, 5]
test_02未拆分: [6, 7]
test_02未拆分: [9, 10]
test_03已拆分: 4 5
test_03已拆分: 6 7
test_03已拆分: 9 10

示例说明:

  • test_02 没有对数据拆分,因此入参是@data中可遍历的3组数据,因此test_02会执行3次
  • test_03 有对数据拆分,因此入参是@data中可遍历的3组数据,因此test_03会执行3次,因为使用了 @unpack ,每组还会被二次拆分

2.3 字典拆分&未拆分

import unittest
from ddt import ddt, data, unpack, file_data

# 声明了ddt类装饰器@ddtclassMyddtTest(unittest.TestCase):@data({'name':'zs','age':18},{'name':'ls','age':19})deftest_04(self, value):print("test_04未拆分:", value)@data({'name':'zs','age':18},{'name':'ls','age':19})@unpackdeftest_05(self, name,age):print("test_05已拆分:",f"name:{name},age:{age}")# test_06 与 test_05 用法等效,只是将数据存放在一个变量中# *testdata 在这里的作用是将 testdata 列表中的每个字典作为单独的参数传递给 data 装饰器。这使得 data 装饰器能够接收多个参数,而不是一个单一的列表参数。
    testdata =[{'name':'zs','age':18},{'name':'ls','age':19}]@data(*testdata)@unpackdeftest_06(self, name, age):#字典拆分需要与key的个数对应,否则会报错print("test_06已拆分:",f"name:{name},age:{age}")if __name__ =="__main__":
    unittest.main()

执行结果:

test_04未拆分: {'name': 'zs', 'age': 18}
test_04未拆分: {'name': 'ls', 'age': 19}
test_05已拆分: name:zs,age:18
test_05已拆分: name:ls,age:19
test_06已拆分: name:zs,age:18
test_06已拆分: name:ls,age:19

3. @file_data 使用示例

3.1 @file_data加载json文件

login_user.json
{
  "user1": {
    "name": "admin",
    "password": "123456"
  },
  "user2": {
    "name": "guest",
    "password": "1122223"
  }
}
MyddtTest.py 

示例加载json文件并作用于testcase的两种方式

import unittest
from ddt import ddt, data, unpack, file_data

# 声明了ddt类装饰器@ddtclassMyddtTest(unittest.TestCase):@file_data("login_user.json")deftest_07(self, name, password):print("test_07:",f"name={name},password={password}")@file_data("login_user.json")deftest_08(self,**login_info):print("test_08:",f"name={login_info.get('name')},password={login_info.get('password')}")if __name__ =="__main__":
    unittest.main()

执行结果: 可见两种写法效果是一样的

test_07: name=admin,password=123456
test_07: name=guest,password=1122223
test_08: name=admin,password=123456
test_08: name=guest,password=1122223

3.2 @file_data加载yaml文件

# config.yaml

# 使用-分隔用例,则yaml读取到的数据类型为列表
-
  model: 登录模块
  title: 登录成功
  url: http://api.test.cn/api/user/user_login
  method: POST
  data:
    username: admin
    pwd: Ace123456
  check:
    error_code: 200
    msg: 登录成功!
-
  model: 登录模块
  title: 密码错误
  url: http://api.test.cn/api/user/user_login
  method: POST
  data:
    username: admin
    pwd: Ace123456!!
  check:
    error_code: 400
    msg: 密码错误!
import unittest
from ddt import ddt, data, unpack, file_data

# 声明了ddt类装饰器@ddtclassMyddtTest(unittest.TestCase):# @file_data加载yaml文件@file_data("config.yaml")deftest_10(self, model, title, url, method, data, check):
        username = data['username']
        pwd = data['pwd']print(model, title, url, username, pwd, check)# **testdata:将提取到的数据存放在空字典testdata中@file_data("config.yaml")deftest_11(self,**testdata):# 再从字典testdata中单独提取参数
        model = testdata['model']
        title = testdata['title']
        url = testdata['url']
        username = testdata['data']['username']
        pwd = testdata['data']['pwd']
        check = testdata['check']print(model, title, url, username, pwd, check)if __name__ =="__main__":
    unittest.main()

注:
使用ddt遇到的坑: 运行程序时将鼠标定位在类或者程序外运行解决,如果放在代码中间位置,如下代码,若鼠标放在第一行代码后面,点击

run

的时候会报错

type object 'MyddtTest' has no attribute 'test_04'
@data({'name':'zs','age':18},{'name':'ls','age':19})deftest_04(self, value):print("test_04未拆分:", value)

找到的原因是: 运行程序时将鼠标定位在类或者程序外运行解决,ddt只能运行整体,不能运行局部即单个测试方法
若有其他更合理的解释欢迎留言指导


本文转载自: https://blog.csdn.net/xubeiqiannian/article/details/140907541
版权归原作者 青格er 所有, 如有侵权,请联系我们删除。

“【selenium】数据驱动测试”的评论:

还没有评论