分析:如何多线程运行测试用例

这是时常被问到的问题,尤其是UI自动化的运行,过程非常耗时,所以,所以多线程不失为一种首先想到的解决方案。

多线程是针对的测试用例,所以和selenium没有直接关系,我们要关心的是单元测试框架。

unittest

首先,应该说明的是unittest本身是不支持多线程的。当然,如果你学过Python的threading模块,也未必不行。不过我在stackoverflow 找了半天,大多是介绍unittest 测试多线程模块,并非是unittest本身如何多线程运行用例。

“我如何学习葵花宝典” 和 “我如何验证 张三 学会了葵花宝典”是两回事,而我显然要解决的问题是前者。

又重新百度,结果就找了答案。核心借助 tomorrow3 的测试库,再配合HTMLTestRunner 生成测试报告。

GitHub - SeldomQA/XTestRunner: Modern style test report based on unittest framework.
GitHub - dflupu/tomorrow3: An implementation of the tomorrow package for python >= 3.0

  • 测试用例

测试用例如下,你可以复制多份测试。

# test_a.py
import time
import unittest
from selenium import webdriver


class Test1(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome()

    def test_01(self):
        self.driver.get("https://www.bing.com/?mkt=zh-CN")
        elem = self.driver.find_element_by_id("sb_form_q")
        elem.send_keys("多线程")
        elem.submit()
        time.sleep(2)
        self.assertIn("多线程", self.driver.title)

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == "__main__":
    unittest.main()
  • 运行文件

核心在tomorrow3提供的threads装饰器,用于装饰测试运行方法。

import unittest
import os
from TestRunner import HTMLTestRunner
from tomorrow3 import threads

# 定义目录
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
TEST_DIR = os.path.join(BASE_DIR, "test_dir")
REPORT_DIR = os.path.join(BASE_DIR, "test_report")


def test_suits():
    """
    加载所有的测试用例
    """
    discover = unittest.defaultTestLoader.discover(
        TEST_DIR,
        pattern="test_*.py"
    )
    return discover


@threads(2)  # !!!核心!!!! 设置线程数
def run_case(all_case, nth=0):
    """
    执行所有的用例, 并把结果写入测试报告
    """
    report_abspath = os.path.join(REPORT_DIR, f"result{nth}.html")
    with open(report_abspath, "wb+") as file:
        runner = HTMLTestRunner(stream=file, title='多线程测试报告')
        # 调用test_suits函数返回值
        runner.run(all_case)


if __name__ == "__main__":
    cases = test_suits()
    # 循环启动线程
    for i, j in zip(cases, range(len(list(cases)))):
        run_case(i, nth=j)  # 执行用例,生成报告

总结:

确实可以(根据设置的线程数)同时开启两个浏览器运行,同时带来了两个问题。

  1. 程序会根据线程数,生成多份测试报告,每个测试报告统计当前线程所运行的测试结果。
  2. 如果去掉nth参数,设置为一个报告,那么第二个线程运行的结果不能正确展示的一张报告上。
  3. 至少每个线程中的用例要保证有浏览器的启动/关闭。

第3点,你可能不理解,我举个例子,小时候见过妈妈/奶奶缝衣服。假设一件衣服拿一根针来缝制,缝衣服最麻烦就是穿针引线,针眼很小,每次都要费半天功夫,小孩子眼神好,我时常被叫去穿针引线。那为了节约时间怎么办,我当然是把线弄的长长的,最好是一根针线可以缝制多件衣服。

在Selenium 中,定义的浏览器驱动driver,每一条用例都定义一次驱动,伴随而来的就每个用例都开启/关闭一次浏览器,这当然是非常耗时的,为了缩短这个时间,我们最好是启动一次浏览器把所有用例都跑完才关闭。

那么问题来了,当我们使用多线程之后,相当于多个人同时缝制衣服,共用一根针线肯定不行啊。至少需要每人一根针线吧!而且缝制衣服的人是变化的,为了赶时间就多两个人(多开两个线程),用例比较少就少几个人(少启两个线程),为了适应这种变化,那么最好一件衣配置一根针线,每件衣服是最小单位,一个人必须要独立的把一件衣服缝好。

为了使用多线程,我们就必须每条用例开启/关闭一次浏览器,这其实是另一种时间的浪费,为了弥补这里的浪费,你必须把线程开得足够多才行。

最后,你必须再配置一位统计员,去统计每个人缝制衣服的数量,合计到一个报告中。

pytest

多线程运行用例在 pytest 中就相对容易太多了,pytest-xdist 插件就可以完成这件事情。

GitHub - pytest-dev/pytest-xdist: pytest plugin for distributed testing and loop-on-failures testing modes.

  • 测试用例

测试用例如下,你可以复制多份测试。

# test_a.py
import time
from selenium import webdriver


def test_01():
    driver = webdriver.Chrome()
    driver.get("http://www.baidu.com")
    elem = driver.find_element_by_id("kw")
    elem.send_keys("unittest")
    elem.submit()
    time.sleep(2)
    assert driver.title == "unittest_百度搜索"
    driver.quit()


def test_02():
    driver = webdriver.Chrome()
    driver.get("http://www.baidu.com")
    elem = driver.find_element_by_id("kw")
    elem.send_keys("python")
    elem.submit()
    time.sleep(2)
    assert driver.title == "python_百度搜索"
    driver.quit()

  • 运行文件

核心就是安装 pytest-xdist 插件,通过-n参数设置线程数即可。

import os
import pytest

# 定义目录
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
TEST_DIR = os.path.join(BASE_DIR, "test_dir")
REPORT_DIR = os.path.join(BASE_DIR, "test_report")


if __name__ == '__main__':
    report_file = os.path.join(REPORT_DIR, "result.html")
    pytest.main([
        "-n", "2",  # !!核心!!!设置2个线程
        "-v", "-s", TEST_DIR,
        "--html=" + report_file,
        ])

总结:

相对于unittest,在pytest实现多线程非常简单,最终线线程的测试结果也可以很好在一个测试报告中展示。

  1. 存在的问题,正如我上面讨论的,你必须为每个用例设置开启/关闭。除了额外消耗启动时间外,如果想统一配置用例通过哪个浏览器执行也会比较麻烦。
  2. 你的每一条用例应该保持绝对独立,不能出现这条用例依赖上条用例的执行结果。因为,这两条用例可能会分配由不同的线程执行。
  3. 正如上一条的原因,你不能控制用例的执行顺序。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++干货基地】六大默认成员函数: This指针 | 构造函数 | 析构函数

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 哈喽各位铁汁们好啊,我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的…

YOLO目标检测——森林火灾烟雾检测数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用:森林火灾监控与预警标注说明:使用lableimg标注软件标注,标注框质量高,含voc(xml)、coco(json)和yolo(txt)三种格式标签,分别存放在不同文件夹下,可以直接用于YOLO系列的目标检测。其他&#x…

3D-Genome | Hi-C互作矩阵归一化指南

Hi-C 是一种基于测序的方法,用于分析全基因组染色质互作。它已广泛应用于研究各种生物学问题,如基因调控、染色质结构、基因组组装等。Hi-C 实验涉及一系列生物化学反应,可能会在输出中引入噪声。随后的数据分析也会产生影响最终输出噪声&…

PandasAI—让AI做数据分析

安装 pip install pandasai !pip install --upgrade pandas pandasai 导入依赖项 import pandas as pdfrom pandasai import PandasAIfrom pandasai.llm.openai import OpenAI使用pandas创建一个数据框 df pd.DataFrame({"country": ["United States",…

VisionPro 判断圆是不是无限接近圆或存在缺陷

项目上可能需要判断圆是否是无限接近圆或者判断圆边缘是否存在缺陷等。 第一种方法:找圆工具和点到点的距离计算圆边缘上的点到圆心距离的最大值和最小值的差值。 #region namespace imports using System; using System.Collections; using System.Drawing; usin…

Batch Nomalization 迁移学习

Batch Nomalization 1.Batch Nomalization原理 图像预处理过程中通常会对图像进行标准化处理,这样能够加速网络的收敛。就是按照channel去求均值和方差,然后原数据减均值除标准差,使我们的feature map满足均值为0,方差为1的分布…

AI助力剧本创作:如何5分钟内构思出热门短剧大纲

人工智能重塑短剧行业:从剧本创作到市场推广 在当今短剧行业的飞速发展中,剧本创作的质量及其更新的速度已然成为短剧能否转化为热门作品的关键性因素。然而,随着短剧创作成本的日益攀升,一个卓越的剧本无论在创作时间上还是在构思…

基于SpringBoot+MYSQL的大学生租房平台

目录 1、 前言介绍 2、主要技术 3、系统流程 3.1、操作流程 3.2、登录流程 3.3、删除信息流程 3.4、添加信息流程 4、功能需求 5、系统设计 5.1、功能结构设计 5.1、数据库概念设计 6、运行截图(部分) 6.1、管理员功能实现 6.1.1、房东管理 6.1.2、信息审批管理 …

物联网在智慧城市建设中的关键作用:连接、感知、智能响应

一、引言 随着信息技术的飞速发展,物联网(IoT)技术已经渗透到我们生活的方方面面,特别是在智慧城市建设中发挥着至关重要的作用。智慧城市是指通过运用先进的信息和通信技术,实现城市基础设施、公共服务、交通管理、环…

断开服务器仍后台运行程序

1.可以使用nohup命令: nohup python xx.py 2>1& 不要忘记 2>1& 之后会返回一个进程号(记不住也没关系,可以看3),此时程序就在后台运行了,与服务器断开连接也能正常运行 2.在终端实时打印…

ai绘画是怎么画的?ai绘画算法揭秘 - AI绘画每日一帖

“ AI 绘画通过CLIP技术建立「文字潜在空间」到「图片潜在空间」的对应关系,并通过 Diffusion 技术从一张噪点图得到一张有信息的高清图。 在 一文讲透ai作画原理技术 一文中,我们介绍了ai绘画的基本原理,这背后更详细的ai绘画算法是什么&…

Visual Studio如何进行类文件的管理(类文件的分离)

大家好: 衷心希望各位点赞。 您的问题请留在评论区,我会及时回答。 一、问题背景 实际开发中,类的声明放在头文件中,给程序员看类的成员和方法。比如:Dog.h(类的声明文件) 类的成员函数的具体…

stable diffusion 原理是什么?

“ 这篇文章主要介绍了Stable Diffusion,这是一种用于AI绘画的算法,它是由CompVis和Runway团队在2021年12月提出的“潜在扩散模型”(LDM/Latent Diffusion Model)的变体,基于2015年提出的扩散模型(DM/Diffu…

场景问题: VisualVM工具Profiler JDBC不是真实执行的SQL

1. 问题 诡异的问题表象: 前端反馈分页接口的Total字段一直为0 使用Visualvm中的 Profiler 注入到应用后,查看JDBC监控得到了分页接口执行的SQL,复制出来执行是55. 此时还没有注意到 IN 的范围中有一个特别的值 NULL 🤨 2. 排查…

2834. 找出美丽数组的最小和

文章目录 [2834. 找出美丽数组的最小和](https://leetcode.cn/problems/find-the-minimum-possible-sum-of-a-beautiful-array/)思路:代码: 2834. 找出美丽数组的最小和 思路: 1.n 是数组的长度。k 是题目中的target。m 的值是通过取k / 2和…

提取pdf图档中的物料编码

一、摘要 图1 图档示例 本篇代码目的是从指定文件夹下的PDF文件中提取物料编码等相关信息,并将这些信息存储在列表中输出。这段代码主要实现了以下功能: 定义一个file_name函数,用于获取指定文件夹下所有文件的完整路径。通过遍历文件夹和子文…

UOS 与 Ubuntu 命令行打开安装包界面,双击打开界面调用安装包界面展示

UOS 使用deepin-deb-installer安装程序 deepin-deb-installer xxxxxxx.deb & Ubuntu snap-store --local-filename /home/seven/wps-office_1xxxxxxx.deb &

Android14音频进阶:AudioTrack如何拿到AudioFlinger创建的匿名共享内存(六十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

聚观早报 | 腾讯QQ测试AI对话功能;哪吒L官宣4月交付

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月8日消息 腾讯QQ测试AI对话功能 哪吒L官宣4月交付 中国对瑞士等6国试行免签 Redmi K70至尊版细节曝光 Meta正…

如何阅读“计算机界三大神书”之一 ——《计算机程序的构造和解释》SICP

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…