HttpRunner3.x 源码解析(5)-runner.py

news2025/5/23 17:18:33

首先看下生成的pytest文件

from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase


class TestCaseLogin(HttpRunner):

    config = (
        Config("登录成功").variables(**{"password": "tester", "expect_foo2": "config_bar2"}).base_url("https://api.pity.fun")
        .verify(False)
        .export(*["token"])
    )

    teststeps = [
        Step(
            RunRequest("登录成功")
            .with_variables(**{"foo1": "bar1"})
            .setup_hook("${get_request($request)}")
            .post("/auth/login")
            .with_headers(**{"Content-Type": "application/json"})
            .with_json({"username": "${ENV(username)}", "password": "${ENV(password)}"})
            .teardown_hook("${get_reponse($response)}")
            .extract()
            .with_jmespath("body.msg", "token")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal("body.code", 0)
            .assert_equal("body.msg", "哈哈哈")
        ),
    ]


if __name__ == "__main__":
    TestCaseLogin().test_start()

首先类继承了HttpRunner类

主要包括config和teststeps两部分

函数的入库是test_start()方法

test_start

  def test_start(self, param: Dict = None) -> "HttpRunner":
        """main entrance, discovered by pytest"""
        self.__init_tests__()
        self.__project_meta = self.__project_meta or load_project_meta(
            self.__config.path
        )
        self.__case_id = self.__case_id or str(uuid.uuid4())
        self.__log_path = self.__log_path or os.path.join(
            self.__project_meta.RootDir, "logs", f"{self.__case_id}.run.log"
        )
        log_handler = logger.add(self.__log_path, level="DEBUG")

        # parse config name
        config_variables = self.__config.variables
        if param:
            config_variables.update(param)
        config_variables.update(self.__session_variables)
        self.__config.name = parse_data(
            self.__config.name, config_variables, self.__project_meta.functions
        )

        if USE_ALLURE:
            # update allure report meta
            allure.dynamic.title(self.__config.name)
            allure.dynamic.description(f"TestCase ID: {self.__case_id}")

        logger.info(
            f"Start to run testcase: {self.__config.name}, TestCase ID: {self.__case_id}"
        )

        try:
            return self.run_testcase(
                TestCase(config=self.__config, teststeps=self.__teststeps)
            )
        finally:
            logger.remove(log_handler)
            logger.info(f"generate testcase log: {self.__log_path}")

首先调用了__init_tests__()方法

 teststeps是pytest文件中的Step列表,示例只有1个步骤。

 

config.perform方法返回了一个Tconfig对象,这个对象定义了testcase的config中的关键字和内容

 

teststeps是py文件中的Step列表,

调用的step.perform()方法,返回__step_context,而__step_context来自step_context调用perfoem方法。

在Step类的初始化函数可以看到,step_context可以是如下几种

 

当step_contxt时RunTestCase时,调用它的perfom方法如下,可以看到返回的是一个TStep对象。

 

 接着看test_start()

self.__project_meta = self.__project_meta or load_project_meta(
    self.__config.path
)

 返回项目的资源文件

self.__case_id为caseid或者是一个uuid
self.__log_path为日志目录
config_variables = self.__config.variables为config部分的变量
self.__config.name = parse_data(
    self.__config.name, config_variables, self.__project_meta.functions
)获取config中的name
if USE_ALLURE:
    # update allure report meta
    allure.dynamic.title(self.__config.name)
    allure.dynamic.description(f"TestCase ID: {self.__case_id}")

logger.info(
    f"Start to run testcase: {self.__config.name}, TestCase ID: {self.__case_id}"
)

如果用了allure报告,则定义title和描述

 

return self.run_testcase(
    TestCase(config=self.__config, teststeps=self.__teststeps)
)

将config和teststeps列表传给TestCase并调用HttpRunner类的run_testcase方法执行用例

run_testcase

这个方法最后返回的也是HttpRunner实例

主要的是下面这一句,执行了用例的步骤。

extract_mapping = self.__run_step(step)

 __run_step方法

如果步骤中存在request,则调用__run_step_request来执行步骤,并返回返回testdata

