zoukankan      html  css  js  c++  java
  • HttpRunner3源码阅读:9. 测试用例中的类定义testcase

    testcase

    testcase.py这里主要写了一个测试文件里的几个组成类及其方法(Config/Step...)

    可用资料

    inspect[类型检查...]:https://docs.python.org/zh-cn/3/library/inspect.html
    property[方法转为只读属性]:https://docs.python.org/zh-cn/3/library/functions.html?highlight=property#property

    导包

    import inspect  # :类型检查、获取源代码、检查类与函数、检查解释器的调用堆栈。
    from typing import Text, Any, Union, Callable
    
    from httprunner.models import (
        TConfig,
        TStep,
        TRequest,
        MethodEnum,
        TestCase,
    )
    

    源码附注释

    Config类

    class Config(object):
        # 接收一个name参数
        def __init__(self, name: Text):
            # 以下定义的都是私有属性
            # 该属性无法通过对象.属性名访问
            # Config().__name
            # 但可以通过对象._类名+属性名访问
            # Config()._Config__name
            # _属性名,则为一种规范表示不想被当前程序外的地方访问,但可以通过对象.属性名方法
            self.__name = name
            self.__variables = {}
            self.__base_url = ""
            self.__verify = False
            self.__export = []
            # 这个权重 是用在locust 中的
            self.__weight = 1
            # 返回调用方堆栈的帧记录列表。返回列表中的第一个条目表示调用方; 最后一个条目表示堆栈上的最外层调用。
            caller_frame = inspect.stack()[1]
            self.__path = caller_frame.filename
        
        # 修饰的方法可用属性方式调用x.name
        @property
        def name(self) -> Text:
            return self.__name
    
        @property
        def path(self) -> Text:
            return self.__path
    
        @property
        def weight(self) -> int:
            return self.__weight
        
    # 设置配置信息以下...
        def variables(self, **variables) -> "Config":
            """变量字典合并"""
            self.__variables.update(variables)
            return self
    
        def base_url(self, base_url: Text) -> "Config":
            self.__base_url = base_url
            return self
    
        def verify(self, verify: bool) -> "Config":
            self.__verify = verify
            return self
    
        def export(self, *export_var_name: Text) -> "Config":
            # 末尾一次性追加另一个序列中的多个值
            self.__export.extend(export_var_name)
            return self
    
        def locust_weight(self, weight: int) -> "Config":
            self.__weight = weight
            return self
    
        def perform(self) -> TConfig:
            return TConfig(
                name=self.__name,
                base_url=self.__base_url,
                verify=self.__verify,
                variables=self.__variables,
                export=list(set(self.__export)),
                path=self.__path,
                weight=self.__weight,
            )
    

    StepRequestValidation类

    class StepRequestValidation(object):
        # 传入一个测试步骤模型对象
        def __init__(self, step_context: TStep):
            self.__step_context = step_context
    
        # 以下各验证方法
        def assert_equal(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            """ jmes_pathn: json搜索表达式, expected_value:期望值
                message: 描述
            """
            # 追加到验证器列表
            self.__step_context.validators.append(
                {"equal": [jmes_path, expected_value, message]}
            )
            return self
        # 不相等
        def assert_not_equal(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"not_equal": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_greater_than(
            self, jmes_path: Text, expected_value: Union[int, float], message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"greater_than": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_less_than(
            self, jmes_path: Text, expected_value: Union[int, float], message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"less_than": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_greater_or_equals(
            self, jmes_path: Text, expected_value: Union[int, float], message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"greater_or_equals": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_less_or_equals(
            self, jmes_path: Text, expected_value: Union[int, float], message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"less_or_equals": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_length_equal(
            self, jmes_path: Text, expected_value: int, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"length_equal": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_length_greater_than(
            self, jmes_path: Text, expected_value: int, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"length_greater_than": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_length_less_than(
            self, jmes_path: Text, expected_value: int, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"length_less_than": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_length_greater_or_equals(
            self, jmes_path: Text, expected_value: int, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"length_greater_or_equals": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_length_less_or_equals(
            self, jmes_path: Text, expected_value: int, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"length_less_or_equals": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_string_equals(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"string_equals": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_startswith(
            self, jmes_path: Text, expected_value: Text, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"startswith": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_endswith(
            self, jmes_path: Text, expected_value: Text, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"endswith": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_regex_match(
            self, jmes_path: Text, expected_value: Text, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"regex_match": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_contains(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"contains": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_contained_by(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"contained_by": [jmes_path, expected_value, message]}
            )
            return self
    
        def assert_type_match(
            self, jmes_path: Text, expected_value: Any, message: Text = ""
        ) -> "StepRequestValidation":
            self.__step_context.validators.append(
                {"type_match": [jmes_path, expected_value, message]}
            )
            return self
    
        def perform(self) -> TStep:
            return self.__step_context
    

    StepRequestExtraction

    
    # 步骤中提取参数类,
    # 提供验证方法,返回验证类对象 StepRequestValidation
    class StepRequestExtraction(object):
        def __init__(self, step_context: TStep):
            self.__step_context = step_context
    
        def with_jmespath(self, jmes_path: Text, var_name: Text) -> "StepRequestExtraction":
            self.__step_context.extract[var_name] = jmes_path
            return self
    
        # def with_regex(self):
        #     # TODO: extract response html with regex
        #     pass
        #
        # def with_jsonpath(self):
        #     # TODO: extract response json with jsonpath
        #     pass
    
        def validate(self) -> StepRequestValidation:
            return StepRequestValidation(self.__step_context)
        
        def perform(self) -> TStep:
            return self.__step_context
    

    RequestWithOptionalArgs

    # 步骤中:Request请求 ,请求header等配置
    # 提取数据, 校验,teardown_hook
    class RequestWithOptionalArgs(object):
        def __init__(self, step_context: TStep):
            self.__step_context = step_context
    
        def with_params(self, **params) -> "RequestWithOptionalArgs":
            self.__step_context.request.params.update(params)
            return self
    
        def with_headers(self, **headers) -> "RequestWithOptionalArgs":
            self.__step_context.request.headers.update(headers)
            return self
    
        def with_cookies(self, **cookies) -> "RequestWithOptionalArgs":
            self.__step_context.request.cookies.update(cookies)
            return self
    
        def with_data(self, data) -> "RequestWithOptionalArgs":
            self.__step_context.request.data = data
            return self
    
        def with_json(self, req_json) -> "RequestWithOptionalArgs":
            self.__step_context.request.req_json = req_json
            return self
    
        def set_timeout(self, timeout: float) -> "RequestWithOptionalArgs":
            self.__step_context.request.timeout = timeout
            return self
    
        def set_verify(self, verify: bool) -> "RequestWithOptionalArgs":
            self.__step_context.request.verify = verify
            return self
    
        def set_allow_redirects(self, allow_redirects: bool) -> "RequestWithOptionalArgs":
            self.__step_context.request.allow_redirects = allow_redirects
            return self
    
        def upload(self, **file_info) -> "RequestWithOptionalArgs":
            self.__step_context.request.upload.update(file_info)
            return self
    
        def teardown_hook(
            self, hook: Text, assign_var_name: Text = None
        ) -> "RequestWithOptionalArgs":
            if assign_var_name:
                self.__step_context.teardown_hooks.append({assign_var_name: hook})
            else:
                self.__step_context.teardown_hooks.append(hook)
    
            return self
    
        def extract(self) -> StepRequestExtraction:
            return StepRequestExtraction(self.__step_context)
    
        def validate(self) -> StepRequestValidation:
            return StepRequestValidation(self.__step_context)
    
        def perform(self) -> TStep:
            return self.__step_context
    

    RunRequest

    # 请求前置:参数变量,setup_hook,请求最终调用RequestWithOptionalArgs
    # 此方法Demo中有使用
    class RunRequest(object):
        def __init__(self, name: Text):
            self.__step_context = TStep(name=name)
    
        def with_variables(self, **variables) -> "RunRequest":
            self.__step_context.variables.update(variables)
            return self
    
        def setup_hook(self, hook: Text, assign_var_name: Text = None) -> "RunRequest":
            if assign_var_name:
                self.__step_context.setup_hooks.append({assign_var_name: hook})
            else:
                self.__step_context.setup_hooks.append(hook)
    
            return self
    
        def get(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.GET, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def post(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.POST, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def put(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.PUT, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def head(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.HEAD, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def delete(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.DELETE, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def options(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.OPTIONS, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
        def patch(self, url: Text) -> RequestWithOptionalArgs:
            self.__step_context.request = TRequest(method=MethodEnum.PATCH, url=url)
            return RequestWithOptionalArgs(self.__step_context)
    
    

    StepRefCase

    # 需要传入步骤, Demo中并未使用该类,
    class StepRefCase(object):
        def __init__(self, step_context: TStep):
            self.__step_context = step_context
        # 结束时运行函数
        def teardown_hook(self, hook: Text, assign_var_name: Text = None) -> "StepRefCase":
            if assign_var_name:
                self.__step_context.teardown_hooks.append({assign_var_name: hook})
            else:
                self.__step_context.teardown_hooks.append(hook)
    
            return self
        # 导出变量
        def export(self, *var_name: Text) -> "StepRefCase":
            self.__step_context.export.extend(var_name)
            return self
    
        def perform(self) -> TStep:
            return self.__step_context
    

    RunTestCase

    # 步骤 -> 测试用例类(引入), 此方法Demo有案例
    class RunTestCase(object):
        def __init__(self, name: Text):
            self.__step_context = TStep(name=name)
    
        def with_variables(self, **variables) -> "RunTestCase":
            self.__step_context.variables.update(variables)
            return self
    
        def setup_hook(self, hook: Text, assign_var_name: Text = None) -> "RunTestCase":
            if assign_var_name:
                self.__step_context.setup_hooks.append({assign_var_name: hook})
            else:
                self.__step_context.setup_hooks.append(hook)
    
            return self
        # testcase 测试用例类
        def call(self, testcase: Callable) -> StepRefCase:
            self.__step_context.testcase = testcase
            return StepRefCase(self.__step_context)
    
        def perform(self) -> TStep:
            return self.__step_context
    
    

    Step

    # 步骤
    class Step(object):
        # 可以是以下5种对象
        def __init__(
            self,
            step_context: Union[
                StepRequestValidation,
                StepRequestExtraction,
                RequestWithOptionalArgs,
                RunTestCase,
                StepRefCase,
            ],
        ):
            self.__step_context = step_context.perform()
    
        @property
        def request(self) -> TRequest:
            return self.__step_context.request
    
        @property
        def testcase(self) -> TestCase:
            return self.__step_context.testcase
    
        def perform(self) -> TStep:
            return self.__step_context
    
    
    作者:zy7y
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    java基本数据类型及运算的注意事项
    B-Tree 和 B+Tree 结构及应用,InnoDB 引擎, MyISAM 引擎
    软件工程与软件开发模型、软件开发方法
    2020年3月份Unity3D游戏源码合集-免费下载
    独立游戏开发必备!8个效果不错的Unity3D 免费模型资源包
    2019年4月份整理的Unity3D 20个实用插件-免费下载
    2019年4月份整理的Unity3D游戏完整源码
    2019年3月整理的2D美术资源合集
    画面效果都不错!20个精品Unity3D着色器插件
    Unity3D中UnityPlayerActivity与UnityPlayerNativeActivity有什么区别
  • 原文地址:https://www.cnblogs.com/zy7y/p/15119487.html
Copyright © 2011-2022 走看看