自动化测试- 数据驱动测试

devtools/2024/12/30 22:15:03/

数据驱动测试模式

基本概念

数据驱动(Data-Driven)是一种软件测试和开发方法,强调通过数据来驱动测试用例的执行和结果验证。与传统的硬编码测试用例不同,数据驱动测试允许使用外部数据源(如 CSV 文件、Excel 表格、数据库等)来提供测试输入和期望输出,从而提高测试的灵活性和可维护性。测试脚本只是作为一个驱动或者类似于一个传送数据的机制。测试数据和测试行为进行完全分离这样的测试脚本设计模式叫做数据驱动。

数据驱动的优势

提高可维护性测试用例与测试数据分离,修改数据不需要更改测试逻辑。
复用性:同一测试逻辑可以使用不同的数据集进行多次测试
覆盖更多场景:可以轻松地添加新的测试数据,覆盖更多的测试场景。
减少重复代码:通过参数化测试,减少了重复的测试代码。

数据驱动的一般流程

1)测试架构搭建

确定测试目标,明确需要测试的功能或模块,确定测试的目标和范围。

2)设计测试用例:

根据需求文档和功能说明,设计测试用例,确定输入数据和预期结果。

3)选择数据源:

确定用于存储测试数据的数据源,可以是 CSV 文件、Excel 表格、数据库、JSON 文件等。

4)编写测试脚本:

编写测试脚本,使用数据驱动框架(如 pytest、JUnit、TestNG 等)来读取数据源中的测试数据,并将其传递给测试用例。

5)测试、分析、维护:

运行测试脚本,测试框架会根据数据源中的数据多次执行测试用例。收集测试执行结果,分析测试通过和失败的情况,生成测试报告。根据需要更新和维护测试数据,确保测试覆盖最新的需求变化

python DDT

python的使用ddt模块进行数据驱动测试,DDT通过使用装饰器来实现,主要包括unittest框架中的装饰器如@ddt、@data、@unpack和@file_data。

pip install ddt    ‌使用装饰器‌:@ddt‌:用于装饰测试类,表示该类使用DDT。
@data‌:用于装饰测试用例,传递参数。可以是列表、元组、字典等。
@unpack‌:用于拆分元组或列表中的元素,使其作为独立的参数传递给测试用例。
@file_data‌:从JSON或YAML文件中加载数据,支持yaml和json格式‌。

实例

python">import unittest
import time
from ddt import ddt,data,unpack
@ddt
class Mytest(unittest.TestCase):def setUp(self):print('test begin----')time.sleep(1)def tearDown(self):print('test end------')time.sleep(1)@data('hello','word')def test_print(self,value):print('传入值是: '+value)@data([1,2,3],[1,2,2])@unpack  #会将d([a,b])拆分两个参数def test_add(self,a,b,expected):actual=int(a)+int(b)  #测试参数[1,2,3]  1+2=3 和1+2=2?expected=int(expected)self.assertEqual(actual,expected)
if __name__=='__main__':unittest.main()

官方实例

https://ddt.readthedocs.io/en/latest/example.html

复杂案例测试

一般的测试流程 1)打开浏览器; 2)输入账号、密码;3)单机登录按钮,进行断言; 4)退出系统关闭浏览器           数据驱动模型中测试: 1)设计架构 -》如data存放excel文件;2)设计用例如用例号、测试标题、预期结果;3) 对excel文件数据进行操作;4)使用ddt生成自动化测试用例;5)运行脚本对成功或失败的用例进行标记                                                     

1,被测试界面准备

tddt.html文件

<!DOCTYPE html>
<html lang='zh-CN'><head><meta charset="utf-8"><meta content="IE=edge"><title>后台管理</title><link href='./style.css' rel='stylesheet' type='text/css' /></head><body><h1>后台管理系统</h1><div class='login box'><!---form starts---><form action='#'><div class='txt'><input placeholder='请输入您的邮箱' id='ty-email'/><div class='msg' id='ty-email-error'></div></div><div class='txt'><input type='password' placeholder='请输入密码' id='ty-pwd'/><div class='msg' id='ty-pwd-error'></div></div><div class='login-btn'><input type='submit' onclick='login()' value='登录'></div><div class='account'><p>账号:admin@test.com; 密码: admin</p></div></form></div><!--- form ends---><!--copyright--><div class='copyright'><p>Copyright 2024 </p></div><!--copyright--></body>
</html>

2、框架搭建

测试框架的搭建是确保软件质量的关键步骤,主要包括选择合适的测试框架、规划测试用例、实现自动化测试等方面,测试结构通常包含的文件目录结构如下:

