Python多线程单元测试

发布于 2024-11-17 06:24:26 字数 1126 浏览 3 评论 0原文

我使用多线程设计(别无选择),但我的大部分代码驻留在单个线程中,其中的所有事件都通过 队列。以这种方式,我的大部分代码的行为就好像它是单线程的,而且我不必担心锁、信号量等等。

唉,我已经到了需要对我的代码进行单元测试的地步(请不要批评我一开始就没有 TDD),而我不知所措 - 如何在另一个线程中测试某些东西?

例如,假设我有以下类:

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() 对于排队线程内的任何内容都可以正常工作,但测试将在主线程中异步调用它,因此结果可能不正确!

I use a multi-threaded design (had no choice), but most of my code resides in a single thread where all events in it are managed via a queue. In this fashion most of my code behaves as if it is single threaded, and I don't have to worry about locks, semaphores and what not.

Alas I've come to the point where I need to unittest my code (please don't lash for not TDDing in the first place), and I'm at a loss - how do you test something in another thread?

For instance, say I have the following class:

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

and I want to test:

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() works fine for anything inside the queued thread, but it will be called asynchronously in the main thread by the test, thus the result may not be correct!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

何以畏孤独 2024-11-24 06:24:26

如果您的设计假设所有内容都必须经过队列,那么不要与之对抗 - 让所有内容都经过队列!

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})

If your design assumes everything must go through the queue, then don't fight it - make everything go through it!

Add an on_call event to your queued event handler, and register to it the following function:

def on_call(self, callback):
    callback()

then modify your test to:

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})
左耳近心 2024-11-24 06:24:26

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

You can have a look at test_threading.py in the stdlib tests which does something similar to what you are trying to do. The basic idea is to protect a thread execution with mutex and semaphore so that the execution is complete before the test condition is asserted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文