51Testing软件测试论坛

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

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 7468|回复: 1
打印 上一主题 下一主题

[转贴] 接口测试框架(三)-框架优化

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-11 13:59:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
* 一、加入读取、写入Excel文件功能

第一步,在文件读取类中加入读取与写入excel文件的类。
  1. from xlrd import open_workbook
  2. from xlutils.copy import copy
  3. from xlwt import Style

  4. class ExcelReader():
  5.     def __init__(self, excel_file, sheet, title_line=True):
  6.         if os.path.exists(excel_file):
  7.             self.excel_file = excel_file
  8.         else:
  9.             raise FileNotFoundError('File not found!%s')
  10.         self.sheet = sheet
  11.         self.title_line = title_line
  12.         self.table = None
  13.         self._data = list()

  14.     def set_value(self,col, row, value):
  15.         #   将传入值写进xlsw文件相应的行号,列号中
  16.         rb = open_workbook(self.excel_file, formatting_info=True)
  17.         wb = copy(rb)
  18.         ws = wb.get_sheet(0)
  19.         ws.write(col, row, value, Style.default_style)
  20.         wb.save(self.excel_file)

  21.     @property
  22.     def data(self):
  23.         #   读取xlsx文件
  24.         if not self._data:
  25.             work_book = open_workbook(self.excel_file)
  26.             if type(self.sheet) not in [int, str]:
  27.                 print '[Excel sheet error]Input <int> <str> please'
  28.             elif type(self.sheet) is str:
  29.                 self.table = work_book.sheet_by_name(self.sheet)
  30.             else:
  31.                 self.table = work_book.sheet_by_index(self.sheet)
  32.             #   判断是否有标题,标题有无影响数据的格式(可运行最下方main函数进行比较)
  33.             #   有标题:[{标题1:参数1,标题2:参数2,标题3:参数3}]
  34.             #   无标题:[[参数1(行1),参数2(行1),参数3(行1)],[参数1(行2),参数2(行2),参数3(行2)]]
  35.             if self.title_line:
  36.                 title = self.table.row_values(0)
  37.                 for row in range(1, self.table.nrows):
  38.                     self._data.append(dict(zip(title, self.table.row_values(row))))
  39.             else:
  40.                 for col in range(self.table.nrows):
  41.                     self._data.append(self.table.row_values(col))
  42.         return self._data
复制代码

这里参照了灰蓝的写法,自己再加入了写入excel文件的方法。

* 二、创建测试类用于读取excel中的测试用例

这一步主要是讲落叶归根博客中的方法引入到我们的测试框架中。大致的思路是,将excel中的数据存入我们的用例类中,生成一个个的测试用例。好像就这一块算是我自己独立完成的,哎,要走的路好长呀。

这里有几个很重要的点,分别是:参数、关联、检查点、是否运行

参数:注意一定要是字典类型否则会出错。参数还要支持参数化,例如$token则会去配置文件中读取token的值,并赋值给该参数。

关联:这里还是拿token举例。比如说我先执行登录接口,登录成功后会返回给我们一个token,接下来的测试都需要用到token。那么我们在这里将登录接口中的token设为关联,运行登录测试用例后,就会将刚获取的token的值存入配置文件中。

检查点:这个比较简单,看响应内容中是否有包含该字符串。

是否运行:这里的值设为yes就会执行,没有的话就不会执行。
  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from utils.file_reader import YamlReader
  4. from utils.config import BASE_PATH
  5. from utils.client import HTTPsClient
  6. from utils.log import logger
  7. import yaml
  8. import json
  9. import os


  10. class InterfaceCase(object):
  11.     #   接口测试对象,属性对应接口测试xlsx文件。方法有建立用例数据,运行用例数据
  12.     def __init__(self, data):
  13.         self.data = data
  14.         self.no = int('%d' % data['No.'])
  15.         self.apiName = data['API']
  16.         self.testCase = data['TestCase']
  17.         self.host = data['HOST']
  18.         self.url = data['URL']
  19.         self.requestMethod = data['RequestMethod']
  20.         self.params = data['Params']
  21.         self.relation = data['Relation']
  22.         self.checkPoint = data['CheckPoint']
  23.         self.active = data['Active']
  24.         self.result = 'Na'
  25.         self.response = None
  26.         self.y = YamlReader(os.path.join(BASE_PATH, 'config', 'test.yaml'))
  27.         self.get_config()

  28.     def __str__(self):
  29.         #   漂亮的输出测试用例的重要属性
  30.         return 'No.' + str(self.no) + ' API:' + self.apiName + ' TestCase:' + self.testCase + \
  31.           ' result:' + self.result

  32.     def get_config(self):
  33.         #   将参数中带有$的参数与配置文件中的参数匹配,并赋值
  34.         #   例如:参数中有$token,则将配置文件中token的值付给token这个参数
  35.         try:
  36.             params = json.loads(self.params)
  37.         except ValueError:
  38.             logger.warn('No.%s Params input error!' % self.no)
  39.             return
  40.         data = self.y.data
  41.         for i in params:
  42.             if '

  43. * 三、编写测试用例

  44. 都写好啦,终于可以编写接口测试用例了!11,和10列我用来存储执行用例的情况,一个是检查点是否成功,另一个是响应内容。
  45. <div class="blockcode"><blockquote>#!/usr/bin/env python
  46. #coding=utf-8

  47. import unittest
  48. import os
  49. from utils.file_reader import ExcelReader
  50. from utils.log import logger
  51. from utils.config import Config, DATA_PATH
  52. from utils.interface_case import InterfaceCase


  53. class InterfaceTest001(unittest.TestCase):
  54.     excel_path = os.path.join(DATA_PATH, Config().get('data')['interface_case_list'])
  55.     e = ExcelReader(excel_path, 0, True)
  56.     case_list = e.data

  57.     def test_func(self):
  58.         for i in self.case_list:
  59.             #   运行用例前,将xlsx文件中执行结果以及用例执行情况还原
  60.             self.e.set_value(int('%d' % i['No.']), 11, 'Na')
  61.             self.e.set_value(int('%d' % i['No.']), 10, '')
  62.             t = InterfaceCase(i)
  63.             #   是否执行该条用例
  64.             if t.active == 'yes':
  65.                 response = t.run()
  66.                 logger.info(t)
  67.                 #   将用例执行结果以及用例执行情况写入xlsx
  68.                 self.e.set_value(t.no, 10, response['msg'])
  69.                 self.e.set_value(t.no, 11, t.result)


  70. if __name__ == '__main__':
  71.     #   运行测试用例
  72.     unittest.main()
