zoukankan      html  css  js  c++  java
  • Python接口自动化实战(第二阶段)- 数据与代码分离

    前面我们已经实现了用unittest框架编写测试用例,实现了请求接口的封装,这样虽然已经可以完成接口的自动化测试,但是其复用性并不高。

    我们看到每个方法(测试用例)的代码几乎是一模一样的,试想一下,在我们的测试场景中,一个注册接口有可能会有十几条到几十条测试用例,如果每组数据都编写一个方法,这样将会有更多的重复项代码,不仅执行效率不高,也不好维护。

    接下来将会对框架进行优化,采用数据驱动方式,1)把测试数据用excel表格管理起来,代码做封装,2)用ddt来驱动测试,两部分相互独立。

    1.数据与代码分离:excel管理测试数据

    在上一节的代码中, test_register.py 模块中,定义了三个方法(三个测试用例),每一个测试用例都需要提供一组测试数据:url,params,method,expect_res等,不利于修改和构建,现在我们新建 excel文件(TestData.xlsx )。如下:

    自动化用例设计:

    关于自动化测试用例的设计,是基于对接口业务流程的熟悉,只有熟悉业务流程,才能设计出较好的自动化测试数据。这边要考虑的点很多,

    • id:用例编号,从1开始,唯一
    • module:接口模块
    • case_name:用例名称
    • method:请求类型
    • url:接口地址信息
    • params:请求参数

    用例设计好了,这边我遇到了三个问题:

    第一:如何读取测试数据?

    第二:读取的测试数据,应该存储成什么格式?

    第三:数据如何传递?

    当然,用例的设计对于越复杂的场景,考虑的就会越多,其中有一点很重要,尽量保持用例的独立性,用例之间的关联性不要太强,避免一条用例的失败,导致其他用例也无法执行。

    xlrd 使用 

    安装xlrd第三方库,pip install xlrd.from xlrd import open_workbook

    wb = open_workbook("TestData.xlsx")  # 打开excel
    sh = wb.sheet_by_name("register")  # 定位工作表
    print(sh.row_values(0))   # 输出第1行的所有值(列表格式)
    print(dict(zip(sh.row_values(0),sh.row_values(1))))  # 将数据和标题组成字
    for i in range(sh.nrows): print(sh.row_values(i))

     封装读取excel操作 -如何读取测试数据?

    实现代码如下:

    from xlrd import open_workbook
    class Doexcel():
    
        def excel_data_list(self, filename, sheetname):
            data_list = []
            wb = open_workbook(filename)  # 打开excel
            sh = wb.sheet_by_name(sheetname)  # 定位工作表
            header = sh.row_values(0)   # 获取标题行的数据
            for i in range(1, sh.nrows):   # 跳过标题行,从第二行开始获取数据
                col_datas = dict(zip(sh.row_values(0), sh.row_values(i)))   # 将标题和每一行的数据,组装成字典
                data_list.append(col_datas)   # 将字典添加到列表中 ,列表嵌套字典,相当于每个字典的元素都是一个列表(也就是一行数据)
            return data_list
    
        def get_test_data(self, data_list, case_id):
            '''
            :param data_list: 工作表的所有行数据
            :param case_id: 用例id,用来判断执行哪几条case。如果id=all ,那就执行所有用例;否则,执行列表参数中指定的用例
            :return:  返回最终要执行的测试用例
            '''
            if case_id == 'all':    
                final_data = data_list
            else:
                final_data = []
                for item in data_list:
                    if item['id'] in case_id:
                        final_data.append(item)
            return final_data

    if __name__ == '__main__':
    data_list=Doexcel().excel_data_list('F:JialiProgramfileserviceX_API_TestTest_datasTestData.xlsx','register')
    final_data=Doexcel().get_test_data(data_list, [1,2,3])
    print(final_data)

    执行结果

    [{'method': 'post', 'expect_res': 200.0, 'actual_res': '', 'id': 1.0, 'test_res': '', 'case_name': 'test_register_normal', 'url': 'http://27.154.55.14:8180/api/fcb2bcrm/webRegister', 'module': 'register', 'params': '{"LoginAccount":"test01@gamil.com","Password":"123456","Type":"Pro"}'}, 
    {'method': 'post', 'expect_res': 400.0, 'actual_res': '', 'id': 2.0, 'test_res': '', 'case_name': 'test_register_existing', 'url': 'http://27.154.55.14:8180/api/fcb2bcrm/webRegister', 'module': 'register', 'params': '{"LoginAccount":"test01@gamil.com","Password":"123456","Type":"Pro"}'},
    {'method': 'post', 'expect_res': 400.0, 'actual_res': '', 'id': 3.0, 'test_res': '', 'case_name': 'test_register_invalid_email', 'url': 'http://27.154.55.14:8180/api/fcb2bcrm/webRegister', 'module': 'register', 'params': '{"LoginAccount":"test01@gamil","Password":"123456","Type":"Pro"}'}]

    2.ddt 数据驱动- 如果传递数据?

    数据驱动,个人理解就是测试数据的参数化

    1)安装第三方库 : pip install ddt

    2)引入ddt模块:from ddt import ddt,data 

    3)test_register.py 代码加入ddt

    # 导入
    import unittest
    import requests
    from Common.http_request import HttpRequest
    from ddt import ddt,data   # 引入ddt模块
    from Common.do_excel import *
    
    test_data = Doexcel().excel_data_list('F:JialiProgramfileserviceX_API_TestTest_datasTestData.xlsx','register')   #读取工作表 register 的所有数据 ,返回的是个列表嵌套字典格式
    
    @ddt
    class TestRegister (unittest.TestCase):   # 类必须以Test开头,继承TestCase
    
        def setUp(self):
            print("======开始执行测试用例======")
    
        def tearDown(self):
            print("======测试用例执行完毕======")
    
        # 测试用例
        @data(*test_data)   
        def test_register(self, data_itme):  # data_item 就是每一组测试数据(字典的形式)
            # 发送请求
            res = HttpRequest().http_request(data_itme['url'],eval(data_itme['params']),data_itme['method'])
            # 断言:
            try:
                self.assertEqual(int(data_itme['expect_res']), res.status_code)
            except AssertionError as e:
                print('Failed')
                raise e   # 注意一定要抛出异常

    3.测试结果写回 - 扩展doExcel类

    在excel表格中,有 两列的值是需要在执行完测试用例后写回的:实际结果和测试结果。

        def write_back_result(self, filename, sheetname, row, actual_res, test_result):
            '''
            
            :param filename: 文件名
            :param sheetname: 要写回数据的表格
            :param row: 要写回的行数
            :param actual_res: 实际结果 :实际结果是第8列,测试结果是第9列 ,比如:(2,8)(2,9)
            :param test_result: 测试结果 :pass/failed
            :return: 
            '''
            wb = load_workbook(filename)
            sheet = wb[sheetname]
            sheet.cell(row,8).value = actual_res    
            sheet.cell(row,9).value = test_result 
            wb.save(filename)

    在test_register.py文件中,每次执行完一组测试数据,调用 write_back_result()方法,将所需要的参数传递进去。

     

  • 相关阅读:
    毕业设计第一周第一天
    python添加水印
    python 连接MySQL数据库
    利用Python爬取免费代理IP
    Python将大的csv文件拆分多个小的csv文件
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream
    org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://localhost:9000/usr/local/spark/zytdemo
    Error: Could not open client transport with JDBC Uri: jdbc:hive2://localhost:10000: java.net.ConnectException: 拒绝连接 (Connection refused) (state=08S01,code=0)
    大数据常用命令
    硬件工程师必会电路模块之MOS管应用(转)
  • 原文地址:https://www.cnblogs.com/testjiali/p/10421304.html
Copyright © 2011-2022 走看看