-
-
Notifications
You must be signed in to change notification settings - Fork 762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test Gunicorn Worker #1834
Comments
I can take this on. I agree we should keep it simple and focus on unit testing. One way I've approached unit testing without mocks is by starting a Gunicorn server with the I'll think about some other complementary ways to approach testing of the worker. |
Just dropping a note here to say that I'm working on this and making some slow progress. I started off with the Instead, I'm working on some testing capabilities that will:
Hope to have a PR for review soon. |
This comment was marked as spam.
This comment was marked as spam.
I'm working through a few tedious limitations right now. One of them relates to conditional test coverage. As correctly suggested in the description, we need to change our coverage.py config from The limitation is that we can't cover How do we tell coverage.py, "please exclude Coverage.py has an I tried setting pragmas at the top-level of the modules, but coverage-conditional-plugin doesn't support this (wemake-services/coverage-conditional-plugin#2). Am I missing something? Or will I need to do a PR that resolves wemake-services/coverage-conditional-plugin#2 in order to unblock this? I guess the simplest option would be to add a |
PR submitted (wemake-services/coverage-conditional-plugin#221). This feature will enable entire modules to be conditionally omitted from test coverage measurement. |
Coding for this is done, and we now have a nice way to omit the worker code from test coverage measurement on Windows, thanks to coverage-conditional-plugin 0.9.0. PR coming up shortly. |
Thanks 🙏 |
I'll deprecate the workers within Uvicorn. |
This project supports the Gunicorn web server. Gunicorn's server design includes a primary "arbiter" process that spawns "worker" processes. Workers are child processes, each with their own running server. Workers are implemented as Python classes. Custom workers can be supplied. This project also supports the Uvicorn web server. In the past, Uvicorn supplied workers for use with Gunicorn. The Uvicorn workers were not tested. The `uvicorn.workers` module was completely omitted from coverage measurement due to use of the coverage.py `include` setting to specify source files. Efforts were made to test the Uvicorn workers (encode/uvicorn#1834, encode/uvicorn#1995), but the workers were arbitrarily deprecated and moved to someone's personal project (encode/uvicorn#2302), instead of an Encode-managed project as would have been expected (encode/uvicorn#517 (comment)) Rather than introducing a production dependency on a separate Uvicorn workers package that is not managed by Encode, this commit will add the Gunicorn workers directly to this project. This commit will add the code from `uvicorn.workers` to a new module `inboard/gunicorn_workers.py`. The code will be preserved as it was prior to deprecation, with a copy of the Uvicorn license and necessary updates for compliance with the code quality settings in this project: - Ruff [UP008](https://docs.astral.sh/ruff/rules/super-call-with-parameters/) - Ruff [UP035](https://docs.astral.sh/ruff/rules/deprecated-import/) - mypy `[attr-defined]` - Module "uvicorn.main" does not explicitly export attribute "Server" - mypy `[import-untyped]` - `gunicorn.arbiter` - mypy `[import-untyped]` - `gunicorn.workers.base` - mypy `[misc]` - Class cannot subclass "Worker" (has type "Any") - mypy `[type-arg]` - Missing type parameters for generic type "dict" (on `config_kwargs`) This commit will also add tests of 100% of the Gunicorn worker code to a new module `tests/test_gunicorn_workers.py`. A test fixture starts a subprocess running Gunicorn with a Uvicorn worker and an ASGI app. The subprocess includes an instance of `httpx.Client` for HTTP requests to the Uvicorn worker's ASGI app, and saves its output to a temporary file for assertions on `stdout`/`stderr`. Tests can send operating system signals to the process. The coverage.py configuration will be updated for subprocess test coverage measurement. Changes to coverage measurement include: - Enable the required parallel mode (note that it is important to ensure the `.gitignore` ignores files named `.coverage.*` because many coverage files are generated when subprocesses are measured in parallel mode) - Set the required `COVERAGE_PROCESS_START` environment variable - Add the `coverage_enable_subprocess` package to invoke `coverage.process_startup` - Combine coverage reports before reporting coverage - Add instructions to `contributing.md` about how to omit subprocess tests Related: https://github.com/encode/uvicorn/blob/4fd507718eb0313e2de66123e6737b054088f722/LICENSE.md https://github.com/encode/uvicorn/blob/4fd507718eb0313e2de66123e6737b054088f722/uvicorn/workers.py encode/uvicorn#517 (comment) encode/uvicorn#1834 encode/uvicorn#1995 encode/uvicorn#2302 https://coverage.readthedocs.io/en/latest/subprocess.html https://docs.gunicorn.org/en/latest/design.html https://docs.gunicorn.org/en/latest/signals.html https://www.uvicorn.org/deployment/#gunicorn
The idea here is to create a setup to test the
gunicorn
worker classes that we have.I don't know how is the best way to achieve this, as
gunicorn
test suite didn't give me much insight on how we can test this integration withoutunittest.mock
. Suggestions are welcome.If you are interested on working on this, go ahead. Some clarifications:
unittest.mock
- if inevitable, explain the reason.workers.py
.Notes
When doing this, please change those lines:
uvicorn/setup.cfg
Lines 39 to 43 in eec7d22
To something more like: https://github.com/encode/starlette/blob/048643adc21e75b668567fc6bcdd3650b89044ea/setup.cfg#L41-L42
Important
The text was updated successfully, but these errors were encountered: