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

news/2024/11/30 9:55:13/

这是时常被问到的问题,尤其是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 webdriverclass Test1(unittest.TestCase):@classmethoddef 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)@classmethoddef 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 webdriverdef 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. 正如上一条的原因,你不能控制用例的执行顺序。

http://www.ppmy.cn/news/423165.html

相关文章

快速解决Github无法访问的问题

Github访问慢,是困扰很多人的问题,今天就出一个解决方案,按照下面思路,可以实现快速访问Github,来查看我们需要的资源。 目录 一、获取DNS 二、修改hosts文件内容 2.1 修改hosts权限 2.2 修改hosts内容 三、轻…

Sui主网升级至V1.3.0版本

Sui主网现已升级至V1.3.0版本,升级要点如下所示: 将协议版本更新至12 开始在Narwhal中使用BatchV2,新增VersionedMetadata允许更精细的追踪Narwhal批处理延迟。有关详细信息,请参阅#12178和#12290。 将协议版本更新至13 弃用0…

sqlserver------数据库的存储过程(练习)

对于数据库的存储过程之前的专题有讲过 这里具体讲述存储过程的编写方法: 例题:有heat表和eatables两张表,分别为: eatables heat:protein(蛋白质),fat(脂肪&#xff…

2017艾普兰机智云全家福

AWE艾普兰奖的知名度从家电领域已经扩展到消费电子领域以及周边领界,成为各界公认的具有跨界影响力的实力评选。每年也都成为各品牌企业的必争之荣誉。堪称中国家电与消费电子行业奥斯卡!家电与消费电子领域的最高荣尚! 机智云致力于在移动互…

智能家居物联网化将成为AWE大会最大看点

AWE大会已经在今日9点半开幕,AWE在今年将扩张至8个展馆,其整体展示规模达到11万平米,这是以往都无法匹敌的。海尔、美的、格力、海信、创维、TCL、康佳、格兰仕、澳柯玛、新飞、美菱、奥马、方太、老板、万和、万家乐、华帝、帅康、樱花、格美…

【观察】 通盘无妙手,看SmartX如何构建增长根基

申耀的科技观察 读懂科技,赢取未来! 超融合自诞生以来,几乎很快就赢得了市场各方的认可,并从一个相对较小范围的应用领域,逐渐成长为目前企业构建软件定义数据中心,乃至未来实现多云管理架构中一个重要的基…

IoT方案|机智云智慧家电互联互通解决方案

[ 行业背景 ] 过去10年,在移动互联网、云计算、物联网技术快速发展的推动下,产品智能化逐渐成为家电和消费电子类产品标配,在丰富产品功能性外,有效提升了用户使用的舒适度和便利,并随着场景化需求的增加,形…

获3500万美元A轮融资,滴普科技用数字智能加速企业升级

2019年9月24日,滴普科技DEEPEXI 2.0 新品发布暨A轮融资战略发布会在北京隆重召开,发布会以“聚合数字、链接智慧”为主题,由甲子光年创始人张一甲担任主持人,与来自晨兴资本、高瓴资本、IDG资本、BAI贝塔斯曼亚洲投资基金、初心资…