51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 2887|回复: 2

[转贴] 我的 python 接口测试框架

[复制链接]

该用户从未签到

发表于 2017-6-22 15:48:22 | 显示全部楼层 |阅读模式
简单介绍
  • Win7 64,python 3,Pycharm. unittest
  • 读取配置文件--读取测试用例--执行测试用例--记录测试结果--生成html结果文件
  • 支持指定接口用例id的测试
  • 考虑到登陆后返回的token,useId给其他接口联合使用的情况
  • 使用html在线生成器生成xml,基于xml管理数据,只要改xml文件,不用改其他代码。
  • 检查点的定义
    • 检查第一层的全字段
    • 如果有嵌套层,检查第一层的全字段后,检查嵌套层的model的type类型
模块类的设计说明
  • Httpbase.py 读取http的域名和端口
  • Config.py http方法的封装,可以支持多协议扩展,get,post
  • Runner_m.py 核心代码。run_case是程序的入口
  • Htmlreport.py 结果生成html文件
xml模型
  1. <root>
  2.     <title>导购码接口测试</title>
  3.     <host>dgm.XXXX</host>
  4.     <port>80</port>
  5.     <No>[]</No> # 指定需要运行哪些接口
  6.     <InterfaceList> # 第一个层固定预留,只用于登陆接口
  7.         <id>1001</id>
  8.         <name>登陆</name>
  9.         <method>POST</method>
  10.         <url>/Login</url>
  11.         <hope>{"appStatus":{"errorCode":0,"message":"操作成功"},"content":[{"user_sex":0,"fk_user_city":440300,"user_id":30,"nickname":"18576759587","user_phone":"18576759587","head_picture":"http:\/\/dgm.boweixin.com\/","has_finance":1,"user_state":1}]}</hope>
  12.         <params>{"account":"18576759587","password":"1112111","type":"0"}</params>
  13.         <login>user_id</login> # 登陆后返回的userid,token等
  14.         <isList>0</isList> # 是否有嵌套
  15.         <!--Version=3.0&UserName=18576759587&IMEI=868157020567821&Password=222222&City=%E6%B7%B1%E5%9C%B3%E5%B8%82&Province=%E5%B9%BF%E4%B8%9C%E7%9C%81&Plat=android&PhoneModel=H60-L02-->
  16.     </InterfaceList>
  17.     <InterfaceList>
  18.         <id>1002</id>
  19.         <name>厂家主页</name>
  20.         <method>GET</method>
  21.         <url>/GetFactoryHome?homeId=2</url>
  22.         <hope>{"appStatus":{"errorCode":0,"message":"操作成功"},"content":[{"business_name":"坤达点子","notice_img":"\/product\/20160718184134_321.jpg","user_type":1,"user_id":2,"goods":[{"good_price":45211.0,"good_id":12,"good_name":"艾欧","banner_picture1":"\/product\/20160719165135_8977.png"},{"good_price":199.0,"good_id":14,"good_name":"麒麟瓜1","banner_picture1":"\/product\/20160720102028_5352.jpg"},{"good_price":452.0,"good_id":6,"good_name":"实力产品","banner_picture1":"\/product\/20160718165448_2602.png"},{"good_price":99898.0,"good_id":11,"good_name":"越南芒果","banner_picture1":"\/product\/20160720100057_5877.jpg"}],"shop_img":"\/product\/20160718120144_3196.jpg","head_picture":"http:\/\/dgm.boweixin.com\/\/product\/20160718134528_4744.jpg","notice_id":1}]}</hope>
  23.         <params>{}</params>
  24.          <login>1</login> # 0不需要登陆后的参数,1表示需要登陆后的参数
  25.         <isList>1</isList> # 是否有嵌套层
  26.     </InterfaceList>
