我正在尝试为我的应用程序创建使用多个进程的单元测试,但在尝试同时运行所有测试时遇到了奇怪的问题。基本上,当单独运行测试时,它们会毫无问题地通过,但是当顺序运行时,例如在文件中运行所有测试时,某些测试将失败。
我所看到的是,正在创建许多python进程,但是当测试报告为已通过时,它们没有关闭。例如,如果运行2个测试,每个测试生成5个过程,则系统监视器中会显示10个python进程。
我尝试过使用终止和加入,但都没有工作。有没有办法强制测试正确关闭它在运行下一个测试之前生成的所有进程?
我在Ubuntu 16.04中运行Python 2.7。
修改 它是一个相当大的代码库,所以这里是一个简化的例子。
def bot_leave(self, ctx):
state = self.get_voice_state(ctx.message.server)
coro = state.voice.disconnect()
try:
asyncio.run_coroutine_threadsafe(coro, state.voice.loop)
except:
# an error happened sending the message
pass
答案 0 :(得分:0)
经过一段时间的努力(实际上是2天),我发现解决方案在技术上没有错,但是删除了您可以拥有的所有并行代码(仅在测试中,仅在测试中……)
我使用这个软件包mock
来模拟函数(自Pytohn 3.3 xD以来,我现在意识到它已经是unittest模块的一部分),您可以假设某些函数的执行效果很好, 固定某个返回值,或更改函数本身。
所以我做了最后一个选择:更改函数本身。
在我的情况下,我使用了一个进程列表(因为Pool
在我的情况下不起作用)和Manager's list
在进程之间共享数据。
我的原始代码如下:
import multiprocessing as mp
manager = mp.Manager()
list_data = manager.list()
list_return = manager.list()
def parallel_function(list_data, list_return)
while len(list_data) > 0:
# Do things and make sure to "pop" the data in list_data
list_return.append(return_data)
return None
# Create as many processes as images or cpus, the lesser number
processes = [mp.Process(target=parallel_function,
args=(list_data, list_return))
for num_p in range(mp.cpu_count())]
for p in processes:
p.start()
for p in processes:
p.join(10)
因此,在我的测试中,我从多处理模块中模拟了Process .__ init__函数来执行我的parallel_function,而是创建一个新进程。
在测试文件中,在进行任何测试之前,应定义相同的函数以尝试并行化:
def fake_process(self, list_data, list_return):
while len(list_data) > 0:
# Do things and make sure to "pop" the data in list_data
list_return.append(return_data)
return None
在定义将要执行此部分代码的任何方法之前,您必须定义其装饰器以覆盖Process .__ init__函数。
@patch('multiprocessing.Process.__init__', new=fake_process)
@patch('multiprocessing.Process.start', new=lambda x: None)
@patch('multiprocessing.Process.join', new=lambda x, y: None)
def test_from_the_hell(self):
# Do things
如果您使用Manager数据结构,则无需使用锁或任何其他方法来控制对数据的访问,因为这些结构是线程安全的。
我希望这对尝试测试多处理代码的其他迷失者有所帮助。