数据测试 浅谈 Data Driven Testing

QE LAB for QE LAB · 2023年04月03日 · 2666 次阅读

作者:赵泽鑫|QE_LAB

What is Data Driven Testing

数据驱动测试(Data-driven test)是一种软件测试方法,其中测试数据以表格或电子表格格式存储。数据驱动测试允许测试人员输入一个单一的测试脚本,可以对表格中的所有测试数据执行测试,并期望在同一表格中的测试输出。它也被称为表驱动测试或参数化测试。尤其是针对于自动化测试,DDT 几乎是所有自动化测试默认遵循的规范。当我们执行自动化测试的时候,都会遵照 DDT 的要求,尽量将测试中的可变数据抽象出来,变成单独的文件,这个文件的格式可以是 csv、xslx,也可以是 json、xml 或者是 database。

Why Data Driven Testing

DDT 的数据一般包括支持自动化测试用例执行的测试数据,UI 测试使用的元素定位数据,和测试产生的测试结果。使用 DDT 的方式编写我们的测试脚本可以 1. 尽量保证 test case 和容易发生变化的数据解耦。这样当容易发生变化的数据变更后可以在统一的位置进行维护。同时脚本的实现方式发生变化的时候不影响用例本身的执行。2. 可以复用代码,避免重复冗余的代码。

How to create a Data Driven Automation Framework

DDT 究竟怎么落地到实际的测试中呢?举个🌰,最简单的登陆注册页面,正确的用户名,错误的密码;正确的密码,错误的用户名;正确的用户名,正确的密码; 甚至输入用户名的格式和密码的格式不同都会产生不同的用例。那我们可以把这些不同的数据存在一个文件中,用变量的方式把数据传递到登陆的方法中,这样就完成了一个简单的 DDT 测试脚本。

为了能更加方便的使用 DDT 的方式编写测试,有很多工具来辅助我们更简单的实现 DDT。如果你的常用编程语言是 python,可以了解下 python 中的 selenium-ddt 库。里面的常用方法是@data@ddt@unpack@file_data这四种装饰器。

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

def get_data():
   testdata = [{'name': 'tom', 'age': 20}, {'name': 'kite', 'age': 30}]
   return testdata

@ddt
class MyTestCase(unittest.TestCase):
   @data(1, 2, 3) //单组元组数据
   def test1(self, value):
       print(value)

   @data((1, 2, 3), (4, 5, 6))
   def test2(self, value):
       print(value)

   @data((1, 2, 3), (4, 5, 6)) //多组元组数据
   @unpack // 加入unpack方法后使用两组数据执行该用例
   def test3(self, value1, value2, value3):
       print(value1, value2, value3)

   @data([{'name': 'tom', 'age': 20}, {'name': 'kite', 'age': 30}]) //列表数据
   def test4(self, value):
       print(value)

   @data({'name': 'tom', 'age': '20'}, {'name': 'kite', 'age': '30'})//字典数据
   def test5(self, value):
       print(value)

   @data({'name': 'tom', 'age': '20'}, {'name': 'kite', 'age': '30'})//多组字典数据拆分
   @unpack
   def test6(self, name, age):
       print(name, age)

   testdata = [{'name': 'tom', 'age': 20}, {'name': 'kite', 'age': 30}]

   # @data(*testdata)
   @data(get_data()) //可以引用其他方法中的数据
   def test7(self, value):
       print(value)

   @file_data(os.getcwd() + '/test.json')//读取文件应用文件中的数据
   def test8(self, value2):
       print(value2)

if __name__ == '__main__':
   unittest.main()

代码比较简单但是可以说明问题,感兴趣的同学可以自己尝试运行一下,查看结果。可以看到 ddt 中支持多种多样数据结构的同时,也支持不同获取数据的来源,可以是定义在脚本中的数据,也可以是函数的返回数据,还可以读取文件中的数据。虽然在 pytest 支持参数化注解后就很少人使用 selenium-ddt 了,但是其中的设计思想还是值得参考。

下面是一个 pytest 参数化的🌰。pytest 的参数化是通过@pytest.mark.parametrize 注解来实现的。@pytest.mark.parametrize 的内部是 ParametrizeMarkDecorator,ParametrizeMarkDecorator 的类中传入了 MarkDecorator 装饰器,这个装饰器被调用后,会将标记附加在类中,自动应用到类中找到的所有用例里面。这就是为什么使用注解后的用例可以全部被执行的原因。而读取这些数据解析出来,是因为 ParametrizeMarkDecorator 的实现是一个 Iterable,当传入的 data 是一个可迭代对象的时候,就可以将 data 中的数据 unpack 出来。

login_data = [
  ('test001', 'test001@qq.com', '123456', '123456', '666', '验证码不正确'),
  ('test200', 'test009@qq.com', '123456', '123456', '111', '注册成功,点击确定进行登录。'),
]

@pytest.mark.parametrize('username,email,pwd,expected', login_data)
def test1_register(self, username, email, pwd, expected):

   self.driver.find_element(By.NAME, 'username').send_keys(username)
   self.driver.find_element(By.NAME, 'email').send_keys(email)
   self.driver.find_element(By.NAME, 'pwd').send_keys(pwd)
   self.driver.find_element(By.NAME, 'comfirmed').click()
   WebDriverWait(self.driver, 5).until(EC.alert_is_present())
   alert = self.driver.switch_to.alert
   assert alert.text == expected
   alert.accept()

Best practices of Data Driven testing

  1. 在数据驱动测试过程中,使用真实的数据是最理想的。
  2. 测试流程应该在编写在测试脚本内。
  3. 使用数据来驱动断言。
  4. 测试数据要包含积极和消极的结果。
  5. 将数据驱动的功能测试复用在其他形式的测试,如安全或者性能测试。

Disadvantages of Data Driven testing

  1. 测试的质量取决于实施团队的自动化技能。
  2. 当测试脚本需要大量的数据时,数据验证的工作也会比较复杂。
  3. 维护测试是一个大问题,因为数据驱动测试需要大量的编码。
  4. 使用 DDT 完成测试脚本的开发需要比较高水平的 coding 能力。
  5. 会产生很多文件。主要是与管理测试脚本和测试结果有关。

DDT 是一种编写自动化测试的规范或者说是一个框架,用文件的形式存储测试数据,达到数据和测试脚本物理上的隔离,从而达到更好维护用例和更 make sense 的结果。大家在实践 DDT 或者学习 DDT 过程中遇到过哪些问题或者有什么更好的实践,欢迎找我讨论!

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册