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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
    LCA 最近公共祖先 (模板)
    线段树,最大值查询位置
    带权并查集
    转负二进制
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
  • 原文地址:https://www.cnblogs.com/zy7y/p/15119487.html
Copyright © 2011-2022 走看看