2018-05-14 14:26:07         来源：止语的博客

1.环境准备：

python3.6 requests xlrd openpyxl HTMLTestRunner_api

2.目前实现的功能：

3.目前已知的缺陷：

# xlrd读excel数据

1.先从excel里面读取测试数据，返回字典格式

``` 1 # coding:utf-8
2
3
4
5
6 import xlrd
7 class ExcelUtil():
8     def __init__(self, excelPath, sheetName="Sheet1"):
9         self.data = xlrd.open_workbook(excelPath)
10         self.table = self.data.sheet_by_name(sheetName)
11         # 获取第一行作为key值
12         self.keys = self.table.row_values(0)
13         # 获取总行数
14         self.rowNum = self.table.nrows
15         # 获取总列数
16         self.colNum = self.table.ncols
17
18     def dict_data(self):
19         if self.rowNum <= 1:
20             print("总行数小于1")
21         else:
22             r = []
23             j = 1
24             for i in list(range(self.rowNum-1)):
25                 s = {}
26                 # 从第二行取对应values值
27                 s['rowNum'] = i+2
28                 values = self.table.row_values(j)
29                 for x in list(range(self.colNum)):
30                     s[self.keys[x]] = values[x]
31                 r.append(s)
32                 j += 1
33             return r
34
35 if __name__ == "__main__":
36     filepath = "debug_api.xlsx"
37     sheetName = "Sheet1"
38     data = ExcelUtil(filepath, sheetName)
39     print(data.dict_data())
40 openpyxl写入数据
41
42 1.再封装一个写入excel数据的方法
43
44 # coding:utf-8
46 import openpyxl
47
48 # 作者：上海-悠悠
49 # QQ群：226296743
50
51 def copy_excel(excelpath1, excelpath2):
52     '''复制excek，把excelpath1数据复制到excelpath2'''
53     wb2 = openpyxl.Workbook()
54     wb2.save(excelpath2)
55     # 读取数据
58     sheets1 = wb1.sheetnames
59     sheets2 = wb2.sheetnames
60     sheet1 = wb1[sheets1[0]]
61     sheet2 = wb2[sheets2[0]]
62     max_row = sheet1.max_row         # 最大行数
63     max_column = sheet1.max_column   # 最大列数
64
65     for m in list(range(1,max_row+1)):
66         for n in list(range(97,97+max_column)):   # chr(97)='a'
67             n = chr(n)                            # ASCII字符
68             i ='%s%d'% (n, m)                     # 单元格编号
69             cell1 = sheet1[i].value               # 获取data单元格数据
70             sheet2[i].value = cell1               # 赋值到test单元格
71
72     wb2.save(excelpath2)                 # 保存数据
73     wb1.close()                          # 关闭excel
74     wb2.close()
75
76 class Write_excel(object):
77     '''修改excel数据'''
78     def __init__(self, filename):
79         self.filename = filename
81         self.ws = self.wb.active  # 激活sheet
82
83     def write(self, row_n, col_n, value):
84         '''写入数据，如(2,3，"hello"),第二行第三列写入数据"hello"'''
85         self.ws.cell(row_n, col_n).value = value
86         self.wb.save(self.filename)
87
88 if __name__ == "__main__":
89     copy_excel("debug_api.xlsx", "testreport.xlsx")
90     wt = Write_excel("testreport.xlsx")
91     wt.write(4, 5, "HELLEOP")
92     wt.write(4, 6, "HELLEOP")```

# 封装request请求方法

1.把从excel读处理的数据作为请求参数，封装requests请求方法，传入请求参数，并返回结果

2.为了不污染测试的数据，出报告的时候先将测试的excel复制都应该新的excel

3.把测试返回的结果，在新的excel里面写入数据

