Testing Batteries
djxi.testing provides utilities that make it straightforward to write
unit and integration tests for DXEndpointBattery classes.
Overview
Name |
Description |
|---|---|
|
|
|
Standalone assertion: raises |
|
Standalone assertion: raises |
|
|
DXBatteryTestCase
The recommended base class for battery tests:
# myapp/tests.py
from djxi.testing import DXBatteryTestCase
from myapp.views import ItemBattery
class ItemBatteryTests(DXBatteryTestCase):
def test_list_renders_empty_state(self):
request = self.dx.get("/")
response = ItemBattery().render_section(request, "item-list", {"items": []})
self.assert_section_rendered(response, "No items yet.")
def test_list_renders_item_title(self):
item = Item.objects.create(title="Buy milk")
request = self.dx.get("/")
response = ItemBattery().render_section(
request, "item-list", {"items": [item]}
)
self.assert_section_rendered(response, "Buy milk")
self.assert_section_not_rendered(response, "No items yet.")
def test_create_adds_item(self):
request = self.dx.post("/", data={"title": "New task"})
response = ItemBattery().url_patterns()[1].callback(request)
self.assertEqual(response.status_code, 200)
self.assertTrue(Item.objects.filter(title="New task").exists())
DXRequestFactory
DXRequestFactory mirrors the RequestFactory API
(get, post, put, patch, delete) but runs the full
MIDDLEWARE stack before returning the request:
from djxi.testing import DXRequestFactory
factory = DXRequestFactory()
request = factory.get("/items/")
assert hasattr(request, "htmx") # DjxiHeadersMiddleware has run
request = factory.post("/items/create", data={"title": "Task"})
assert request.POST["title"] == "Task"
You can pass a custom middleware list to isolate specific middleware:
factory = DXRequestFactory(middleware=["djxi.middleware.DjxiHeadersMiddleware"])
request = factory.get("/")
assert hasattr(request, "htmx")
Standalone assertion helpers
Import and use them in any test framework (pytest, unittest, etc.):
import pytest
from django.http import HttpResponse
from djxi.testing import assert_section_rendered, assert_section_not_rendered
def test_greeting():
response = HttpResponse(b"<p>Hello, Alice!</p>")
assert_section_rendered(response, "Hello, Alice!")
assert_section_not_rendered(response, "Hello, Bob!")
def test_greeting_fails_correctly():
response = HttpResponse(b"<p>Nothing here</p>")
with pytest.raises(AssertionError) as exc_info:
assert_section_rendered(response, "Hello, Alice!")
assert "Hello, Alice!" in str(exc_info.value)
Testing async handlers
For async handlers, call the view function directly and await it:
import asyncio
from djxi.testing import DXRequestFactory
from myapp.views import AsyncItemBattery
def test_async_list():
factory = DXRequestFactory()
request = factory.get("/")
patterns = AsyncItemBattery.url_patterns()
view = next(p for p in patterns if p.name == "list").callback
response = asyncio.get_event_loop().run_until_complete(view(request))
assert response.status_code == 200
assert b"item-list" in response.content
Testing permission hooks
Attach a user object to the request to test requires_auth and
check_permissions():
from types import SimpleNamespace
from django.contrib.auth.models import AnonymousUser
def test_anonymous_is_rejected():
factory = DXRequestFactory()
request = factory.get("/")
request.user = AnonymousUser()
view = ProtectedBattery.url_patterns()[0].callback
response = view(request)
assert response.status_code == 403
def test_authenticated_user_is_allowed():
factory = DXRequestFactory()
request = factory.get("/")
request.user = SimpleNamespace(is_authenticated=True)
view = ProtectedBattery.url_patterns()[0].callback
response = view(request)
assert response.status_code == 200
API reference
- class DXRequestFactory(middleware=None)
- Parameters:
middleware – Optional list of middleware dotted paths. Defaults to
settings.MIDDLEWARE.
- get(path='/', **kwargs)
- post(path='/', data=None, **kwargs)
- put(path='/', data=None, **kwargs)
- patch(path='/', data=None, **kwargs)
- delete(path='/', **kwargs)
Create an
HttpRequestand run it through the middleware stack.
- assert_section_rendered(response, text)
Assert that text is present in the decoded response body. Raises
AssertionErrorwith a descriptive message on failure.
- assert_section_not_rendered(response, text)
Assert that text is absent from the decoded response body. Raises
AssertionErrorwith a descriptive message on failure.