复制代码
入口代码
  1. gm = con_api_xml.ret_xml() # 读取xml
  2. hb = con_api_xml.ret_http_base(gm) #读取http参数
  3. #初始化报告
  4. html_report1 = htmlreport.HtmlReport(gm)

  5. # 测试用例(组)类
  6. class TestInterfaceCase(unittest.TestCase):
  7.     def __init__(self, testName, hope, index):
  8.         super(TestInterfaceCase, self).__init__(testName)
  9.         self.hope = hope
  10.         self.index = index
  11.     def setUp(self):
  12.         self.config_http = config.ConfigHttp(hb.host, hb.port)
  13.     def function(self):
  14.         response = ""
  15.         if self.index == 1: # 登陆的接口测试
  16.              if gm[self.index]["method"] == "POST":
  17.                 response = self.config_http.post(go.URL, go.PARAMS)
  18.                 go.REALLY_RESULT = eval(response)
  19.                 print(go.REALLY_RESULT)
  20.                 hope = eval(self.hope)
  21.                 # temp = testJson.compareJson(hope, go.REALLY_RESULT, gm[self.index]["isList"])
  22.                 temp = check.compare(hope,go.REALLY_RESULT)
  23.                 if temp:
  24.                     go.LOGIN_KY = gm[1]["login"]
  25.                     go.LOGIN_VALUE = go.REALLY_RESULT["content"][0][go.LOGIN_KY]
  26.                     go.RESULT = 'Pass'
  27.                     html_report1.success_num = html_report1.success_num + 1
  28.                 else:
  29.                     go.RESULT = 'Fail'
  30.                     html_report1.error_num = html_report1.error_num + 1
  31.         else:
  32.             if gm[self.index]["login"] != "0":
  33.                     go.PARAMS[go.LOGIN_KEY] = go.LOGIN_VALUE
  34.             if gm[self.index]["method"] == "POST":
  35.                 response = self.config_http.post(go.URL, go.PARAMS)
  36.             if gm[self.index]["method"] == "GET":
  37.                 response = self.config_http.get(go.URL, go.PARAMS)
  38.             print(type(response))
  39.             go.REALLY_RESULT = eval(str(response))
  40.             hope = eval(self.hope)
  41.             # temp = testJson.compareJson(hope, go.REALLY_RESULT, gm[self.index]["isList"])
  42.             temp = check.compare(hope,go.REALLY_RESULT,  gm[self.index]["isList"])
  43.             print(temp)
  44.             if temp:
  45.                 go.RESULT = 'Pass'
  46.                 html_report1.success_num = html_report1.success_num + 1
  47.             # except AssertionError:
  48.             else:
  49.                 go.RESULT = 'Fail'
  50.                 html_report1.fail_num = html_report1.fail_num + 1
  51. # 获取测试套件
  52. def get_test_suite(index):
  53.     test_suite = unittest.TestSuite()
  54.     hope = gm[index]["hope"] # 预期值
  55.     # print(hope)
  56.     test_suite.addTest(TestInterfaceCase("function", hope,index))
  57.     return test_suite

  58. # 运行测试用例函数
  59. def run_case(runner):
  60.     html_report1.case_total = 0
  61.     case_list = hb.No
  62.     case_list = eval(case_list)  # 把字符串类型的list转换为list
  63.     html_report1.case_list = case_list
  64.     temp_case = ""
  65.     if len(case_list) == False: #判断是否执行指定的用例ID
  66.         temp_case = gm
  67.         for index in range(1, len(temp_case)):
  68.             go.URL = gm[index]['url']
  69.             go.PARAMS = gm[index]["params"]
  70.             test_suite = get_test_suite(index)
  71.             runner.run(test_suite)
  72.             # 记录运行结果
  73.             gm[index]["result"] = go.RESULT
  74.             gm[index]["really_result"] = go.REALLY_RESULT
  75.     else:
  76.         for i in case_list:
  77.             for j in range(1, len(gm)):
  78.                 if str(i) == gm[j]['id']:
  79.                     go.URL = gm[j]['url']
  80.                     go.PARAMS = gm[j]["params"]
  81.                     test_suite = get_test_suite(j)
  82.                     runner.run(test_suite)
  83.                     gm[j]["result"] = go.RESULT
  84.                     gm[j]["really_result"] = go.REALLY_RESULT
  85. # 运行测试套件
  86. if __name__ == '__main__':
  87.     start_time = time.time()
  88.     runner = unittest.TextTestRunner()
  89.     run_case(runner)
  90.     end_time = time.time()
  91.     html_report1.time_caculate(end_time - start_time)  # 计算测试消耗时间
  92.     html_report1.generate_html( r'D:\\app\\auto_http34_test\\report\report.html')     # 生成测试报告
复制代码

检查点的代码
  1. def compare(exJson,factJson,isList=0):
  2.     isFlag = True
  3.     if exJson.get("appStatus") == factJson.get("appStatus"):
  4.         if isList== False: # 如果没有嵌套层
  5.             return isFlag
  6.         data2 = exJson.get("content")
  7.         data3 = factJson.get("content")
  8.         for item2 in data2:
  9.             for item3 in data3:
  10.                 keys2 = item2.keys()
  11.                 keys3 = item3.keys()
  12.                 if keys2 == keys3: # 如果嵌套层的key完全相等
  13.                      for key in keys2:
  14.                         value2 = item2.get(key)
  15.                         value3 = item3.get(key)
  16.                         if type(value3)==type(value2):
  17.                            pass
  18.                         else:
  19.                             isFlag = False
  20.                             break
  21.                 else:
  22.                     isFlag = False
  23.                     break
  24.     else:
  25.         isFlag = False
  26.     print(isFlag)
  27.     return isFlag
复制代码

运行结果用的是pyh拼接的html页面
  • 页面比较丑没有去美化


后续优化
  • 接口加密
  • 美化UI
  • 期望值从其他接口查询
  • 其他优化

回复

使用道具 举报

该用户从未签到

发表于 2017-6-22 15:58:28 | 显示全部楼层
多谢分享,正想学下Python,很好的资料。
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2017-6-22 15:59:57 | 显示全部楼层
八戒你干嘛 发表于 2017-6-22 15:58
多谢分享,正想学下Python,很好的资料。

谢谢支持!
回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-3-29 07:07 , Processed in 0.064066 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表