复制代码

事后一些小小的想法

虽然刚开始的时候觉得落叶归根这种excel存储测试用例的方法实在是太赞了,但是写完之后发现了很多的局限性。比如这样写,我就很难用灰蓝博客中介绍的生成html报告的方法,只能看自己输出的日志文件。

项目开始的时候,我想用这个框架做接口测试,但是发现这个测试框架根本就不够灵活。比如我要做一个登录次数上限的用例,我就不能用这个测试框架,必须要自己重新写测试类。

还有一个特别困扰的问题,师父希望接口测试的脚本更加的灵活。灵活到,我给别人发一个脚本,他F5就可以直接运行。而不是这个框架这样,需要其他的测试员去读懂这个框架。读懂之后还要配置这个框架需要的环境。

总的来说,动手编写这个框架还是很开心的,提升了自己编写python脚本的能力。 in params:
                try:
                    params = data[0]
                except KeyError:
                    raise KeyError('No.%s Params "%s" not found!' % (self.no, i))
        self.params = params

    def run(self):
        #   运行用例,暂时只支持POST以及GET方法。client.py中可支持更多参数配置
        h = HTTPsClient(url=self.host+self.url, method=self.requestMethod)
        if self.requestMethod == 'POST':
            self.response = h.json_transform_dict(h.send(data=self.params))
        elif self.requestMethod == 'GET':
            self.response = h.json_transform_dict(h.send(params=self.params))
        else:
            raise KeyError('method "%s" not support!' % self.requestMethod)
        if self.checkPoint:
            try:
                params = self.checkPoint.split('=')
            except TypeError:
                logger.error('checkPoint input error!')
                raise TypeError('checkPoint input error : %s' % self.checkPoint)
            value = str(self.response[params[0]])
            if value != params[1]:
                self.result = 'Fail'
                logger.info('No.%s check point "%s" not found ' % (self.no, self.checkPoint))
                return self.response
            elif value == params[1]:
                self.result = 'Pass'
        else:
            self.result = 'Pass'
        #   判断是否存在关联,如果有且格式正确则将执行后的参数写入配置文件
        #   例如:$token=token,则将response中的token值存入到配置文件中
        if self.relation:
            try:
                l = self.relation.split(',')
            except TypeError:
                logger.error('relation input error!')
                raise TypeError('relation input error : %s' % self.relation)
            for i in l:
                try:
                    params = i[1:].split('=')
                except TypeError:
                    logger.error('relation input error!')
                    raise TypeError('relation input error : %s' % i)
                data = self.y.data[0]
                #   response['data']根据项目不同可能略有差异
                #   此处防止response中想要获取的值为空,产生异常
                if self.response['data'][params[0]] == None:return self.response
                try:
                    data[params[1]] = self.response['data'][params[0]].encode('utf-8')
                except AttributeError:
                    data[params[1]] = self.response['data'][params[0]]
                #   将变量写入yaml文件
                self.y.data = yaml.dump(data, default_flow_style=False)
        return self.response

* 三、编写测试用例

都写好啦,终于可以编写接口测试用例了!11,和10列我用来存储执行用例的情况,一个是检查点是否成功,另一个是响应内容。
[        DISCUZ_CODE_2        ]
事后一些小小的想法

虽然刚开始的时候觉得落叶归根这种excel存储测试用例的方法实在是太赞了,但是写完之后发现了很多的局限性。比如这样写,我就很难用灰蓝博客中介绍的生成html报告的方法,只能看自己输出的日志文件。

项目开始的时候,我想用这个框架做接口测试,但是发现这个测试框架根本就不够灵活。比如我要做一个登录次数上限的用例,我就不能用这个测试框架,必须要自己重新写测试类。

还有一个特别困扰的问题,师父希望接口测试的脚本更加的灵活。灵活到,我给别人发一个脚本,他F5就可以直接运行。而不是这个框架这样,需要其他的测试员去读懂这个框架。读懂之后还要配置这个框架需要的环境。

总的来说,动手编写这个框架还是很开心的,提升了自己编写python脚本的能力。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
发表于 2020-4-23 00:31:21 | 只看该作者
发的是山东省地方
回复 支持 反对

使用道具 举报

本版积分规则

关闭

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

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

GMT+8, 2024-11-16 17:54 , Processed in 0.070401 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

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