conf目录‌用于存放项目运行环境和执行环境相关的配置参数‌
logic用于封装与项目相关的关键字和业务逻辑‌
testsuite用于编写测试用例,pytest默认约定以test开头的文件和方法为测试用例,不满足条件的不会被执行,建议按照特性建立文件夹对测试用例进行分类‌
utils用于存放与业务无关的实用程序,如辅助方法‌
common‌用于存储公共代码,如路径处理等‌
utils用于存储工具类,主要处理各种文件的工具函数‌
data用于存储测试过程中使用到的数据‌
report用于存储测试报告‌
‌config用于存储配置文件,如测试地址等‌
README.md用于说明自动化工程的文档‌

3、设计用例:

测试用例放到excel文件里,这里列举了5个当然还有很多测试用例比如密码长度、邮箱格式等等

处理数据脚本

新建文件夹commont并在其内创建ExcelUtil.py 脚本,处理从excel获得的数据,casedata.xlsx放在data文件夹下,casedata.xlsx的数据是在名为Login的Sheet里

python">from openpyxl import load_workbook
import os
class ExcelUtil(object):def __init__(self,excel_path=None,sheet_name=None):'''获取execl 工作表'''if excel_path==None:current_path=os.path.abspath(os.path.dirname(__file__))self.excel_path=current_path+'/../data/casedata.xlsx'else:self.excel_path=excel_pathif sheet_name==None:self.sheet_name='Sheet1'else:self.sheet_name=sheet_nameself.data=load_workbook(self.excel_path)self.sheet=self.data[self.sheet_name]def get_data(self):'''读取文件数据每一行一个list所有数据一个大list'''rows=self.sheet.rowsrow_num=self.sheet.max_rowcol_num=self.sheet.max_columnif row_num<=1:print('总行数小于1,没有数据')else:case_all=[]for row in rows:case=[]for i in range(col_num):case.append(row[i].value)case_all.append(case)return case_all
if __name__=='__main__':sheet='Login'file=ExcelUtil(sheet_name=sheet)print(file.get_data())

4、数据生成测试用例

case文件夹下创建TestLogin.py 脚本, get_case()将得到的数据转为测试case输入。 Login类定义login()方法,简化起见将浏览器driver、邮箱地址、密码作为输入参数,另外断言处理是针对输入测试结果的反馈。使用ddt生成测试用例

python">
from selenium import webdriver   #导入webdriver
import ddt,unittest,time,os,sys
from selenium.webdriver.common.by import By
from ddt import ddt,data,unpackcurrent_file_path = os.path.abspath(__file__)
project_dir = os.path.dirname(os.path.dirname(current_file_path))
sys.path.append(project_dir)
import commont.ExcelUtilclass Case(object):def __init__(self):passdef get_case(self):'''获取数据剔除首行标题,并以邮箱地址、密码、预期结果定位、预期结果顺序保存'''sheet='Login'file=commont.ExcelUtil.ExcelUtil(sheet_name=sheet)data=file.get_data()email_index=data[0].index('邮箱地址')password_index=data[0].index('密码')excepted_element_index=data[0].index('预期结果定位')excepted_index=data[0].index('预期结果')data_length=data.__len__()all_case=[]for i in range(1,data_length): #除去标题行case=[]case.append(data[i][email_index])case.append(data[i][password_index])case.append(data[i][excepted_element_index])case.append(data[i][excepted_index])all_case.append(case)return all_case
class Login(object):def __init__(self,driver):self.driver=driverdef login(self,email,password):time.sleep(1)if email!=None:email_elem=self.driver.find_element(By.ID,'ty-email')email_elem.send_keys(email)time.sleep(1)if password!=None:paswword_elem=self.driver.find_element(By.ID,'ty-pwd')paswword_elem.send_keys(password)time.sleep(1)login_btn=self.driver.find_element(By.CSS_SELECTOR,'input[value="登录"]')login_btn.click()def login_assert(self,assert_type,assert_message):time.sleep(1)if assert_type=='email error':email_message=self.driver.find_element(By.ID,'ty-email-error').textassert email_message==assert_messageelif assert_type=='password error':password_message=self.driver.find_element(By.ID,'ty-pwd-error').textassert password_message==assert_messageelif assert_type in ['login success','login fail']:login_message=self.driver.switch_to.alert.textassert login_message==assert_messageelse:print('输入类型断言不正确')
@ddt
class TestLogin(unittest.TestCase):def setUp(self):self.driver=webdriver.Chrome()url='file:///E:/tddt.html'self.driver.implicitly_wait(20)self.driver.maximize_window()self.driver.get(url=url)def tearDown(self):self.driver.quit()case=Case().get_case()@data(*case)@unpackdef test_login(self,email,password,asser_type,assert_message):login=Login(driver=self.driver)login.login(email=email,password=password)login.login_assert(assert_type=asser_type,assert_message=assert_message)
if __name__=='__main__':unittest.main()

