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

前言

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

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

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

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

  • TestRunner 可以执行单条测试用例以及测试套件中所有的用例
  • TestSuite 是直接执行套件中所有的用例
  • Testcase 中的 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:123456789@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:123456789@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)

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

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

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程执行测试框架用例可以提高执行效率,特别是在大规模测试中。以下是一个简单的示例代码,演示如何使用多线程执行测试框架的用例: ```python import threading import unittest # 定义测试用例类 class MyTestCase(unittest.TestCase): def test_case1(self): # 测试用例1的代码逻辑 pass def test_case2(self): # 测试用例2的代码逻辑 pass # 添加更多的测试用例方法... if __name__ == '__main__': # 创建测试套件并添加测试用例 suite = unittest.TestSuite() suite.addTest(MyTestCase('test_case1')) suite.addTest(MyTestCase('test_case2')) # 添加更多的测试用例... # 定义执行用例的函数 def run_test_case(test_case): # 执行用例 unittest.TextTestRunner().run(test_case) # 创建线程列表 threads = [] # 创建线程并启动执行 for test in suite: thread = threading.Thread(target=run_test_case, args=(test,)) thread.start() threads.append(thread) # 等待所有线程执行完毕 for thread in threads: thread.join() ``` 在上面的示例代码中,我们使用了 Python 自带的 unittest 框架来定义测试用例。首先,我们创建了一个 MyTestCase 类,其中包含了多个测试用例方法,比如 test_case1 和 test_case2。然后,我们创建了一个测试套件(suite)并添加了需要执行测试用例。 接下来,我们定义了一个 run_test_case 函数,用于执行测试用例。然后,我们创建了一个线程列表,并使用线程创建和启动多个线程来执行测试用例。最后,我们使用 join() 方法等待所有线程执行完毕。 这样,我们就可以通过多线程的方式来执行测试框架的用例,提高执行效率。当然,在实际应用中,你可能还需要处理测试结果的收集和报告等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值