Testing
The testing modules provide specialized testing utilities for WebSocket consumers, including enhanced communicators and base test case classes with authentication support and message collection capabilities.
Core Testing
The core testing module provides the foundation for Chanx's testing infrastructure with a framework-agnostic mixin.
- class chanx.core.testing.WebsocketCommunicatorMixin(application: Any, path: str, headers: list[tuple[bytes, bytes]] | None = None, subprotocols: list[str] | None = None, spec_version: int | None = None, *, consumer: type[ChanxWebsocketConsumerMixin[Any]])
Mixin providing enhanced WebSocket testing functionality for Chanx consumers.
This mixin provides Chanx-specific features that work across different WebSocket frameworks (Django Channels, fast-channels, etc.):
Structured message sending and receiving with BaseMessage objects
Automatic message collection until completion signals
Message validation using consumer's type adapters
Connection state tracking
Async context manager support for automatic cleanup
Key methods:
send_message(): Send BaseMessage objects directly
receive_all_json(): Collect all messages until timeout
receive_all_messages(): Collect and validate messages until stop action
connect()/disconnect(): Enhanced connection management
The mixin automatically handles message serialization/deserialization and integrates with Chanx's completion signal system for reliable testing.
Concrete implementations should inherit from both this mixin and a framework-specific WebSocket communicator class (e.g., channels.testing.WebsocketCommunicator).
- action_key: str = 'action'
- application: Any
- async assert_closed() None
Asserts that the WebSocket has been closed.
- async connect(timeout: float = 1) tuple[bool, int | str | None]
Connects to the WebSocket and tracks connection state.
- Parameters:
timeout -- Maximum time to wait for connection (in seconds)
- Returns:
Tuple of (connected, status_code)
- consumer: type[ChanxWebsocketConsumerMixin]
- async disconnect(code: int = 1000, timeout: float = 1) None
Closes the socket
- Parameters:
code -- Optional code to disconnect
timeout -- Maximum time to wait for connection (in seconds)
- async receive_all_json(timeout: float = 1) list[dict[str, Any]]
Receives and collects all JSON messages until an ACTION_COMPLETE message is received or timeout occurs.
- Parameters:
timeout -- Maximum time to wait for messages (in seconds)
- Returns:
List of received JSON messages
- async receive_all_messages(stop_action: Literal['complete', 'event_complete', 'group_complete'] | str = 'complete', timeout: float = 1) list[BaseMessage]
Receives and collects JSON messages until a specific action is received.
Automatically filters out completion messages (ACTION_COMPLETE and GROUP_ACTION_COMPLETE).
- Parameters:
stop_action -- The action type to stop collecting at
timeout -- Maximum time to wait for messages (in seconds)
- Returns:
List of received JSON messages (excluding completion messages)
- async receive_json_from(timeout: float = 1) Any
Receive and parse JSON data from the WebSocket.
Provided by the framework testing communicator (Channels/fast-channels).
- Parameters:
timeout -- Maximum time to wait for data (seconds)
- Returns:
Parsed JSON data as dictionary
- async receive_output(timeout: float = 1) Any
Receive raw output from the WebSocket.
Provided by the framework testing communicator (Channels/fast-channels).
- Parameters:
timeout -- Maximum time to wait for output (seconds)
- Returns:
Raw output dictionary
- async send_json_to(data: dict[str, Any]) None
Send JSON data to the WebSocket.
Provided by the framework testing communicator (Channels/fast-channels).
- Parameters:
data -- Dictionary to serialize and send as JSON
- async send_message(message: BaseMessage) None
Sends a Message object as JSON to the WebSocket.
- Parameters:
message -- The Message instance to send
- class chanx.core.testing.CapturedBroadcastEvent(event: BaseMessage, groups: Collection[str] | str | None)
Structure of a captured broadcast event.
- event: BaseMessage
- groups: Collection[str] | str | None
- chanx.core.testing.capture_broadcast_events(consumer: type[ChanxWebsocketConsumerMixin], suppress: bool = True) Generator[list[CapturedBroadcastEvent], None, None]
Capture broadcast events sent via broadcast_event() for testing purposes.
Similar to structlog's capture_logs(), this context manager captures calls to broadcast_event() by monkey-patching the broadcast_event method to spy on events.
- Parameters:
consumer -- The consumer class to capture broadcast events from.
suppress -- If True (default), suppress actual broadcast event calls. If False, capture events and still call the original broadcast_event.
- Returns:
A list that will be populated with captured broadcast events.
Django Channels Testing
The Django Channels testing module provides Django-specific testing utilities.
- class chanx.channels.testing.WebsocketCommunicator(application: Any, path: str, headers: list[tuple[bytes, bytes]] | None = None, subprotocols: list[str] | None = None, spec_version: int | None = None, *, consumer: type[ChanxWebsocketConsumerMixin[Any]])
Base WebSocket communicator for testing Chanx consumers with Django Channels.
Combines Chanx testing features (send_message, receive_all_messages, message validation) with Django Channels' WebSocket communicator (connect, disconnect, send_json_to).
For Django-specific features like authentication, use DjangoWebsocketCommunicator.
- application: Any
- consumer: type[AsyncJsonWebsocketConsumer]
- class chanx.channels.testing.DjangoWebsocketCommunicator(application: Any, path: str, headers: list[tuple[bytes, bytes]] | None = None, subprotocols: list[str] | None = None, spec_version: int | None = None, *, consumer: type[ChanxWebsocketConsumerMixin[Any]])
Extends WebsocketCommunicator with Django authentication and settings integration.
Adds Django-specific features:
wait_for_auth(): Handle Django authentication messages
assert_authenticated_status_ok(): Validate DRF authentication status
SEND_AUTHENTICATION_MESSAGE and CAMELIZE settings support
Use this for Django consumers with authentication.
- async assert_authenticated_status_ok(max_auth_time: float = 0.5) None
Assert that the WebSocket connection was authenticated successfully.
Waits for an authentication message and verifies that its status code is 200 OK.
- Parameters:
max_auth_time -- Maximum time to wait for authentication message (in seconds)
- Raises:
AssertionError -- If the authentication status is not 200 OK
- async wait_for_auth(send_authentication_message: bool | None = None, max_auth_time: float = 0.5, after_auth_time: float = 0.1) AuthenticationMessage | None
Waits for and returns an authentication message if enabled in settings.
- Parameters:
send_authentication_message -- Whether to expect auth message, defaults to setting
max_auth_time -- Maximum time to wait for authentication (in seconds)
after_auth_time -- Wait time sleep after authentication (in seconds)
- Returns:
Authentication message or None if auth is disabled
- class chanx.channels.testing.WebsocketTestCase(*args: Any, **kwargs: Any)
Django test case for WebSocket testing with Chanx.
Integrates Chanx WebSocket testing with Django's test framework, providing:
Django TransactionTestCase inheritance for database transaction handling
Automatic Django ASGI application discovery from routing configuration
Django-style setUp/tearDown with automatic communicator cleanup
Integration with Django authentication headers via get_ws_headers()
Support for Django-specific WebSocket subprotocols
Usage: 1. Subclass WebsocketTestCase 2. Set ws_path to your Django WebSocket endpoint 3. Override get_ws_headers() for Django authentication 4. Use self.auth_communicator for primary connection testing 5. Use create_communicator() for multi-user Django scenarios
The test case automatically discovers WebSocket routing from Django's ASGI configuration and ensures proper cleanup of all connections after each test.
- property auth_communicator: DjangoWebsocketCommunicator
Returns a connected DjangoWebsocketCommunicator instance. The instance is created using create_communicator if not already exists.
- consumer: type[AsyncJsonWebsocketConsumer[Any]]
- create_communicator(*, router: Any | None = None, ws_path: str | None = None, headers: list[tuple[bytes, bytes]] | None = None, subprotocols: list[str] | None = None) DjangoWebsocketCommunicator
Creates a DjangoWebsocketCommunicator for testing WebSocket connections.
Creates and tracks a communicator instance for interacting with WebSocket consumers in tests, allowing you to create multiple communicators to test various scenarios including: - Multi-user WebSocket interactions - Testing group message broadcasting - Testing authentication with different credentials - Simulating concurrent connections
The method tracks all created communicators and automatically handles their cleanup during tearDown() to prevent resource leaks.
- Parameters:
router -- Application to use (defaults to self.router)
ws_path -- WebSocket path to connect to (defaults to self.ws_path)
headers -- HTTP headers to include (defaults to self.ws_headers) Use different headers for testing multiple authenticated users
subprotocols -- WebSocket subprotocols to use (defaults to self.subprotocols)
- Returns:
A configured DjangoWebsocketCommunicator instance ready for connecting
- Raises:
AttributeError -- If ws_path is not set and not provided
- get_subprotocols() list[str]
Returns WebSocket subprotocols to use. Override this method to provide custom subprotocols.
- get_ws_headers() list[tuple[bytes, bytes]]
Returns WebSocket headers for authentication/configuration. Override this method to provide custom headers.
- router: Any = None
- setUp() None
Set up the test environment before each test method.
Initializes WebSocket headers and subprotocols by calling the corresponding getter methods, and prepares for tracking communicators.
- tearDown() None
Clean up after each test method.
Ensures all WebSocket connections created during the test are properly disconnected to prevent resource leaks and test isolation issues.
- ws_path: str = ''
FastAPI Testing
The FastAPI testing module provides FastAPI-specific testing utilities.
- class chanx.fast_channels.testing.WebsocketCommunicator(application: Any, path: str, headers: list[tuple[bytes, bytes]] | None = None, subprotocols: list[str] | None = None, spec_version: int | None = None, *, consumer: type[ChanxWebsocketConsumerMixin[Any]])
Fast-channels WebSocket communicator for testing Chanx consumers.
Combines Chanx testing mixin features with fast-channels' WebSocket communicator, providing comprehensive testing capabilities for FastAPI applications:
Chanx features (from WebsocketCommunicatorMixin):
Structured message sending/receiving with BaseMessage objects
Automatic message collection until completion signals
Message validation using consumer's type adapters
Async context manager support for automatic cleanup
send_message(): Send BaseMessage objects directly
receive_all_json(): Collect all messages until timeout
receive_all_messages(): Collect and validate messages until stop action
FastAPI fast-channels features:
Full compatibility with FastAPI ASGI applications
fast-channels channel layer support
High-performance async operation
- application: Any
- consumer: type[AsyncJsonWebsocketConsumer]