一般自动化测试的流程
-准备测试数据(根据被测函数的参数)
-调用被测函数,得到实际结果
-断言
这样的方法可以完成测试,但是存在不少的缺点
-一个用例需要单独编写一个测试用例函数/方法,存在重复性代码(可以通过ddt解决)
-测试的数据都放在用例的方法里,如果哪个数据需要改动,那么全部方法里的相关数据都要改
数据维护起来不方便(通过把数据存放到excel表格中管理)
所以,我们需要把数据单独放到excel表格中管理,之后有需要修改只需要在表格中修改便可
通过read_exce方法读取excel当中的数据,作为被测函数/方法的参数
1.把测试用例的数据放到表格中
如果被测函数的参数较多,写入excel时可以把被测函数的参数用字典的方式填入excel的一个单元格中,调用数据时候方便查看
之前我们封装的read_excel函数,得到的结果是一个列表嵌套元组
这样提取数据并不方便,比如只看到一个1,也很容易忘记是什么数据,所以需要在函数里继续对函数进行操作,转换成一个列表嵌套字典的形式,也方便我们查看数据和提取数据
from openpyxl import load_workbook
def read_excel(excel_name,sheet_name):
#得到工作簿
wb = load_workbook(excel_name)
#得到工作表
sheet = wb[sheet_name]
#读取所有数据
data = list(sheet.values) #得到一个列表,包括标题,值
key = data[0]
data_1 = [dict(zip(key, value))for value in data[1:]] #列表推导式,从列表第二个元素开始到最后都跟第一个元素合并字典
return data_1
然后再把这个函数封装到excel类里,方便之后时候
2.使用封装好的excel类里的read_excel方法
login_data = ExcelHandle(case_file,"login").read_excel()
从ExcelHandle类里获取对象,然后使用read_excel()方法,得到的结果是一个列表嵌套字典
小套路:测试自己封装好的函数/方法,减少测试时候发生的错误
if __name__ == '__main__':
data = read_excel(r"E:\lemmon-public\lesson\lesson15_excel结合用例使用\cases01.xlsx",'Sheet1')
print(data)
点击旁边的按钮可以运行上面的函数,但是在其他模块调用这个函数的时候不会执行这段代码,这种方法可以自行测试编写的代码是否能运行成功
错误操作
当我们准备好测试数据之后.我们就需要把excel表格的数据导入测试用例函数
import unittest
from lesson.lesson15_excel结合用例使用.funcs_login import login
from lesson.lesson15_excel结合用例使用.read_excel import read_excel
data = read_excel(r"E:\lemmon-public\lesson\lesson15_excel结合用例使用\cases01.xlsx","Sheet1")
class TestLongin(unittest.TestCase):
def test_login(self):
for row in data: #遍历data列表,得出每个元素(字典)
params_str = row['data'] #取字典中key为data的值,因为是从excel中获取 所以是字符串不是字典
params = eval(params_str) #转换成字典
username = params["username"] #从嵌套的字典里获取值
password = params["password"]
expected = row["expected"]
actual = login(username,password) #调用被测函数,传入数据
self.assertEqual(expected ,actual)
写for是为了减少重复编写测试用例方法,但是这样的操作存在两个问题
1.测试用例函数用for循环,unittest只发现了一个用例,实际上我们想要的是3个用例,不能在测试用例函数中用循环
2.代码有错误 username = params["username"] TypeError: string indices must be integers
excel当中不存在字典,字典是python中的概念.如果单元格中有文本,读取出来基本上都是字符串
需要把字符串转换字典 eval()
通过eval()函数转换了数据类型后,我们就可以用代码获取字典里的数据,但是目前只解决了测试数据单独管理的问题,所以这时候需要用到参数化,数据驱动来实现多个测试用例函数
通过参数化(ddt)完成数据到用例的结合
参数化:用例函数参数. 一个测试函数当中会带参数,该参数往往就是测试用例数据,没有声明参数化,用例函数不能随便加入参数
数据驱动(data drive testing , ddt)
用法1:
-在unittestreport导入ddt,list_data
from unittestreport import ddt,list_data
-在类上面声明ddt,表示对这个类使用数据驱动
#在类上声明ddt
@ddt
class TestLogin(unittest.TestCase):
-在方法上面声明list_data(),参数输入要参数化的数据(读取excel得出的列表数据[{},{},{}])
#在方法上面声明list_data
@list_data(data)
#在方法的参数输入一个变量
def test_login(self,row):
-在测试用例方法传入参数,相当于遍历列表,每次取出列表的一个元素,也就是每一组测试用例的所有数据
-方法里获取被测函数需要的数据
import unittest
from unittestreport import ddt,list_data
from lesson.lesson15_excel结合用例使用 import funcs_login
from lesson.lesson15_excel结合用例使用 import read_excel
#data代表要运行的所有测试数据[{},{},{}]
data = read_excel.read_excel(r"E:\lemmon-public\lesson\lesson15_excel结合用例使用\cases01.xlsx","Sheet1")
#在类上声明ddt
@ddt
class TestLogin(unittest.TestCase):
#在方法上面声明list_data
@list_data(data)
#在方法的参数输入一个变量
def test_login(self,row):
#row 代表每次从data这个list当中取出其中一组数据{},相当于 for row in data
#源码:会自动生成一个新的test_login1函数
params_str = row['data']
params = eval(params_str)
username = params["username"]
password = params["password"]
expected_str = row["expected"] #excel里就算填字典,因为不识别,所以读取时候仍然是字符串
expected = eval(expected_str)
actual = funcs_login.login(username,password)
self.assertEqual(expected ,actual)
用法2:
-通过ddt导入ddt,data
from ddt import ddt,data
-在类上面声明ddt
#在类上声明ddt
@ddt
class TestLogin(unittest.TestCase):
-在方法上面声明data(*测试数据[{},{},{}]) 参数要加*号
#在方法上面声明data,参数要加*号
@data(*excle)
#在方法的参数输入一个变量
def test_login(self,row):
-在方法里获取数据
import unittest
from ddt import ddt,data
from lesson.lesson15_excel结合用例使用.funcs_login import login
from lesson.lesson15_excel结合用例使用.read_excel import read_excel
#data代表要运行的所有测试数据[{},{},{}]
excle = read_excel(r"E:\lemmon-public\lesson\lesson15_excel结合用例使用\cases01.xlsx","Sheet1")
#在类上声明ddt
@ddt
class TestLogin(unittest.TestCase):
#在方法上面声明data,参数要加*号
@data(*excle)
#在方法的参数输入一个变量
def test_login(self,row):
#row 代表每次从data这个list当中取出其中一组数据{},相当于 for row in data
#远吗:会自动生成一个新的test_login1函数
params_str = row['data']
params = eval(params_str)
username = params["username"]
password = params["password"]
expected_str = row["expected"] #excel里就算填字典,因为不识别,所以读取时候仍然是字符串
expected = eval(expected_str)
actual = login(username,password)
self.assertEqual(expected ,actual)
由此可见,对一个测试逻辑一致,数据不一致的用例通过参数化可以整合到一个自动化用例函数
用数据驱动和参数化后:用例函数只需要写一个,数据可以有多个甚至上万个,节省很多测试用例函数
拓展:测试结果写入excel
我们可以通过写入excel函数,把测试结果通过代码写入excel
1,首先要在测试用例类里继承之前封装好的excel类
@ddt
class TestLogin(unittest.TestCase,ExcelHandle):
2,设置夹具的前置条件
表示每次执行测试用例的时候,需要获得excel类的对象,相当于打开excel表格,因为之后要在测试用例类里使用excel类的方法
def setUp(self) -> None:
self.excel_info = ExcelHandle(case_file,"login")
在用例代码最后使用类的方法
self.excel_info.write_excel(row=info["case_id"] + 1, column=8, value=result)
也可以在测试用例类的外层先获取excel类的对象,这样可以不用继承ExcelHandle
excel_info =ExcelHandle(case_file,"login")
使用写入的方法
excel_info.write_excel(row=info["case_id"] + 1, column=8, value=result)
-注意事项:
excel当中不存在字典,字典是python中的概念.如果单元格中有文本,读取出来基本上都是字符串
参数化不能用for循环,因为for循环虽然可以执行多个数据,但是在自动化测试方法里,只会被当成一个用例