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



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

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

    unittest

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

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

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

    https://github.com/SeldomQA/HTMLTestRnne
    https://github.com/dflupu/tomrrow

    • 测试用例
      测试用例如下,你可以复制多份测试。
    # 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()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 运行文件
      核心在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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    总结:

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

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

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

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

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

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

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

    pytest

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

    • 测试用例
      测试用例如下,你可以复制多份测试。
    # 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()
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 运行文件
      核心就是安装 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,
            ])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    总结:

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

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

    最后

    如果你想学习自动化测试,那么下面这套视频应该会帮到你很多

    如何逼自己1个月学完自动化测试,学完即就业,小白也能信手拈来,拿走不谢,允许白嫖....

    最后我这里给你们分享一下我所积累和整理的一些文档和学习资料,有需要直接领取就可以了!


    以上内容,对于软件测试的朋友来说应该是最全面最完整的备战仓库了,为了更好地整理每个模块,我也参考了很多网上的优质博文和项目,力求不漏掉每一个知识点,很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你。

    ​​

    ​​​​

  • 相关阅读:
    Go 与 Java 字符编码选择:UTF-8 与 UTF-16 的较量
    springMVC的学习【上】
    css实现倾斜按钮(radial-gradient)
    玩家们最关心的绝地求生游戏作战秘籍,分享大神干货,助您轻松提升战斗力!
    【python】TypeError: unhashable type: ‘list‘ 解决方法——简单示例
    一文带你实现从PDF到Word文件的相互转换
    el-table行添加阴影悬浮效果
    虚拟化不是区块链的发展道路,也不是真正意义上的区块链的呈现形式
    [附源码]计算机毕业设计基于springBoot仓库管理系统
    数组中和为0的三个数
  • 原文地址:https://blog.csdn.net/qq_56271699/article/details/134268769