sanic-org / sanic-testing

Test clients for Sanic
https://sanic.dev/en/plugins/sanic-testing/getting-started.html
MIT License
31 stars 19 forks source link

Reusable SanicASGITestClient #75

Open ShamansCoding opened 8 months ago

ShamansCoding commented 8 months ago

Motivation:

The SanicASGITestClient class provides only a client that lifts a new instance of the test application for each request.

This is very expensive and time-consuming. The application I'm trying to migrate to the current version of sanic-testing has 1500+ tests that pass on the old testing engine in 7 minutes. With the new SanicASGITestClient, passing 30 percent of the tests takes about 8 minutes.

In addition to the increased passing time, at 31 percent of the tests, there is a recursion error somewhere deep in ast.py. I couldn't figure out the cause of this behavior, and with the current version of the client, it's simply impossible to run the tests to completion.

Proposal to solve the problem:

The ability to use the SanicASGITestClient as a context manager or manually control its execution through the run() and stop() methods has been added to the class.

This allows for the repeated use of the running test server for multiple requests to the test server. With the right configuration of the test environment, the test server can be used within the scope="session."

@pytest.fixture(scope="session", autouse=True)
def event_loop():
    """Create an instance of the default event loop for each test case."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()

@pytest.fixture(scope="session", autouse=True)
async def test_cli(event_loop):
    asgi_client = SanicASGITestClient(real_app)

    await asgi_client.run()

    yield asgi_client

    await asgi_client.stop()

The running server also executes all lifecycle hooks of the provided real application instance, allowing you to start the server and test some parts of the application more isolated, while still having the ability to access the real context of the application and everything initialized in that context in the tests.

When running 100 consecutive API requests in one test using the old client in my application, the speed is about 44 seconds. With the use of the new client, the speed increases to 14 seconds.

Full backward compatibility is maintained; the client can be used as before, preserving the old API and behavior completely.