如果存在testcase,则调用__run_step_testcase(step)来执行,最后返回test_data

    def __run_step(self, step: TStep):
        """run teststep, teststep maybe a request or referenced testcase"""
        logger.info(f"run step begin: {step.name} >>>>>>")

        if step.request:
            step_data = self.__run_step_request(step)
        elif step.testcase:
            step_data = self.__run_step_testcase(step)
        else:
            raise ParamsError(
                f"teststep is neither a request nor a referenced testcase: {step.dict()}"
            )

        self.__step_datas.append(step_data)
        logger.info(f"run step end: {step.name} <<<<<<\n")
        return step_data.export_vars

__run_step_request

这个方法解析request并调用request方法来执行

resp = self.__session.request(method, url, **parsed_request_dict)

 

parsed_request_dict解析请求字典

parsed_request_dict

{'method': 'POST', 'url': '/auth/login', 'params': {}, 'headers': {'Content-Type': 'application/json'}, 'req_json': {'username': 'tester', 'password': 'tester'}, 'data': None, 'cookies': {}, 'timeout': 120, 'allow_redirects': True, 'verify': False}

if step.setup_hooks:
    self.__call_hooks(step.setup_hooks, step.variables, "setup request")

如果存在setup_hooks就调用hook

 

 

# teardown hooks
if step.teardown_hooks:
    self.__call_hooks(step.teardown_hooks, step.variables, "teardown request")

如果存在teardown就调用hook

 最后返回step_data

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

17_I.MX6ULL_内部RTC

目录 I.MX6U RTC简介 相关寄存器 实验源码 I.MX6U RTC简介 实时时钟是很常用的一个外设,通过实时时钟我们就可以知道年、月、日和时间等信息。因此在需要记录时间的场合就需要实时时钟,可以使用专用的实时时钟芯片来完成此功能,但是现在大多数的MCU或者MPU内部就已经自带了…

一、Locust快速 入门

1 . 介绍 Locust 是一种易于使用、可编写脚本且可扩展的性能测试工具。 您可以在常规 Python 代码中定义用户的行为&#xff0c;而不是被困在 UI 或限制性领域特定语言中。 这使得 Locust 可以无限扩展并且对开发人员非常友好。 用普通的旧 Python 编写测试场景 如果您希望…

【华为OD机试】1038 - 学英语

文章目录一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1二、代码参考作者&#xff1a;KJ.JK&#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x…

