Python 3.11。异步测试运行器

And*_*vko 6 python python-unittest python-3.11 python-3.12

决定将 Python 版本从3.10升级到3.11,之前我们已经使用了asynctest.TestCase和setUp方法tearDown并支持异步代码的测试。

我已经检查过unittest.IsolatedAsyncioTestCase,但它为每个测试使用不同的事件循环,这导致使用我们现在无法承受的不同会话。

我们使用async setUp /asyncSetUp来初始化依赖项并创建测试数据,因此需要此功能。

有类似物吗?或者您使用什么来使用 python 3.11 / 3.12 测试复杂系统?

asynctest.TestCase3.11+ 不支持ps

我想知道是否有使用 python 3.11/3.12 测试异步代码的专业知识。也许有人也面临着我的问题。

Von*_*onC 0

在Python 3.11中,asynctest.TestCase确实不支持,并且unittest.IsolatedAsyncioTestCase确实为每个测试创建一个新的事件循环。
当您的测试需要跨不同测试的一致事件循环时(例如使用共享会话或连接时),这可能会出现问题。

一种可能的替代方法是创建一个自定义测试用例类来扩展 unittest.TestCase并手动管理事件循环。这将允许您对所有测试使用相同的事件循环,类似于asynctest.TestCase工作方式。

import asyncio
import unittest


class AsyncTestCase(unittest.TestCase):
    loop = None

    @classmethod
    def setUpClass(cls):
        print("Setting up test case class")
        cls.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(cls.loop)

    @classmethod
    def tearDownClass(cls):
        print("Tearing down test case class")
        cls.loop.close()
        asyncio.set_event_loop(None)

    def run_async_test(self, coro):
        print(f"Running async test: {self._testMethodName}")
        return self.loop.run_until_complete(coro)
Run Code Online (Sandbox Code Playgroud)

该run_async_test(self, coro)方法用于运行异步测试。它以协程作为参数,使用循环类属性中存储的事件循环运行它直至完成,然后返回结果。

这确实在方法中创建了一个事件循环setUpClass,并对类中的所有测试使用相同的事件循环。这与unittest.IsolatedAsyncioTestCase类不同,类为每个测试创建一个新的事件循环。

这应该允许您将测试方法编写为异步 ( async def) 并让它们在unittest框架内正确执行。

例如,在测试中使用它是:

# tests/test_async_module.py
from tests.async_test_case import AsyncTestCase
from async_modules import async_add


class TestAsyncModule(AsyncTestCase):
    def test_async_add(self):
        print("Starting test_async_add")

        async def coro():
            print("Starting coroutine in test_async_add")
            result = await async_add(5, 3)
            print("Finished awaiting in test_async_add")
            self.assertEqual(result, 8)

        self.run_async_test(coro())
        print("Finished test_async_add")

    def test_dummy(self):
        print("Running test_dummy")
        self.assertTrue(True)
Run Code Online (Sandbox Code Playgroud)

和:

# async_module.py
import asyncio


async def async_add(a, b):
    await asyncio.sleep(1)  # Simulate an async operation
    return a + b
Run Code Online (Sandbox Code Playgroud)

完整项目位于VonC/AsyncTestCaseExample.

我得到:

C:\Users\vonc\AppData\Local\Programs\Python\Python311\python.exe C:\Users\vonc\PycharmProjects\AsyncTestCaseExample\__main__.py 
Setting up test case class
Starting test_async_add
Running async test: test_async_add
Starting coroutine in test_async_add
..
----------------------------------------------------------------------
Ran 2 tests in 1.016s

OK
Finished awaiting in test_async_add
Finished test_async_add
Running test_dummy
Tearing down test case class

Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)