一、前言
本文章主要讲解Python自动化测试中测试用例的数据分离,在自动化测试中能够更好的管理测试用例以及代码,除此之外下方有系列文章的传送门,还在持续更新中,感兴趣的小伙伴也可以前往查看,话不多说,让我们一起看看吧~
系列文章:
系列文章1:【Python自动化测试1】遇见Python之美
系列文章2:【Python自动化测试2】Python安装配置及PyCharm基本使用
系列文章3:【Python自动化测试3】初识数据类型与基础语法
系列文章4:【Python自动化测试4】字符串知识总结
系列文章5:【Python自动化测试5】列表与元组知识总结
系列文章6:【Python自动化测试6】字典与集合知识总结
系列文章7:【Python自动化测试7】数据运算符知识合集
系列文章8:【Python自动化测试8】流程控制语句讲解
系列文章9:【Python自动化测试9】函数知识合集
系列文章10:【Python自动化测试10】文件基础操作
系列文章11:【Python自动化测试11】模块、包与路径知识合集
系列文章12:【Python自动化测试12】异常处理机制知识合集
系列文章13:【Python自动化测试13】类、对象、属性与方法知识合集
系列文章14:【Python自动化测试14】Python自动化测试基础与进阶练习题
系列文章15:【Python自动化测试15】unittest测试框架的核心概念与作用
二、什么是数据分离?
如下代码所示,在测试一个函数时我们需要编写测试用例并断言,通过框架及相关方法来进行测试,这样做会产生一个问题,对于一个庞大的软件、游戏而言,可能会有上万条测试用例,如果数据与代码存在绑定关系,很明显会有很多弊端,例如查询、更改测试数据等,这意味着代码和测试数据将会一起进行维护,维护成本会随着时间以及数量不断的增加,且有互相依赖性。
故此我们需要把数据与代码区分开来,那么分开的这个过程和结果,我们就称之为数据分离,进行单独性的管理。 那么测试用例的数据分离,就是将用例数据与代码区分开的意思。如果测试数据需要进行修改或添加,那么我们只需要维护测试数据即可,而测试用例是不需要进行改动的。
"""
一共涉及到4个知识内容:
1、setUp 测试用例前执行
2、teardown 测试用例后执行
3、setUpClass 测试类之前执行
4、teardownClass 测试类之后执行
"""
import unittest
def login(username=None, password=None):
if username is None or password is None:
return {"code": 400, "msg": "用户名或密码为空" }
if username == "萌笑天" and password == 123456:
return {"code": 200, "msg": "登录成功" }
return {"code": 300, "msg": "用户名或密码错误" }
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
"""每个测试用例之前都会执行的代码"""
print("每个测试用例之前的准备工作")
print("假装正在连接数据库...")
def tearDown(self) -> None:
"""每个测试用例之后都会执行的代码,无论测试用例是否通过,tearDown均会执行"""
print("每个测试用例执行之后都需要做的事情")
print("假装正在断开数据库")
@classmethod
def setUpClass(cls) -> None:
"""每个测试类之前都会执行的"""
print("每个测试类之前只执行一次")
@classmethod
def tearDownClass(cls) -> None:
"""每个测试类之后都会执行的"""
print("每个测试类之后会执行一次")
def test_login_success(self):
username = "萌笑天"
password = 123456
expected = {"code": 200, "msg": "登录成功"}
actual = login(username,password)
self.assertEqual(expected, actual) # 断言预期结果与实际结果是否相等
def test_login_error(self):
username = "萌笑天"
password = 1234567
expected = {"code": 1100, "msg": "用户名或密码错误" }
actual = login(username,password)
self.assertEqual(expected, actual)
三、进行数据分离
进行数据分离的核心就是将数据与代码分开,结合我们前面所学的知识,我们可以把一些测试数据以列表嵌套字典的形式进行存储,转化后的代码为:
"""
TODO:请注意,下面的这些代码并非是最佳的优化途径,只是为了在配合数据分离的知识内容进行讲解
TODO:在后续会逐渐进行优化,采取更优策略,后续文章会进行说明
"""
import unittest
login_data = [
{"username": "萌笑天", "password": 123456, "expected": {"code": 200, "msg": "登录成功"}},
{"username": "萌笑天", "password": 1234567, "expected": {"code": 1100, "msg": "用户名或密码错误"}}
]
def login(username=None, password=None):
if username is None or password is None:
return {"code": 400, "msg": "用户名或密码为空" }
if username == "萌笑天" and password == 123456:
return {"code": 200, "msg": "登录成功" }
return {"code": 300, "msg": "用户名或密码错误" }
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
"""每个测试用例之前都会执行的代码"""
print("每个测试用例之前的准备工作")
print("假装正在连接数据库...")
def tearDown(self) -> None:
"""每个测试用例之后都会执行的代码,无论测试用例是否通过,tearDown均会执行"""
print("每个测试用例执行之后都需要做的事情")
print("假装正在断开数据库")
@classmethod
def setUpClass(cls) -> None:
"""每个测试类之前都会执行的"""
print("每个测试类之前只执行一次")
@classmethod
def tearDownClass(cls) -> None:
"""每个测试类之后都会执行的"""
print("每个测试类之后会执行一次")
def test_login_success(self):
data = login_data[0]
username = data["username"]
password = data["password"]
expected = data["expected"]
actual = login(username,password)
self.assertEqual(expected, actual)
def test_login_error(self):
data = login_data[1]
username = data["username"]
password = data["password"]
expected = data["expected"]
actual = login(username,password)
self.assertEqual(expected, actual)
如上代码所示,目前测试数据和代码是实现了分离,这样当我们想进行测试数据维护或代码维护时就会更加便捷,虽然这样的方式并不是最有效的,但主要是为了让大家先行理解数据分离的概念,将会在后续的文章中继续进行优化。
正常而言我们要进行模块管理,即代码属于一个模块(py文件),而数据属于一个模块,故此我们实际的data数据并不是放在代码模块中的,而应该是一个新的data.py的模块文件,通过导入的方式进行调用,真实的项目里亦是如此,如上代码是方便新手进行理解所用:
E:TestingSoftwarePython3.10.1(64x)python.exe "E:TestingSoftwarePyCharmPyCharm Community Edition 2021.3pluginspython-cehelperspycharm_jb_unittest_runner.py" --target test_login.TestLogin.test_login_error
Testing started at 10:49 ...
Launching unittests with arguments python -m unittest test_login.TestLogin.test_login_error in E:TestingSoftwarePython3.10.1(64x)PythonProjectCSDN自动化测试系列_第一节_Python基础语法1
每个测试类之前只执行一次
每个测试用例之前的准备工作
假装正在连接数据库...
每个测试用例执行之后都需要做的事情
假装正在断开数据库
{'code': 300, 'msg': '用户名或密码错误'} != {'code': 1100, 'msg': '用户名或密码错误'}
Expected :{'code': 1100, 'msg': '用户名或密码错误'}
Actual :{'code': 300, 'msg': '用户名或密码错误'}
Traceback (most recent call last):
File "E:TestingSoftwarePython3.10.1(64x)PythonProjectCSDN自动化测试系列_第一节_Python基础语法1test_login.py", line 55, in test_login_error
self.assertEqual(expected, actual)
AssertionError: {'code': 1100, 'msg': '用户名或密码错误'} != {'code': 300, 'msg': '用户名或密码错误'}
- {'code': 1100, 'msg': '用户名或密码错误'}
? ^^
+ {'code': 300, 'msg': '用户名或密码错误'}
? ^
每个测试类之后会执行一次
Ran 1 test in 0.005s
FAILED (failures=1)
Process finished with exit code 1
四、Python操作excel
"""
数据分离的流程:
1、excel编写测试用例
2、通过Python读取excel(读取出来的格式就是列表嵌套字典: [{}, {}, {}]
3、导入测试用例函数
由上得知:目前只需要有一份excel版本的测试用例,并通过Python读取即可
"""
在路径下创建一个case.xlsx,存储测试用例数据
openpyxl属于第三方库,故此我们需要先行安装,已经安装过会直接更新
如下代码所示:我们用函数进行封装,使用openpyxl进行excel数据的读取
"""
Python操作excel的思路:
1、先打开excel文件
2、选择对应表格页签
3、读取对应单元格数据
4、通过数据实现一定的操作
5、关闭excel文件
"""
import openpyxl # 专门用于处理excel表格的库,openpyxl拥有pandas的特性,并属于轻量级库,不会像pandas一样更加复杂,更具优势
from openpyxl.worksheet.worksheet import Worksheet
def read_excel(file_path, sheet_name ):
"""读取excel的函数"""
workbook_data = openpyxl.load_workbook(file_path) # 打开名称为case.xlsx的excel文档
sheet: Worksheet = workbook_data[sheet_name] # 页签名为login,定位到login页签,指明sheet类型为Worksheet
# """如果我们想要获取某一个单元格的数据,可以使用这个方式,但往往一个表格中有庞大的数据,我们并非通过这样的方式获取"""
# cell = sheet.cell(row=1, column=1) # 获取单元格数据,row为行,column为列,代码中表示的为第一行第一列的单元格
# print(cell.value) # 获取第一行第一列的数据
"""更推荐的获取方法是获取所有数据,因为获取的数据并非列表类型,我们还需要进一步进行数据转换"""
values = list(sheet.values)
workbook_data.close() # 关闭文件
return values
data = read_excel("case.xlsx", "login")
print(data)
在之前提及过,测试用例的数据是列表嵌套字典的形式,而打印的数据则是列表嵌套元组的形式,并不符合预期,所以还需要进一步的转换:
"""
Python操作excel的思路:
1、先打开excel文件
2、选择对应表格页签
3、读取对应单元格数据
4、通过数据实现一定的操作
5、关闭excel文件
"""
import openpyxl # 专门用于处理excel表格的库,openpyxl拥有pandas的特性,并属于轻量级库,不会像pandas一样更加复杂,更具优势
from openpyxl.worksheet.worksheet import Worksheet
def read_excel(file_path, sheet_name ):
"""读取excel的函数"""
workbook_data = openpyxl.load_workbook(file_path) # 打开名称为case.xlsx的excel文档
sheet: Worksheet = workbook_data[sheet_name] # 页签名为login,定位到login页签,指明sheet类型为Worksheet
# """如果我们想要获取某一个单元格的数据,可以使用这个方式,但往往一个表格中有庞大的数据,我们并非通过这样的方式获取"""
# cell = sheet.cell(row=1, column=1) # 获取单元格数据,row为行,column为列,代码中表示的为第一行第一列的单元格
# print(cell.value) # 获取第一行第一列的数据
"""更推荐的获取方法是获取所有数据,因为获取的数据并非列表类型,我们还需要进一步进行数据转换"""
values = list(sheet.values)
workbook_data.close() # 关闭文件
title = values[0]
rows = values[1:]
new_rows = [dict(zip(title, row)) for row in rows]
return new_rows
data = read_excel("case.xlsx", "login")
print(data)
好啦~以上就是本次文章分享的全部内容啦,你学会了吗?希望能给大家带来帮助哦!



