PyQt 和 unittest - 如何处理信号和槽
我正在开发的一些小型应用程序使用我编写的模块来通过 REST API 检查某些 Web 服务。我一直在尝试向其中添加单元测试,这样我就不会破坏东西,并且我偶然发现了一个问题。
我使用大量信号槽连接来异步执行操作。例如,典型的测试是(伪Python),以 postDataDownloaded 作为信号:
def testConnection(self):
"Test connection and posts retrieved"
def length_test():
self.assertEqual(len(self.client.post_data), 5)
self.client.postDataReady.connect(length_test)
self.client.get_post_list(limit=5)
现在,unittest 将在运行时报告此测试“正常”,无论结果如何(因为正在调用另一个槽),即使断言失败(我将得到一个未处理的断言错误)。故意使测试失败的示例:
Test connection and posts retrieved ... ok
[... more tests...]
OK
Traceback (most recent call last):
[...]
AssertionError: 4 != 5
测试内部的插槽只是一个实验:如果它在外部(实例方法),我会得到相同的结果。
我还必须补充一点,我调用的各种方法都会发出 HTTP 请求,这意味着它们需要一些时间(我需要模拟请求 - 同时我使用 SimpleHTTPServer 来伪造连接并向它们提供连接)正确的数据)。
有办法解决这个问题吗?
some small application I'm developing uses a module I have written to check certain web services via a REST API. I've been trying to add unit tests to it so I don't break stuff, and I stumbled upon a problem.
I use a lot of signal-slot connections to perform operations asynchronously. For example a typical test would be (pseudo-Python), with postDataDownloaded as a signal:
def testConnection(self):
"Test connection and posts retrieved"
def length_test():
self.assertEqual(len(self.client.post_data), 5)
self.client.postDataReady.connect(length_test)
self.client.get_post_list(limit=5)
Now, unittest will report this test to be "ok" when running, regardless of the result (as another slot is being called), even if asserts fail (I will get an unhandled AssertionError). Example when deliberatiely making the test fail:
Test connection and posts retrieved ... ok
[... more tests...]
OK
Traceback (most recent call last):
[...]
AssertionError: 4 != 5
The slot inside the test is merely an experiment: I get the same results if it's outside (instance method).
I also have to add that the various methods I'm calling all make HTTP requests, which means they take a bit of time (I need to mock the request - in the mean time I'm using SimpleHTTPServer to fake the connections and give them proper data).
Is there a way around this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在调用回调之前,您需要避免退出测试方法。我相信调用将在单独的线程中进行,因此 threading.Event 似乎合适:
You need to avoid exiting the test method until the callback has been called. I believe the call is going to happen in a separate thread, so a threading.Event seems appropriate:
您还可以使用 QTest.qWait。当按下开始按钮时,我的主窗口启动一个异步进程,并在进程完成时更新标签。在“test_async_label_update”方法中,我模拟按下开始按钮,然后调用 QTest.aWait 以允许事件循环处理信号和槽。一旦 aWait 完成,标签就会被检查。对于更复杂的情况,您可以使用 qWaitFor。
https://doc.qt.io/qt-6/qtest.html# q等待:
You can also use QTest.qWait. My MainWindow starts an async process when the start button is pressed and updates the label when the process is finished. In the 'test_async_label_update' method, I simulate the start button being pressed and then I call QTest.aWait to allow the event loop to process the signal and slots. Once the aWait finishes the label is checked. You can use qWaitFor, for more complicated senarios.
https://doc.qt.io/qt-6/qtest.html#qWait :