Python多线程单元测试

时间:2011-06-26 16:45:09

标签: python multithreading unit-testing testing thread-safety

我使用多线程设计(别无选择),但我的大部分代码都驻留在一个线程中,其中的所有事件都通过queue进行管理。以这种方式,我的大部分代码都表现得好像是单线程的,我不必担心锁,信号量等等。

唉,我已经到了需要对代码进行单元测试的地方(首先请不要抨击TDDing),而且我不知所措 - 你如何在另一个线程中测试一些东西?

例如,假设我有以下课程:

class MyClass():
    def __init__(self):
        self.a=0
        # register event to self.on_event

    def on_some_event(self, b):
        self.a += b

    def get(self):
        return self.a

我想测试一下:

import unittest
from queued_thread import ThreadedQueueHandler

class TestMyClass(unittest.TestCase):
    def setUp(self):
        # create the queued thread and assign the queue to self.queue

    def test_MyClass(self):
        mc = MyClass()
        self.queue.put({'event_name':'some_event', 'val':1})
        self.queue.put({'event_name':'some_event', 'val':2})
        self.queue.put({'event_name':'some_event', 'val':3})
        self.assertEqual(mc.get(),6)

if __name__ == '__main__':
    unittest.main()

MyClass.get()适用于排队线程内的任何内容,但是它会在主线程中通过测试异步调用,因此结果可能不正确!

2 个答案:

答案 0 :(得分:9)

如果你的设计假设一切都必须通过队列,那就不要打它 - 让一切都通过它!

on_call事件添加到排队的事件处理程序,并向其注册以下函数:

def on_call(self, callback):
    callback()

然后将您的测试修改为:

def test_MyClass(self):
    def threaded_test():
        self.assertEqual(mc.get(),6)

    mc = MyClass()
    self.queue.put(1)
    self.queue.put(2)
    self.queue.put(3)
    self.queue.put({'event_name':'call','val':threaded_test})

答案 1 :(得分:2)

您可以在stdlib测试中查看test_threading.py,它会执行类似于您尝试执行的操作。基本思想是使用互斥锁和信号量保护线程执行,以便在断言测试条件之前完成执行。