使用Python的xlrd模块来操作Excel
应用场景:
当我们使用Python+unittest框架进行后端服务接口测试的时候,大家发现一个问题,我们的测试步骤是一样的,只是测试数据不同。
- 组装请求参数
- 发送HTTP请求
- 结果验证
我们根据不同的入参设计了不同的测试用例(数据),当数据量过大时,一条测试用例对应一个测试方法就显得不太合适。而且这种方式还将用例和数据耦合到一起,不容易维护。因此我们可以考虑数据与逻辑分离来让我们的测试脚本变得易于维护和简洁。
一、环境搭建:
-
xlrd是什么?
xls文件read库,该模块主要用于读取Excel相关操作
-
xlrd安装
下载地址:https://pypi.python.org/pypi/xlrd
下载后解压,通过CMD命名行切换到解压路劲下,使用命令 python setup.pyinstall 安装该包
通过import引入该包查看是否安装成功
在线安装方式:pip install xlrd
二、常用方法:
1. 打开Excel
excel_data = xlrd.open_workbook("D:\\testcase.xls")
2. 获取一个工作表
通过sheet名称来获取
table = excel_data.sheet_by_name("Sheet1")
当然我们也可以通过索引下标来获取
table = excel_data.sheet_by_index(0)
3. 获取行数和列数
#行数
row_num = table.nrows
#列数
col_num = table.ncols
4.获取一行内容
#根据行号获取一行的数据,返回值为list类型数据
row_data = table.row_values(row_number)
5.获取一列内容
#根据列号获取一列的数据,返回值为list类型数据
col_data = table.col_values(0)
6.获取某一单元格内容
#获取第一行 第二列的值
value = table.cell(0,1).value
#获取第二行 第三列的值
value = table.cell(1,2).value
7.通过行号索引获取单元格内容
我们可以与上面第6条方法做下对比
#获取第一行 第二列的值
value = table.row(0)[1].value
#获取第二行 第三列的值
value = table.row(1)[2].value
三、实例操作:
- 接口地址:http://www.sojson.com/open/api/weather/json.shtml?
- 返回格式:json
- 请求方式:get
- 请求示例:http://www.sojson.com/open/api/weather/json.shtml?city=北京
请求参数说明
参数名称 | 类型 | 必填 | 说明 |
---|---|---|---|
city | string | 是 | 城市名称 |
返回参数说明
参数名称 | 类型 | 说明 |
---|---|---|
status | int | 状态码 |
date | string | 日期 |
message | string | 提示信息 |
city | string | 城市名称 |
count | int | 请求次数 |
data | object | 详细信息 |
响应示例
{
"date":"20171205",
"message":"Success !",
"status":200,
"city":"北京",
"count":1344,
"data":{
"shidu":"21%",
"pm25":4,
"pm10":20,
"quality":"优",
"wendu":"1",
"ganmao":"各类人群可自由活动",
"yesterday":{
"date":"04日星期一",
"sunrise":"07:18",
"high":"高温 4.0℃",
"low":"低温 -6.0℃",
"sunset":"16:50",
"aqi":31,
"fx":"西北风",
"fl":"3-4级",
"type":"多云",
"notice":"绵绵的云朵,形状千变万化"
},
"forecast":[
{
"date":"05日星期二",
"sunrise":"07:19",
"high":"高温 7.0℃",
"low":"低温 -5.0℃",
"sunset":"16:49",
"aqi":99,
"fx":"西南风",
"fl":"<3级",
"type":"晴",
"notice":"晴空万里,去沐浴阳光吧"
},
{
"date":"06日星期三",
"sunrise":"07:20",
"high":"高温 7.0℃",
"low":"低温 -3.0℃",
"sunset":"16:49",
"aqi":78,
"fx":"无持续风向",
"fl":"<3级",
"type":"晴",
"notice":"晴空万里,去沐浴阳光吧"
},
{
"date":"07日星期四",
"sunrise":"07:21",
"high":"高温 5.0℃",
"low":"低温 -5.0℃",
"sunset":"16:49",
"aqi":38,
"fx":"西北风",
"fl":"3-4级",
"type":"多云",
"notice":"悠悠的云里有淡淡的诗"
},
{
"date":"08日星期五",
"sunrise":"07:22",
"high":"高温 6.0℃",
"low":"低温 -4.0℃",
"sunset":"16:49",
"aqi":41,
"fx":"西南风",
"fl":"<3级",
"type":"晴",
"notice":"晴空万里,去沐浴阳光吧"
},
{
"date":"09日星期六",
"sunrise":"07:23",
"high":"高温 6.0℃",
"low":"低温 -4.0℃",
"sunset":"16:49",
"aqi":54,
"fx":"西南风",
"fl":"<3级",
"type":"多云",
"notice":"绵绵的云朵,形状千变万化"
}
]
}
}
Python+unittest框架测试方法实现
# -*- coding: utf-8 -*-
import unittest
import requests,json
class ApiTest(unittest.TestCase):
def setUp(self):
self.url = "http://www.sojson.com/open/api/weather/json.shtml?"
def test_get_shweather(self):
request_data = {"city":u"上海"}
result = requests.get(self.url,params=request_data)
res = result.json()
self.assertEqual(res['status'],200)
#验证返回城市是否为上海
self.assertEqual(res['city'],u'上海')
def test_get_bjweather(self):
request_data = {"city":u"北京"}
result = requests.get(self.url,params=request_data)
res = json.loads(result.text)
self.assertEqual(res['status'],200)
#验证返回城市是否为北京
self.assertEqual(res['city'],u'北京')
if __name__ == '__main__':
unittest.main()
当我们要测试更多城市的时候,就会出现我们上面说的情况,维护多个测试方法,不如我们进行数据与用例逻辑分离,编写基于excel的测试用例。用例格式如下:
用例编号 | 接口URL | 请求方法 | 请求参数 | 预期结果 | 验证点 | 实际结果 |
---|---|---|---|---|---|---|
1 | /open/api/weather/json.shtml | GET | {“city”:“北京”} | {xxxx} | 状态码、数据正确性、返回结构完整性 | |
2 | /open/api/weather/json.shtml | GET | {“city”:“上海”} | {xxxx} | 状态码、数据正确性、返回结构完整性 |
Python+unittest+xlrd数据驱动参数化实现
思路梳理:
我们先来梳理下操作步骤:
- 打开指定的Excel测试用例
- 获取sheet1的表格
- 依次取出我们的每一条测试用例的数据
- 传入测试方法发送HTTP请求并接收响应
- 结果验证,判断实际结果是否与预期结果一致
- 填写测试的实际结果到Excel中,完成一条用例的执行
我们需要根据总的用例条数即excel的行数,来作为循环条件,完成依次取值,并带入到测试方法中完成一次用例执行即http请求。
具体如何来完成上述的操作步骤呢?我们直接看实例。
# -*- coding: utf-8 -*-
import unittest
import requests,json,xlrd,time
class ApiTest(unittest.TestCase):
#初始化 测试数据准备 读取excel中该接口的测试数据
def setUp(self):
#第一步打开excel
excel_data = xlrd.open_workbook('testcase.xlsx')
#第二步通过sheet名称得到table数据
table = excel_data.sheet_by_name('sheet1')
#获取用例总行数
row_num = table.nrows
#获取标题行
title_data = table.row_values(0)
data = []
for i in range(1,row_num):
row_data = table.row_values(i)
if row_data:
data_value = {}
for j in range(0,len(title_data)):
data_value[title_data[j]] = row_data[j]
data.append(data_value)
print data
self.data = data
def test_get_weather(self):
for i in range(0,len(self.data)):
city = self.data[i]['city']
request_data = {'city':city}
result = requests.get(self.data[i]['URL'],request_data)
print result.url
print result.text
res = json.loads(result.text)
self.assertEqual(res['status'],200)
#验证返回城市是否为请求的城市信息
self.assertEqual(res['city'],city)
time.sleep(4)
if __name__ == '__main__':
unittest.main()
为了方便我们可以把excel读取数据单独封装一个方法返回一个list结构的数据,list中是以标题+值的字典类型组成,这样操作起来更方便。感兴趣的可以自己试着优化修改,如遇到问题欢迎留言一起学习讨论!