• 【测试沉思录】23. 如何实现基于场景的接口自动化测试用例?


    作者:陈爱娇 编辑:毕小烦

    自动化本身是为了提高工作效率,不论选择何种框架,何种开发语言,我们最终想实现的效果,就是让大家用最少的代码,最小的投入,完成自动化测试的工作。

    基于这个想法,我们的接口自动化测试思路如下:

    1. 不变的内容全部通过配置化来实现,比如:脚本执行的环境、请求的 HOST、URL 路径、测试数据等;
    2. 环境和数据关联变更:依据不同的环境,选择不同的配置及对应的测试数据;
    3. 抽取公共方法,避免冗余代码;
    4. 场景化的用例,实现可配置化;
    5. 数据驱动;

    一. 问题

    在做自动化的过程中,不能只考虑单接口的脚本,也要考虑场景化的用例。 场景化的用例不需要每个步骤都去校验所有的数据,可能更多看重串联后的最终效果

    那什么是场景用例?

    其实就是多个接口组成的业务场景,常规写代码的做法是,先调用接口 1,验证结果, 再调用接口 2,再继续接口 3,… 等等; 在测试场景中,可能只是各个接口的入参不一样,或者是调用的接口不一样。这样代码写起来就会冗余。

    比如:

    def test_01(self):
        # step 01
        result1 = PackDemo().getTest()
        assert result1 == 4
    
        # step02
        result2 = PackDemo2().getTest2("name")
        assert result2 == 'name'
        
        # step03
        result3 = DemoApi().getTest()
        assert result3 == 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这样的用例,对于简单的接口没什么问题,但是对于复杂的接口,校验逻辑比较多,或者入参比较多,实现的方式就过于单一了。且不同场景的话,每个都要更改调用的步骤和返回值,场景越多冗余越多。

    如果使用配置化的方式,每次从配置文件中动态加载配置的场景用例, 而且能够做到加载后做对应的断言,那该多好。

    怎么做呢?

    咱们看看一些核心的实现。

    二. 方案

    2.1 项目结构

    项目结构如下:

    img

    采用当前比较流行的 Python + Pytest + Allure 来实现,具体结构不做展开。

    2.2 场景用例的配置数据

    # test_scenario.json
    {
      "test_01": {
        "step_1": {  ---- 步骤节点名称,可自定义
          "packagePath": "api", --- 这个步骤要运行的方法所属类的包路径
          "class": "DemoApi", --- 这个步骤要运行的方法所属类名称
          "method": "getTest", --- 这个步骤要运行的方法名称
          "request": null,  ---这个步骤运行的方法入参
          "response": 2, ---这个步骤运行的结果,可以是一个值,或者对象
          "verify": { --- 数据校验的节点
            "type": 1, ---数据校验的类型
            "keys": null  ---如果是校验的特定字段,这里需要输入部分校验的字段
          }
        },
        "step_2": {
          "packagePath": "api.demo",
          "class": "PackDemo",
          "method": "getTest2",
          "request": "request -> name",
          "response": 6,
          "verify": {
            "type": 1,
            "keys": null
          }
        },
        "step_3": {
          "packagePath": "api.demo",
          "class": "PackDemo2",
          "method": "getTest3",
          "request": {
            "name": "param-name",
            "num_list": ["a", "b", "c"]
          },
          "response": 8,
          "verify": {
            "type": 1,
            "keys": null
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2.3 动态加载类

    在我们配置了以上的测试场景的数据后,我们希望在用例执行的过程中,通过获取我们的配置,能够动态的加载数据文件中提到的方法,并执行对应的方法,那这个过程的实现我们主要通过如下的动态加载类来实现。

    # DynamicLoad.py 
    # 部分主要的摘录如下
     def __load_module(self):
            """
            加载对应路径下的模块
            :param package_path: 包路径
            :param class_name: 类名称
            :return:
            """
            return importlib.import_module("." + self.class_name, package=self.package_path)
    
    def __getClassInstance(self):
        """
        加载对应的模块下的类,并返回对应类的实例 
        :param module_name: 对应的模块
        :param class_name:
        :return:
        """
        self.my_module = self.__load_module()
        self.my_class = getattr(self.my_module, self.class_name)()
        return self.my_class
    
    def execMethod(self, method, *args):
        """
        加载对应类下的方法 
        :param instance: 对应的实例
        :param method: 要执行的方法
        :return:
        """
        result = getattr(self.__getClassInstance(), method)(*args)
        return result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    有了以上动态加载的方法后,在执行场景用例时,依据上述的方法,就可以执行测试文件中提到的方法。

    2.4 场景分析类

    在场景用例的测试数据中,除了需要解析需要执行的类、方法外,还要解析文件中涉及到的出入参及数据比对方式,因此,这里还需要一个场景分析类,来解析数据文件中关于具体执行过程的配置。

     #ScenariosAnalyze.py
     def analyse_exe_scenario(self, case_data):
            step_result = {}
            summary = True
            for i in case_data:
                instance = DynamicLoad(case_data[i]['packagePath'], case_data[i]['class'])
                if case_data[i]['request'] is not None:
                    result = instance.execMethod(case_data[i]['method'], case_data[i]['request'])
                else:
                    result = instance.execMethod(case_data[i]['method'])
                if case_data[i]['verify'] is not None:
                    compare_type = case_data[i]['verify']['type']
                    keys = case_data[i]['verify']['keys']
                    step_compare_result = DataCompare().compare_type(compare_type=compare_type, actual=result,
                                                                     expect=case_data[i]['response'], keys=keys)
                    if not step_compare_result:
                        summary = False
                step_result[i] = step_compare_result
            step_result['summary'] = summary
            return step_result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.5 用例实现

    # @File : test_scenario.py
    
    class TestScenario:
    
        @allure.story('场景用例01')
        @allure.severity(allure.severity_level.BLOCKER)
        @pytest.mark.smoke
        def test_01(self):
            result = None
            case_data = self.test_data_json['test_01']
            result = self.scenario_analyze.analyse_exe_scenario(case_data)
            assert result['summary'] is True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通过上述简单的脚本调用,就可以完成一个场景用例的测试了。

    三. 小结

    以上就是场景用例配置化的实现思路。

    它的优点是:

    1. 配置化: 一切固定不变的内容全部配置化,最终达到:一个环境配置文件,一套脚本,几套测试数据,依据环境的不同选择不同的测试数据执行对应的测试脚本;
    2. 门槛低: 因为配置化,测试同学只要把测试数据文件中的关键节点配置好,然后在脚本中写下调用方法,就完成用例编写了;
    3. 好扩展: 在后续的实现中,可以将这些配置全部页面化,包括环境、数据、脚本,达到无代码开发的目的;

    缺点当然是不够灵活,所以没有完美的方案,只有合适的,以上,仅供大家参考。

    (完)

  • 相关阅读:
    Day_17> 动态内存管理
    SAP 电商云 Spartacus UI 去除 Checkout 页面 header 和 footer 区域的几种方法介绍
    MyBatis-1-学习记录环境搭建和入门案例
    提到Canvas,必须好好唠唠它的图像操作能力
    十大免费好用的视频软件推荐,新手小白必备
    RabbitMQ的部署
    buu web部分wp
    黑马Java笔记第5讲—方法
    JS--拷贝数组的方法(浅拷贝)
    idea启动与jar包启动中使用resource资源文件路径问题总结
  • 原文地址:https://blog.csdn.net/wirelessqa/article/details/128201578