如何并行执行python子测试?

如何并行执行python子测试?,python,multiprocessing,python-unittest,pathos,Python,Multiprocessing,Python Unittest,Pathos,考虑下面的unittest.TestCase,它实现了同一测试的两个版本,唯一的区别是其中一个使用多处理并行执行子测试 from pathos.multiprocessing import ProcessingPool ... def test_equality_parallel(self): pool = ProcessingPool(processes=4)

考虑下面的
unittest.TestCase
,它实现了同一测试的两个版本,唯一的区别是其中一个使用
多处理并行执行
子测试

from pathos.multiprocessing import ProcessingPool
...
    def test_equality_parallel(self):                                           
        pool = ProcessingPool(processes=4)                                      
        pool.map(self._test_equals, [1, 2])
        pool.join()
将多处理导入为mp
从unittest导入TestCase
类TestBehavior(TestCase):
定义测试等于(自身,val):
对于[1,2]中的目标值:
使用self.subTest(target=target_val,source=val):
self.assertEqual(val,target_val)
def测试_相等_并行(自):
使用mp.Pool(进程=4)作为池:
map(self.\u test\u等于[1,2])
pool.join()
pool.close()
def测试_相等(自):
对于[1,2]中的val:
自我测试等于(val)
串行版本,
test\u equality
,按预期工作,并产生以下测试失败:

======================================================================
FAIL: test_equality (temp.TestBehaviour) (target=2, source=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "temp.py", line 11, in _test_equals
    self.assertEqual(val, target_val)
AssertionError: 1 != 2

======================================================================
FAIL: test_equality (temp.TestBehaviour) (target=1, source=2)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "temp.py", line 11, in _test_equals
    self.assertEqual(val, target_val)
AssertionError: 2 != 1
另一方面,
test\u equality\u parallel
会导致错误,因为无法对
TestCase
进行pickle处理:

Traceback (most recent call last):
  File "temp.py", line 15, in test_equality_parallel
    pool.map(self._test_equals, [1, 2])
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/pool.py", line 364, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/pool.py", line 768, in get
    raise self._value
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/pool.py", line 537, in _handle_tasks
    put(task)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
TypeError: cannot pickle '_io.TextIOWrapper' object
现在我知道我可以将
\u test_equals
拆分为类外的独立函数;但是,我希望保留
子测试的行为
,以便更好地记录(和后续调试)测试失败

如何并行运行测试,但保持此
子测试的功能

更新

我还尝试使用
pathos.multiprocessing.ProcessingPool
来规避
TestCase
序列化的问题;但是,在本例中,
pool.join()
引发
ValueError:池仍在运行

from pathos.multiprocessing import ProcessingPool
...
    def test_equality_parallel(self):                                           
        pool = ProcessingPool(processes=4)                                      
        pool.map(self._test_equals, [1, 2])
        pool.join()
更新2


这绝对是相关的。提出的第一个解决方案是为要从子进程调用的方法创建第二个类,这是不合适的,因为它不支持使用
子测试。第二,从
测试用例
中删除不可修改的
\u结果
对象似乎有问题,而且考虑到子进程正在运行
子测试
,看起来也不合适。

我是
pathos
(和
dill
多进程
)的作者。您仍然可以看到跨进程的
pathos
出现序列化错误。您可以尝试跨线程序列化。线程并行可能适用于此级别的函数

import multiprocess.dummy as mp
from unittest import TestCase


class TestBehaviour(TestCase):
    def _test_equals(self, val):
        for target_val in [1, 2]:
            with self.subTest(target=target_val, source=val):
                self.assertEqual(val, target_val)

    def test_equality_parallel(self):
        with mp.Pool(processes=4) as pool:
            pool.map(self._test_equals, [1, 2])
            pool.join()
            pool.close()

    def test_equality(self):
        for val in [1, 2]:
            self._test_equals(val)
这将产生:

======================================================================
FAIL: test_equality (test_equaltiy.TestBehaviour)
----------------------------------------------------------------------
...[snip]...
AssertionError: 1 != 2

======================================================================
FAIL: test_equality_parallel (test_equaltiy.TestBehaviour)
----------------------------------------------------------------------
...[snip]...
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 2 tests in 0.108s

FAILED (failures=2)

这告诉我,您可以使用来自
dill
(即
dill.settings
)的序列化变量来绕过序列化问题。请参阅:。

因为我的实际用例严重限制了CPU,所以我希望实现基于进程的线程。使用
multiprocess.Pool
完成了这项工作,对
TestCase
进行了无问题的酸洗。