Add durable entity unit testing support - #218
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
There was a problem hiding this comment.
Pull request overview
Adds first-class, host-free unit testing support for Durable Entities in the azure-functions-durable package by introducing an execute_entity() harness that can execute a single entity operation in-process and surface the observable outcome for assertions.
Changes:
- Added
azure.durable_functions.testing.execute_entity()and supporting result/action types to run v1-style entities, durabletask-native entities, andDurableEntitysubclasses without a host/backend. - Added unit tests validating results, state mutation/deletion, identity, typed scheduled actions, decorated entity handles, and failure propagation.
- Documented the entity unit testing pattern and recorded the new helper in the package changelog.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/azure-functions-durable/test_entity_testing_support.py | Adds coverage for the new entity test harness across multiple entity styles and behaviors. |
| azure-functions-durable/README.md | Documents the new execute_entity() usage pattern for unit testing entities. |
| azure-functions-durable/CHANGELOG.md | Adds an Unreleased changelog entry describing the new testing helper. |
| azure-functions-durable/azure/durable_functions/testing/entity.py | Implements execute_entity() plus typed action/result models and action decoding. |
| azure-functions-durable/azure/durable_functions/testing/init.py | Exposes the new testing API surface via package exports. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
azure-functions-durable/azure/durable_functions/testing/entity.py:72
execute_entity()documents support forDurableEntitysubclasses, but the type hint and parameter docs only acceptCallable[..., Any]. This makes the public typing surface less accurate for class-based entities and can lead to type-checker confusion when passingtype[DurableEntity].
def execute_entity(
entity: Callable[..., Any],
operation: str,
input: Any = None,
state: Any = None,
*,
entity_name: str | None = None,
entity_key: str = "test",
) -> EntityTestResult:
"""Execute one entity operation without a Functions host or backend.
The ``entity`` argument may be a v1-style one-argument function, a
durabletask-native two-argument function, or a
:class:`~durabletask.entities.DurableEntity` subclass. Decorated entities can
be obtained from the function builder's exposed ``entity_function`` handle.
Parameters
----------
entity : Callable[..., Any]
The entity function or ``DurableEntity`` subclass to execute.
azure-functions-durable/azure/durable_functions/testing/entity.py:97
- The docstring’s Raises section doesn’t mention
ValueError, but the function raisesValueErrorwhen it can’t resolve an entity name. Please documentValueError(or change the exception type) so the API contract is accurate.
Raises
------
AttributeError
If a class-based entity does not define ``operation``.
TypeError
If the entity or operation is not callable.
Exception
Any exception raised by entity code or payload serialization.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
azure-functions-durable/azure/durable_functions/testing/entity.py:74
- Docstring parameter type for
entityis stillCallable[..., Any], but the function supports passing aDurableEntitysubclass. Update the docstring type to match the supported inputs (especially since this is user-facing API documentation).
Parameters
----------
entity : Callable[..., Any]
The entity function or ``DurableEntity`` subclass to execute.
operation : str
azure-functions-durable/azure/durable_functions/testing/entity.py:56
execute_entity()accepts aDurableEntitysubclass (and the docstring states this), but the public type hint currently restrictsentitytoCallable[..., Any]. This makes the public API harder to type-check for consumers.
Update the annotation to include type[DurableEntity] (or introduce an alias) so the signature matches the supported inputs.
This issue also appears on line 70 of the same file.
def execute_entity(
entity: Callable[..., Any],
operation: str,
azure-functions-durable/azure/durable_functions/testing/entity.py:126
- Input type discovery currently runs when
encoded_inputis an empty string because the guard isencoded_input is not None. In the durabletask worker, the equivalent check is truthiness (if encoded_input), treatingNoneand""consistently as “no payload”. Aligning the guard here avoids edge-case divergence and matches the runtime behavior more closely.
encoded_input = converter.serialize(input)
input_type = (
type_discovery.entity_input_type(
entity_callable, operation, converter)
if encoded_input is not None
else None
)
operation_input = converter.deserialize(encoded_input, input_type)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 643dfa24-59f4-4119-9377-0d9e488df141
berndverst
left a comment
There was a problem hiding this comment.
Verified the serialized-outcome redesign at a727c82. Strict-mode tuple and custom result, state, signal, and orchestration payloads now match production wire snapshots, including post-call mutations.
Summary
execute_entity()for host-free testing of v1-style, durabletask-native, and class-based entitiesValidation
python -m pytest tests/azure-functions-durable -m "not dts and not azurite and not functions_e2e" --quietpython -m flake8 azure-functions-durablepython -m flake8 tests/azure-functions-durablepython -m pyright ...for changed Python filespython -m pymarkdown -c .pymarkdown.json scan azure-functions-durable/README.mdCloses #184