基于价值认同的需求侧电能共享分布式交易策略(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

惊喜开箱!品牌可以从 Ledger 引领的顶级体验之一中学到什么?

Ledger 是加密货币硬件钱包的领先供应商&#xff0c;它通过进入 The Sandbox 并创建游戏化体验来扩大其教育计划&#xff0c;从而在虚拟世界中掀起波澜。通过在这个令人兴奋的新空间打造自己的品牌&#xff0c;Ledger 正在接触更广泛的受众&#xff0c;并以有趣的方式与人们互动…

回收站清空了怎么恢复?快来get实用方法!

案例&#xff1a;回收站清空了怎么恢复&#xff1f; 【真的栓Q了&#xff0c;我刚点击回收站&#xff0c;不知道按错了什么&#xff0c;回收站被清空了&#xff0c;大家有什么方法可以恢复回收站里的文件吗&#xff1f;请大家给我出出主意吧&#xff01;谢谢啦&#xff01;】 …

不愧是比亚迪!

最近这段时间&#xff0c;因为我自己准备买车嘛&#xff0c;然后先后去试驾了比亚迪汉、小鹏P7i、蔚来ET5、智己LS7这几辆车&#xff0c;接下来想分4篇文章依次给大家分享一下这四个品牌的车试驾体验。比亚迪汉小鹏P7i蔚来ET5这四个品牌总共花了三天时间&#xff0c;也算是比较…

STC89C52定时器的简介

一、序言 针对于STC89C52RC而言&#xff0c;这个芯片内部包含了三个定时器——T0、T1和T2&#xff0c;他们的中断优先级分别是1、3和5。 怎么还有一个定时器2呢&#xff1f;博主也是今天整理这篇博客的时候&#xff0c;翻阅芯片手册才发现的。如果说&#xff0c;我们经常用的…

00后面试华为软件测试工程师,竭尽全力拿到15K。。。。。

不废话&#xff0c;直接重点 一般软件测试的面试分为三轮&#xff1a;笔试&#xff0c;HR面试&#xff0c;技术面试。 前两轮&#xff0c;根据不同企业&#xff0c;或有或无&#xff0c;但最后一个技术面试是企业了解你“行不行”的关键环节&#xff0c;每个企业都会有的。 在…

从C语言到C++(第一章_C++入门_中篇)缺省参数+函数重载+引用

目录 1.缺省参数 1.1缺省参数概念 1.2缺省参数的使用&#xff1a; 1.3缺省参数的分类 1.3.1 全缺省参数 1.3.2 半缺省参数 1.4缺省参数的应用场景 2. 函数重载 2.1函数重载的概念 2.2不支持函数重载的情况 3.引用 3.1引用的概念 3.2引用的特性 3.3引用做参数 3…

C++内存管理(new和delete)

目录 1. new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new与operator delete函数 4 .new和delete的实现原理 1 .内置类型 2 .自定义类型 new的原理 delete的原理 new T[N]的原理 delete[]的原理 5. 定位new表达式(placement-new) 6. malloc/f…

【JavaScript】原生js实现省市区联动效果

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;用原生js实现省市区联动 【前言】今日在复习省市县三级联动的时候&#xff0c;有点忘了原生的js应该怎么样处理省市县的联动&#xff0c;特此写下来再次复习下 目录⭐实现思路⭐思路转…

Node【六】内置模块 【url模块与queryString】

文章目录&#x1f31f;前言&#x1f31f;url 模块&#x1f31f; URL各部分说明&#x1f31f; 将URL字符串转换为对象&#x1f31f; 将对象格式化为URL字符串&#xff1a;url.format(urlObj)&#x1f31f; URL路径处理&#xff1a;url.resolve(from, to)&#x1f31f; queryStri…

Dapr和Rainbond集成,实现云原生BaaS和模块化微服务开发

背景 Dapr 是一个开源的分布式应用运行时&#xff0c;帮助开发者构建松耦合的分布式应用程序&#xff0c;具有良好的可扩展性和可维护性。Rainbond 是一款企业级的云原生应用管理平台&#xff0c;提供了丰富的功能和工具&#xff0c;方便开发者管理和部署应用。Rainbond 和 Da…

如何通过 kubernetes ingress 或者 istio ingressgateway 来暴露 TCP 的服务

点击上方“程序猿技术大咖”&#xff0c;关注并选择“设为星标”回复“加群”获取入群讨论资格&#xff01;在 kubernetes 或 istio 应用中&#xff0c;一般都是通过 kubernetes ingress 或者 istio ingressgateway 来暴露 HTTP/HTTPS 的服务。但是在实际应用中&#xff0c;还是…

纷享销客张睿:快消数字化新时代,数“智”引领新增长

4月6日&#xff0c;在2023年&#xff08;第八届&#xff09;中国快消品创新大会主论坛上&#xff0c;纷享销客经营副总裁兼快消行业部总经理张睿作为嘉宾出席&#xff0c;并以《快消数字化新时代&#xff0c;数“智”引领新增长》为题发表了演讲。他有20余年的市场营销、销售及…

【蓝桥杯省赛真题37】Scratch冰上滑行 少儿编程scratch编程蓝桥杯省赛比赛真题讲解

目录 scratch冰上滑行 一、题目要求 编程实现 二、案例分析 1、角色分析

JUC源码系列-ReentrantReadWriteLock

继承关系 ReadLock和WriteLock是ReentrantReadWriteLock的两个内部类&#xff0c;Lock的上锁和释放锁都是通过AQS来实现的。 AQS定义了独占模式的acquire()和release()方法&#xff0c;共享模式的acquireShared()和releaseShared()方法。 还定义了抽象方法tryAcquire()、tryA…

男生|女生漫画头像怎么制作,分享3种免费制作方法,不用求人

大家发现没有&#xff0c;最近特别流行卡通漫画头像&#xff01;一些小伙伴们通过处理自己的照片&#xff0c;把照片制作成漫画头像&#xff0c;让照片看起来更有趣。那么&#xff0c;男生、女生漫画头像怎么制作呢&#xff1f;需要用到哪些工具?今天给大家分享3种免费制作漫画…

数据结构之线性表3

我们的目标&#xff1a; 1、了解线性结构的特点 掌握顺序表的定义、查找、插入和删除。 2、掌握链表的定义、创建、查找、插入和删除。 3、能够从时间和空间复杂度的角度比较两种存储结构的不同特点及其适用场合。&#xff08;持续更新&#xff09; 前言 本章节内容主要介绍…