``` 1 # coding:utf-8
2 import json
3 import requests
5 from excelddtdriver.common.writeexcel import copy_excel, Write_excel
6
7
8
9
10
11 def send_requests(s, testdata):
12     '''封装requests请求'''
13     method = testdata["method"]
14     url = testdata["url"]
15     # url后面的params参数
16     try:
17         params = eval(testdata["params"])
18     except:
19         params = None
21     try:
24     except:
26     # post请求body类型
27     type = testdata["type"]
28
29     test_nub = testdata['id']
30     print("*******正在执行用例：-----  %s  ----**********" % test_nub)
31     print("请求方式：%s, 请求url:%s" % (method, url))
32     print("请求params：%s" % params)
33
34     # post请求body内容
35     try:
36         bodydata = eval(testdata["body"])
37     except:
38         bodydata = {}
39
40     # 判断传data数据还是json
41     if type == "data":
42         body = bodydata
43     elif type == "json":
44         body = json.dumps(bodydata)
45     else:
46         body = bodydata
47     if method == "post": print("post请求body类型为：%s ,body内容为：%s" % (type, body))
48
49     verify = False
50     res = {}   # 接受返回数据
51
52     try:
53         r = s.request(method=method,
54                       url=url,
55                       params=params,
57                       data=body,
58                       verify=verify
59                        )
60         print("页面返回信息：%s" % r.content.decode("utf-8"))
61         res['id'] = testdata['id']
62         res['rowNum'] = testdata['rowNum']
63         res["statuscode"] = str(r.status_code)  # 状态码转成str
64         res["text"] = r.content.decode("utf-8")
65         res["times"] = str(r.elapsed.total_seconds())   # 接口请求时间转str
66         if res["statuscode"] != "200":
67             res["error"] = res["text"]
68         else:
69             res["error"] = ""
70         res["msg"] = ""
71         if testdata["checkpoint"] in res["text"]:
72             res["result"] = "pass"
73             print("用例测试结果:   %s---->%s" % (test_nub, res["result"]))
74         else:
75             res["result"] = "fail"
76         return res
77     except Exception as msg:
78         res["msg"] = str(msg)
79         return res
80
81 def wirte_result(result, filename="result.xlsx"):
82     # 返回结果的行数row_nub
83     row_nub = result['rowNum']
84     # 写入statuscode
85     wt = Write_excel(filename)
86     wt.write(row_nub, 8, result['statuscode'])       # 写入返回状态码statuscode,第8列
87     wt.write(row_nub, 9, result['times'])            # 耗时
88     wt.write(row_nub, 10, result['error'])            # 状态码非200时的返回信息
89     wt.write(row_nub, 12, result['result'])           # 测试结果 pass 还是fail
90     wt.write(row_nub, 13, result['msg'])           # 抛异常
91
92 if __name__ == "__main__":
93     data = ExcelUtil("debug_api.xlsx").dict_data()
94     print(data[0])
95     s = requests.session()
96     res = send_requests(s, data[0])
97     copy_excel("debug_api.xlsx", "result.xlsx")
98     wirte_result(res, filename="result.xlsx")```

# 测试用例unittest+ddt

1.测试用例用unittest框架组建，并用ddt数据驱动模式，批量执行用例

``` 1 # coding:utf-8
2 import unittest
3 import ddt
4 import os
5 import requests
6 from excelddtdriver.common import base_api
8 from excelddtdriver.common import writeexcel
9
10
11
12
13 # 获取demo_api.xlsx路径
14 curpath = os.path.dirname(os.path.realpath(__file__))
15 testxlsx = os.path.join(curpath, "demo_api.xlsx")
16
17 # 复制demo_api.xlsx文件到report下
18 report_path = os.path.join(os.path.dirname(curpath), "report")
19 reportxlsx = os.path.join(report_path, "result.xlsx")
20
22 @ddt.ddt
23 class Test_api(unittest.TestCase):
24     @classmethod
25     def setUpClass(cls):
26         cls.s = requests.session()
27         # 如果有登录的话，就在这里先登录了
28         writeexcel.copy_excel(testxlsx, reportxlsx) # 复制xlsx
29
30     @ddt.data(*testdata)
31     def test_api(self, data):
32         # 先复制excel数据到report
33         res = base_api.send_requests(self.s, data)
34
35         base_api.wirte_result(res, filename=reportxlsx)
36         # 检查点 checkpoint
37         check = data["checkpoint"]
38         print("检查点->：%s"%check)
39         # 返回结果
40         res_text = res["text"]
41         print("返回实际结果->：%s"%res_text)
42         # 断言
43         self.assertTrue(check in res_text)
44
45 if __name__ == "__main__":
46     unittest.main()```

# 生成报告

1.用HTMLTestRunner生成html报告，我这里改了下名称，改成了HTMLTestRunner_api.py

``` 1 # coding=utf-8
2 import unittest
3 import time
4 from excelddtdriver.common import HTMLTestRunner_api
5 import os
6
7
8
9
10 curpath = os.path.dirname(os.path.realpath(__file__))
11 report_path = os.path.join(curpath, "report")
12 if not os.path.exists(report_path): os.mkdir(report_path)
13 case_path = os.path.join(curpath, "case")
14
16     '''加载所有的测试用例'''
17     # 定义discover方法的参数
19                                                   pattern=rule,)
20
21     return discover
22
23 def run_case(all_case, reportpath=report_path):
24     '''执行所有的用例, 并把结果写入测试报告'''
25     htmlreport = reportpath+r"\result.html"
26     print("测试报告生成地址：%s"% htmlreport)
27     fp = open(htmlreport, "wb")
28     runner = HTMLTestRunner_api.H全部折叠 折叠标题：
29 View Code
30   显示行号    行内代码
31 TMLTestRunner(stream=fp,
32                                                verbosity=2,
33                                                title="测试报告",
34                                                description="用例执行情况")
35
37     runner.run(all_case)
38     fp.close()
39
40 if __name__ == "__main__":
42     run_case(cases)```

2.生成的excel报告

3.生成的html报告