I'm building API that allows users to send input data to generate printable documents.
On top of that I need to allow admin users to define/adjust templates (HTML) for these documents in which users define the layout and logic. Admin users use customized Django Admin to maintain these document templates.
One of the requirements is for the admin users to be able to test their templates: (1) generate and download document out of Django Admin for some test input data, (2) run tests assessing if documents have correct content for multiple test cases.
Users can define test cases for their templates: combination of input data as well as expected output. They can also select test cases and using custom Django admin action they can run tests for these selected test cases (using pytest).
Pytest uses test input data, renders the output document and compares it to the user defined benchmark outputs. Stdout of pytest should is written to text file which is then included in the response of custom Django admin action (downloaded by browser).
My initial implementation behind Django admin was using pytest.main() functionality.
...
import sys
from io import StringIO
...
import pytest
class TestCaseAdmin(admin.ModelAdmin):
...
def run_selected_test_cases(self, request, queryset):
sys.stdout = StringIO()
pytest.main([
"tests/functional/test_user_cases.py",
"-vv",
])
result = sys.stdout.getvalue()
response = HttpResponse(result, content_type="text/plain")
response["Content-Disposition"] = f"attachment; filename={filename}"
return response
The above implementation will run the tests defined in test_user_cases.py and download text file with pytest stdout. However after this is done, pytest crashes with error:
RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
This error will be thrown even if test function in test_user_cases.py is only doing a simple assert True
If I run the same test out of CLI, error is not thrown.
Does anyone know why pytest / pytest-django crashes in this case?
An alternative implementation using subprocess
:
import subprocess
...
def run_selected_test_cases(self, request, queryset):
result = subprocess.run(
[
"python3",
"-m",
"pytest",
"tests/functional/test_user_cases.py",
"-vv",
],
capture_output=True,
text=True,
)
response = HttpResponse(result, content_type="text/plain")
response["Content-Disposition"] = f"attachment; filename={filename}"
return response
does not throw the above error, but the execution is much slower.
Can anyone see an obvoious error in using pytest.main function?