[Python] How to avoid 'Asyncio runner is already initialised' error, when running async tests...

Discussão em 'Python' iniciado por Stack, Setembro 26, 2024.

  1. Stack

    Stack Membro Participativo

    I am trying to run an async test case in a loop, with Python's unittesting framework; however, I am running into a brick wall with the error: AssertionError: asyncio runner is already initialized

    As part of my loop, I have to reinitialise the test suite as following:

    tests = get_tests()
    suite = unittest.TestSuite(tests)
    runner = unittest.TextTestRunner()

    for _ in range(3):
    result = runner.run(suite)
    unittest.registerResult(result)
    suite = unittest.TestSuite(tests)


    The test that is causing problems is (minimal version):


    async def basic_async_func():
    await asyncio.sleep(2)
    return 'hello'

    class MyAsyncTestClass(unittest.IsolatedAsyncioTestCase):

    @classmethod
    def setUpClass(cls):
    cls.name = 'foo'
    # Handling async class set up
    asyncio.run(cls.asyncSetUpClass())

    @classmethod
    async def asyncSetUpClass(cls):
    cls.statement = await basic_async_func()

    def test_set_up(self):
    self.assertEqual(self.statement,'hello')



    I get the following output:

    Traceback (most recent call last):
    File "/home/main.py", line 151, in <module>
    main()
    File "/home/main.py", line 116, in main
    test_result = runner.run(single_suite)
    ^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/lib/python3.12/unittest/runner.py", line 240, in run
    test(result)
    File "/usr/lib/python3.12/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
    ^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/lib/python3.12/unittest/suite.py", line 122, in run
    test(result)
    File "/usr/lib/python3.12/unittest/case.py", line 690, in __call__
    return self.run(*args, **kwds)
    ^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/lib/python3.12/unittest/async_case.py", line 129, in run
    self._setupAsyncioRunner()
    File "/usr/lib/python3.12/unittest/async_case.py", line 120, in _setupAsyncioRunner
    assert self._asyncioRunner is None, 'asyncio runner is already initialized'
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    AssertionError: asyncio runner is already initialized


    I have tried a few different things to resolve this.

    Firstly, I'd originally manually set an event loop:

    cls.loop = asyncio.new_event_loop()
    asyncio.set_event_loop(cls.loop)
    cls.loop.run_until_complete(cls.asyncSetUpClass())


    Secondly, I tried using the asyncio.runner context manager:

    with asyncio.Runner() as runner:
    runner.run(cls.asyncSetUpClass())


    Lastly, I tried to remove the classSetUp method (though this has been a requirement of my actual, non-minimal test case), and to instead just use IsolatedAsyncioTestCase's asyncSetUp function:

    async def asyncSetUp(self):
    self.name = 'foo'
    self.statement = await basic_async_func()


    All of these have given the same error output as above. I am wondering if I need to somehow set or close an asyncio runner at the level of the loop in the first code block? (I tried re-initialising the unittest runner in every loop iteration and this didn't work)

    Continue reading...

Compartilhe esta Página