testcase
testcase.py
这里主要写了一个测试文件里的几个组成类及其方法(Config/Step…)
可用资料
inspect[类型检查…]:https://docs.python.org/zh-cn/3/library/inspect.htmlproperty[方法转为只读属性]:https://docs.python.org/zh-cn/3/library/functions.html?highlight=property#property
导包
import inspect # :类型检查、获取源代码、检查类与函数、检查解释器的调用堆栈。from typing import Text, Any, Union, Callablefrom 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 = nameself.__variables = {}self.__base_url = ""self.__verify = Falseself.__export = []# 这个权重 是用在locust 中的self.__weight = 1# 返回调用方堆栈的帧记录列表。返回列表中的第一个条目表示调用方; 最后一个条目表示堆栈上的最外层调用。caller_frame = inspect.stack()[1]self.__path = caller_frame.filename# 修饰的方法可用属性方式调用x.name@propertydef name(self) -> Text:return self.__name@propertydef path(self) -> Text:return self.__path@propertydef weight(self) -> int:return self.__weight# 设置配置信息以下...def variables(self, **variables) -> "Config":"""变量字典合并"""self.__variables.update(variables)return selfdef base_url(self, base_url: Text) -> "Config":self.__base_url = base_urlreturn selfdef verify(self, verify: bool) -> "Config":self.__verify = verifyreturn selfdef export(self, *export_var_name: Text) -> "Config":# 末尾一次性追加另一个序列中的多个值self.__export.extend(export_var_name)return selfdef locust_weight(self, weight: int) -> "Config":self.__weight = weightreturn selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef assert_startswith(self, jmes_path: Text, expected_value: Text, message: Text = "") -> "StepRequestValidation":self.__step_context.validators.append({"startswith": [jmes_path, expected_value, message]})return selfdef assert_endswith(self, jmes_path: Text, expected_value: Text, message: Text = "") -> "StepRequestValidation":self.__step_context.validators.append({"endswith": [jmes_path, expected_value, message]})return selfdef 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 selfdef assert_contains(self, jmes_path: Text, expected_value: Any, message: Text = "") -> "StepRequestValidation":self.__step_context.validators.append({"contains": [jmes_path, expected_value, message]})return selfdef 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 selfdef 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 selfdef perform(self) -> TStep:return self.__step_context
StepRequestExtraction
# 步骤中提取参数类,# 提供验证方法,返回验证类对象 StepRequestValidationclass StepRequestExtraction(object):def __init__(self, step_context: TStep):self.__step_context = step_contextdef with_jmespath(self, jmes_path: Text, var_name: Text) -> "StepRequestExtraction":self.__step_context.extract[var_name] = jmes_pathreturn self# def with_regex(self):# # TODO: extract response html with regex# pass## def with_jsonpath(self):# # TODO: extract response json with jsonpath# passdef validate(self) -> StepRequestValidation:return StepRequestValidation(self.__step_context)def perform(self) -> TStep:return self.__step_context
RequestWithOptionalArgs
# 步骤中:Request请求 ,请求header等配置# 提取数据, 校验,teardown_hookclass RequestWithOptionalArgs(object):def __init__(self, step_context: TStep):self.__step_context = step_contextdef with_params(self, **params) -> "RequestWithOptionalArgs":self.__step_context.request.params.update(params)return selfdef with_headers(self, **headers) -> "RequestWithOptionalArgs":self.__step_context.request.headers.update(headers)return selfdef with_cookies(self, **cookies) -> "RequestWithOptionalArgs":self.__step_context.request.cookies.update(cookies)return selfdef with_data(self, data) -> "RequestWithOptionalArgs":self.__step_context.request.data = datareturn selfdef with_json(self, req_json) -> "RequestWithOptionalArgs":self.__step_context.request.req_json = req_jsonreturn selfdef set_timeout(self, timeout: float) -> "RequestWithOptionalArgs":self.__step_context.request.timeout = timeoutreturn selfdef set_verify(self, verify: bool) -> "RequestWithOptionalArgs":self.__step_context.request.verify = verifyreturn selfdef set_allow_redirects(self, allow_redirects: bool) -> "RequestWithOptionalArgs":self.__step_context.request.allow_redirects = allow_redirectsreturn selfdef upload(self, **file_info) -> "RequestWithOptionalArgs":self.__step_context.request.upload.update(file_info)return selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 selfdef 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 = testcasereturn 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()@propertydef request(self) -> TRequest:return self.__step_context.request@propertydef testcase(self) -> TestCase:return self.__step_context.testcasedef perform(self) -> TStep:return self.__step_context