多线程执行 unittest 测试用例的实现方案

本贴最后更新于 1454 天前,其中的信息可能已经事过境迁

多线程执行unittest测试用例的实现方案

前言

使用python做过自动化测试的小伙伴,想必都知道unittest和pytest这两个单元测试框架,其中unittest是python的官方库,功能相对于pytest来要逊色不少,但是uniitest使用上手简单,也受到的很多的小伙伴喜爱。一直以来都有小伙伴在问我,pytest可以通过相关的插件来实现多线程执行测试用例,为什么unittest没有呢?unittest如何去实现多线程运行呢?那么今天就专门来给大家聊聊如何使用多线程去执行unittest!

一、unittest测试用例的运行机制

在讲使用多线程去执行uniitest的测试用例之前,我们首先来分析一下,unittest中用例可以通过哪几种方式来执行。这个时候就得去看看unittest的源码了,

image.png

虽然unittest的底层代码是基于C语言实现的,源码中看不到详细的代码,但是我们可以发现TestCase、TestSuite、TestRnner三个类中都有run方法,而且run方法的作用的都是执行测试用例。

其实不管是TestRunner还是TestSuite的run方法执行用例,最终还是调用了用例本身的run方法去执行的。用例执行的方法我们搞清楚了,那么接下来我们就可以采取相关的策略使用多线程来执行了。

二、多线程执行用例的实现思路

三、思路一:具体实现:

1、初步尝试
"""文件1:testcase.py"""
import unittest

class TestRegister(unittest.TestCase):
    """此处用例代码以省略"""

class TestLogin(unittest.TestCase):
     """此处用例代码以省略"""

"""文件2:run_case.py"""
import unittest,threading
from case_test.test_case import TestLogin, TestRegister

# 创建2个套件,每个套件使用一个线程去执行
suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)
suite2 = unittest.defaultTestLoader.loadTestsFromTestCase(TestLogin)

def work1():
    """执行套件1"""
    unittest.TextTestRunner().run(suite1)

def work2:
    """执行套件2"""
    unittest.TextTestRunner().run(suite1)

t1 = threading.Thread(target=work1)
t2 = threading.Thread(target=work2)
t1.start()
t2.start()
t1.join()
t2.join()

运行上面的run_case.py就会发现两个线程可以同时执行测试用例,但是存在一个问题,用例执行完之后,每个线程得到的结果是独立的,无法整合到一起!于是进行了以下优化。

2、再次尝试:测试结果整合

前面我们在执行测试套件的时候,是通过TestRunner去执行的,TestRunner的run方法的参数只能传入测试用例或者测试套件,而unittest中TestSuite,和TestCase的run方法在调用的时候,可以接收一个叫做TestResult的对象。而用例执行的结果就是保存在这个TestResult对象中。我们如果要整个测试结果可以自己先创建一个TestResult对象,然后执行套件的时候传进入,最后两个套件执行得到的测试结果都会保存在这一个TestResult对象中。代码如下

# 创建一个结果保存对象
res = unittest.TestResult()
# 运行测试套件返回测试结果
t1 = threading.Thread(target=suite1.run,kwargs={"result":res})
t2 = threading.Thread(target=suite2.run, kwargs={"result": res})
t1.start()
t2.start()
t1.join()
t2.join()
print(res)

运行上述代码,我们成功的使用多线程运行了测试用例,并且将测试用例执行的结果整合到了一起。

3、封装一个基于线程池来执行的函数

下面的代码封装用到了线程池的相关知识点,大家可以自行扩展

"""
============================
Author:柠檬班-木森
Time:2020/5/26   10:00
E-mail:3247119728@qq.com
Company:湖南零檬信息技术有限公司
============================
"""

import unittest
from concurrent.futures.thread import ThreadPoolExecutor
from test_case import TestLogin, TestRegister


def run_test(suites, thread_count=1):
    """
    多线程执行用例的方法
    :param suite: list -->包含多个套件的列表[TestSuite,TestSuite]
    :param thread_count: int  ---->执行的线程数量,默认为1
    :return: TestResult--->测试结果
    """
    res = unittest.TestResult()
    # 创建一个线程池,执行测试用例
    with ThreadPoolExecutor(max_workers=thread_count) as ts:
        for suite in suites:
            # 将套件的执行提交到线程池中
            ts.submit(suite .run, result=res)
    return res


if __name__ == '__main__':
    # 创建两个套件
    suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)
    suite2 = unittest.defaultTestLoader.loadTestsFromTestCase(TestLogin)
    # 将套件放到列表中
    suite = [suite1, suite2]
    # 给根据套件的数量,每个套件创建一个线程去执行
    res = run_test(suite=suite, thread_count=len(suite))
    # 打印测试结果
    print(res)

四、思路二、代码封装

思路一实现了之后,思路二再来实现就会非常简单了,封装的代码如下:

"""
============================
Author:柠檬班-木森
Time:2020/5/26   10:00
E-mail:3247119728@qq.com
Company:湖南零檬信息技术有限公司
============================
"""
import unittest
from concurrent.futures.thread import ThreadPoolExecutor
from case_test.test_case import TestLogin, TestRegister
def run_test(suite, thread_count=1):
    """
    多线程执行用例的方法
    :param suite: 测试套件
    :param thread_count: int  ---->执行的线程数量,默认为1
    :return: TestResult--->测试结果
    """
    res = unittest.TestResult()
    # 创建一个线程池,执行测试用例
    with ThreadPoolExecutor(max_workers=thread_count) as ts:
        for case in suite:
            # 将用例的执行任务提交到线程池中
            ts.submit(case.run, result=res)
    return res

if __name__ == '__main__':
    # 创建两个套件
    suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)
    # 给根据套件的数量,每个套件创建一个线程去执行
    res = run_test(suite=suite1, thread_count=3)
    # 打印测试结果
    print(res)

关于多线程执行unittest就给大家分享到这里!看到这里可能有些小伙伴会问,多线程执行如何生成测试报告呢?目前unittest生成测试报告使用的几个开源的库,比如BeautifulReport,HTMLTestRunner都不支持多线程。不过要想实现的话也不难,对这些模块运行用例的方法进行重写就可以实现。

关于多线程执行unittest就给大家分享到这里!看到这里可能有些小伙伴会问,多线程执行如何生成测试报告呢?

那么接下来就这大家介绍一下如何使用unittestreport多线程运行用例,并生产测试报告

五、unittestreport多线程执行用例

使用unittestreport来多线程执行用例非常简单,只需要在执行用例时加一个参数thread_count,指定执行的线程即可。案例如下:

from unittestreport import TestRunner
# 加载套件
suite = unittest.defaultTestLoader.discover(CASE_DIR)

# 执行用例
runner = TestRunner(suite,
                    filename=conf.get('report', "filename"),
                    report_dir=REPORT_DIR,
                    title='测试报告',
                    tester='木森',
                    desc="木森执行测试生产的报告",
                    templates=1
                    )
# 指定三个线程运行测试用例
runner.run(thread_count=3)

关于unittest多线程执行测试用例 就给大家分享到这里了!

3 操作
mslemonban 在 2020-11-24 14:42:18 更新了该帖
mslemonban 在 2020-09-22 11:32:48 更新了该帖
mslemonban 在 2020-08-06 17:33:16 更新了该帖
回帖
请输入回帖内容 ...