5、测试执行与结果分析

创建run_main.py与case文件夹、report、data同级别

python">import os,time,unittest
import HTMLTestRunner
current_path=os.path.abspath(os.path.dirname(__file__))
report_path=current_path+'/report/'
#生成时间戳格式的日志文件
now=time.strftime("%Y-%m-%d_%H-%M",time.localtime(time.time()))
title=u'后台系统'
report_abspath=os.path.join(report_path,title+now+'.html')
def all_case():discover=unittest.defaultTestLoader.discover('./case/',pattern="Test*.py")return discoverif __name__=='__main__':all_case()fp=open(report_abspath,'wb')runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title=title)runner.run(all_case())fp.close()

6、报告及分析

会在report里生成“后台系统时间戳.html” 测试报告


fail的原因是,在界面tddt.html里没有复杂处理<div class='msg' id='ty-pwd-error'></div>,password_message=self.driver.find_element(By.ID,'ty-pwd-error').text这里结果为空,邮箱的fail原因也是一样; 对于error的case失败原因是html文件没有alert处理造成脚本里 login_message=self.driver.switch_to.alert.text 然后出现error selenium.common.exceptions.NoAlertPresentException: Message: no such alert


http://www.ppmy.cn/devtools/146403.html

相关文章

4.微服务灰度发布落地实践(消息队列增强)

前言 消息队列是一种用于在应用程序的不同组件或系统之间传递消息的通信机制。它通过将消息存储在一个队列中&#xff0c;确保消息能够可靠地从发送方传递到接收方&#xff0c;即使发送方和接收方不同时在线或处理能力不同。消息队列在现代分布式系统、微服务架构以及异步处理…

如何在 Spring Boot 微服务中设置和管理多个数据库

在现代微服务架构中&#xff0c;通常需要与多个数据库交互的服务。这可能是由于各种原因&#xff0c;例如遗留系统集成、不同类型的数据存储需求&#xff0c;或者仅仅是为了优化性能。Spring Boot 具有灵活的配置和强大的数据访问库&#xff0c;可以轻松配置多个数据库。在本综…

6-Gin 路由详解 --[Gin 框架入门精讲与实战案例]

Gin 是一个用 Go 语言编写的 HTTP Web 框架&#xff0c;以其高性能和简洁的 API 而闻名。它提供了一套强大的路由功能&#xff0c;使得开发者可以轻松地定义 URL 路由规则&#xff0c;并将这些规则映射到具体的处理函数&#xff08;handler&#xff09;。以下是关于 Gin 路由的…

C++:单例模式

创建自己的对象&#xff0c;同时确保对象的唯一性。 单例类只能有一个实例☞静态成员static☞静态成员 必须类外初始化 单例类必须自己创建自己的唯一实例 单例类必须给所有其他对象提供这一实例 静态成员类内部可以访问 构造函数私有化☞构造函数私有外部不能创建&#x…

javaEE

1.maven 1.1 maven是什么&#xff1f; maven 是一个软件全周期管理工具。 1.2 maven vs npm 1.2.1 依赖&#xff08;dependencies&#xff09; 项目中需要对象 常规动作&#xff1a; 引入依赖 1.2.1.1 npm 1.2.1.2 maven 依赖坐标 1.3 maven配置安装 1.3.1 下载maven …

HDFS与HBase有什么关系?

1 、 HDFS 文件存储系统和 HBase 分布式数据库 HDFS 是 Hadoop 分布式文件系统。 HBase 的数据通常存储在 HDFS 上。 HDFS 为 HBase 提供了高可靠性的底层存储支持。 Hbase 是 Hadoop database ,即 Hadoop 数据库。它是一个适合于非结构化数据存储的数据库, HBase 基于列的…

LoRaWAN协议在基于低地球轨道的大规模机器类通信架构中的无缝集成

目录 论文信息文档总结 论文信息 中英文标题 英文标题&#xff1a;Seamless Integration of the LoRaWAN Protocol in a LEO-Based mMTC Architecture中文标题&#xff1a;LoRaWAN协议在基于低地球轨道的大规模机器类通信架构中的无缝集成 作者信息 Andrea Novero&#xff08;…

《多模态融合:开启智能新时代的钥匙》

在当今数字化时代&#xff0c;多模态数据融合已成为人工智能领域的热门话题。从智能手机、智能穿戴设备到自动驾驶汽车&#xff0c;我们身边的各种智能产品都在不断利用多模态数据融合技术&#xff0c;以提供更加丰富、准确和智能的服务。 多模态融合的重要性 多模态数据融合…