【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类装饰器
@ddt
class MyddtTest(unittest.TestCase):

    def setUp(self):
        print("setUp:每个用例执行前调用")

    def tearDown(self):
        print("tearDown:每个用例执行后调用")

    @data(1, 2, 3)
    def test_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类装饰器
@ddt
class MyddtTest(unittest.TestCase):

    @data([4,5],[6,7],[9,10])
    def test_02(self, value):
        print("test_02未拆分:",value)
    @data([4,5],[6,7],[9,10])
    @unpack
    def test_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类装饰器
@ddt
class MyddtTest(unittest.TestCase):
    @data({'name': 'zs', 'age': 18},{'name': 'ls', 'age': 19})
    def test_04(self, value):
        print("test_04未拆分:", value)

    @data({'name': 'zs', 'age': 18},{'name': 'ls', 'age': 19})
    @unpack
    def test_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)
    @unpack
    def test_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类装饰器
@ddt
class MyddtTest(unittest.TestCase):
    @file_data("login_user.json")
    def test_07(self, name, password):
        print("test_07:", f"name={name},password={password}")

    @file_data("login_user.json")
    def test_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类装饰器
@ddt
class MyddtTest(unittest.TestCase):

        # @file_data加载yaml文件
    @file_data("config.yaml")
    def test_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")
    def test_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})
   def test_04(self, value):
       print("test_04未拆分:", value)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值