Skip to content

Commit 0b0b122

Browse files
committed
Updates.
2 parents 8261591 + d920155 commit 0b0b122

File tree

388 files changed

+2273
-1792
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

388 files changed

+2273
-1792
lines changed

articles/api-management/workspaces-overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ The following constraints currently apply to workspace gateways:
132132
* Request metrics can't be split by workspace in Azure Monitor; all workspace metrics are aggregated at the service level
133133
* Workspace gateways don't support CA certificates
134134
* Workspace gateways don't support managed identities, including related features like storing secrets in Azure Key Vault and using the `authentication-managed-identity` policy
135+
* Workspace gateways can only be created in the API Management instance's primary Azure region
135136

136137
## RBAC roles for workspaces
137138

articles/app-service/app-service-configure-premium-v4-tier.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Configure Premium V4 tier
33
description: Learn how to better performance for your web, mobile, and API app in Azure App Service by scaling to the new Premium V4 pricing tier.
44
keywords: app service, azure app service, scale, scalable, app service plan, app service cost
55
ms.topic: article
6-
ms.date: 06/13/2025
6+
ms.date: 06/18/2025
77
ms.author: msangapu
88
author: msangapu-msft
99
ms.custom:
@@ -98,14 +98,20 @@ Premium V4 is available in the following regions:
9898

9999
- Australia East
100100
- Canada Central
101+
- Central US
101102
- East US
102103
- East US 2
103104
- France Central
105+
- North Central US
104106
- North Europe
107+
- Norway East
105108
- Southeast Asia
106109
- Sweden Central
110+
- Switzerland North
111+
- UK South
107112
- West Central US
108113
- West Europe
114+
- West US
109115
- West US 3
110116

111117
## Scale up from an unsupported resource group and region combination

articles/azure-app-configuration/howto-telemetry.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ms.service: azure-app-configuration
66
author: mrm9084
77
ms.author: mametcal
88
ms.topic: how-to
9-
ms.date: 03/05/2025
9+
ms.date: 06/19/2025
1010
---
1111

1212
# Enable telemetry for feature flags
@@ -33,7 +33,7 @@ These types of questions can be answered through the emission and analysis of fe
3333
> [!div class="mx-imgBorder"]
3434
> ![Screenshot of the Azure portal, connecting application insights.](./media/howto-telemetry/connect-to-app-insights.png)
3535
36-
## Enable telemetry for a feature flag (preview)
36+
## Enable telemetry for a feature flag
3737

3838
1. Open your App Configuration store in the Azure portal and select the **Feature manager** blade under the **Operations** section.
3939
1. Select the feature flag named Greeting. If you don't have it, follow the [instructions to create it](./manage-feature-flags.md). Then, right-click on the feature flag and select **Edit**.

articles/azure-compute-fleet/quickstart-create-azure-cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export MY_SUBNET_ID="$(az network vnet subnet show \
8080

8181
## Set up the admin password
8282

83-
Set up a password that meets the [password requirements for Azure VMs](https://learn.microsoft.com/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-).
83+
Set up a password that meets the [password requirements for Azure VMs](/azure/virtual-machines/windows/faq#what-are-the-password-requirements-when-creating-a-vm-).
8484

8585
```bash
8686
export ADMIN_PASSWORD="Azure compliant password"

articles/azure-functions/durable/TOC.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,10 @@
188188
href: durable-functions-create-portal.md
189189
- name: Manage connections
190190
href: ../manage-connections.md?toc=/azure/azure-functions/durable/toc.json
191-
- name: Unit testing
191+
- name: Unit testing (C#)
192192
href: durable-functions-unit-testing.md
193+
- name: Unit testing (Python)
194+
href: durable-functions-unit-testing-python.md
193195
- name: Create as WebJobs
194196
href: durable-functions-webjobs-sdk.md
195197
- name: Durable entities in .NET
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
---
2+
title: Unit Testing Durable Functions in Python
3+
description: Learn about unit testing best practices for Durable functions written in Python for Azure Functions.
4+
author: andystaples
5+
ms.topic: conceptual
6+
ms.date: 05/07/2025
7+
ms.author: azfuncdf
8+
---
9+
10+
# Unit testing Durable Functions in Python
11+
12+
Unit testing is an important part of modern software development practices. Unit tests verify business logic behavior and protect from introducing unnoticed breaking changes in the future. Durable Functions can easily grow in complexity so introducing unit tests helps avoid breaking changes. The following sections explain how to unit test the three function types - Orchestration client, orchestrator, and entity functions.
13+
14+
> [!NOTE]
15+
> This guide applies only to Durable Functions apps written in the [Python v2 programming model](../functions-reference-python.md).
16+
17+
## Prerequisites
18+
19+
The examples in this article require knowledge of the following concepts and frameworks:
20+
21+
* Unit testing
22+
* Durable Functions
23+
* Python [unittest](https://docs.python.org/3/library/unittest.html)
24+
* [unittest.mock](https://docs.python.org/3/library/unittest.mock.html)
25+
26+
## Setting up the test environment
27+
28+
To test Durable Functions, it's crucial to set up a proper test environment. This includes creating a test directory and installing Python's `unittest` module into your Python environment. For more info, see the [Azure Functions Python unit testing overview](../functions-reference-python.md#unit-testing).
29+
30+
## Unit testing trigger functions
31+
32+
Trigger functions, often referred to as _client_ functions, initiate orchestrations and external events. To test these functions:
33+
34+
- Mock the `DurableOrchestrationClient` to simulate orchestration execution and status management.
35+
- Assign `DurableOrchestrationClient` methods such as `start_new`, `get_status`, or `raise_event` with mock functions that return expected values.
36+
- Invoke the client function directly with a mocked client and other necessary inputs such as a `req` (HTTP request object) for HTTP trigger client functions.
37+
- Use assertions and `unittest.mock` tools to verify expected orchestration start behavior, parameters, and HTTP responses.
38+
39+
```python
40+
import asyncio
41+
import unittest
42+
import azure.functions as func
43+
from unittest.mock import AsyncMock, Mock, patch
44+
45+
from function_app import start_orchestrator
46+
47+
class TestFunction(unittest.TestCase):
48+
@patch('azure.durable_functions.DurableOrchestrationClient')
49+
def test_HttpStart(self, client):
50+
# Get the original method definition as seen in the function_app.py file
51+
func_call = http_start.build().get_user_function().client_function
52+
53+
req = func.HttpRequest(method='GET',
54+
body=b'{}',
55+
url='/api/my_second_function',
56+
route_params={"functionName": "my_orchestrator"})
57+
58+
client.start_new = AsyncMock(return_value="instance_id")
59+
client.create_check_status_response = Mock(return_value="check_status_response")
60+
61+
# Execute the function code
62+
result = asyncio.run(func_call(req, client))
63+
64+
client.start_new.assert_called_once_with("my_orchestrator")
65+
client.create_check_status_response.assert_called_once_with(req, "instance_id")
66+
self.assertEqual(result, "check_status_response")
67+
```
68+
69+
## Unit testing orchestrator functions
70+
71+
Orchestrator functions manage the execution of multiple activity functions. To test an orchestrator:
72+
73+
- Mock the `DurableOrchestrationContext` to control function execution.
74+
- Replace `DurableOrchestrationContext` methods needed for orchestrator execution like `call_activity` or `create_timer` with mock functions. These functions will typically return objects of type TaskBase with a `result` property.
75+
- Call the orchestrator recursively, passing the result of the Task generated by the previous yield statement to the next.
76+
- Verify the orchestrator result using the results returned from the orchestrator and `unittest.mock`.
77+
78+
```python
79+
import unittest
80+
from unittest.mock import Mock, patch, call
81+
from datetime import timedelta
82+
from azure.durable_functions.testing import orchestrator_generator_wrapper
83+
84+
from function_app import my_orchestrator
85+
86+
87+
class TestFunction(unittest.TestCase):
88+
@patch('azure.durable_functions.DurableOrchestrationContext')
89+
def test_chaining_orchestrator(self, context):
90+
# Get the original method definition as seen in the function_app.py file
91+
func_call = my_orchestrator.build().get_user_function().orchestrator_function
92+
93+
# The mock_activity method is defined above with behavior specific to your app.
94+
# It returns a TaskBase object with the result expected from the activity call.
95+
context.call_activity = Mock(side_effect=mock_activity)
96+
97+
# Create a generator using the method and mocked context
98+
user_orchestrator = func_call(context)
99+
100+
# Use orchestrator_generator_wrapper to get the values from the generator.
101+
# Processes the orchestrator in a way that is equivalent to the Durable replay logic
102+
values = [val for val in orchestrator_generator_wrapper(user_orchestrator)]
103+
104+
expected_activity_calls = [call('say_hello', 'Tokyo'),
105+
call('say_hello', 'Seattle'),
106+
call('say_hello', 'London')]
107+
108+
self.assertEqual(context.call_activity.call_count, 3)
109+
self.assertEqual(context.call_activity.call_args_list, expected_activity_calls)
110+
self.assertEqual(values[3], ["Hello Tokyo!", "Hello Seattle!", "Hello London!"])
111+
```
112+
113+
## Unit testing entity functions
114+
115+
Entity functions manage stateful objects with operations. To test an entity function:
116+
117+
- Mock the `DurableEntityContext` to simulate the entity's internal state and operation inputs.
118+
- Replace `DurableEntityContext` methods like `get_state`, `set_state`, and `operation_name` with mocks that return controlled values.
119+
- Invoke the entity function directly with the mocked context.
120+
- Use assertions to verify state changes and returned values, along with `unittest.mock` utilities.
121+
122+
```python
123+
import unittest
124+
from unittest.mock import Mock, patch
125+
126+
from function_app import Counter
127+
128+
class TestEntityFunction(unittest.TestCase):
129+
@patch('azure.durable_functions.DurableEntityContext')
130+
def test_entity_add_operation(self, context_mock):
131+
# Get the original method definition as seen in function_app.py
132+
func_call = Counter.build().get_user_function().entity_function
133+
134+
# Setup mock context behavior
135+
state = 0
136+
result = None
137+
138+
def set_state(new_state):
139+
nonlocal state
140+
state = new_state
141+
142+
def set_result(new_result):
143+
nonlocal result
144+
result = new_result
145+
146+
context_mock.get_state = Mock(return_value=state)
147+
context_mock.set_state = Mock(side_effect=set_state)
148+
149+
context_mock.operation_name = "add"
150+
context_mock.get_input = Mock(return_value=5)
151+
152+
context_mock.set_result = Mock(side_effect=lambda x: set_result)
153+
154+
# Call the entity function with the mocked context
155+
func_call(context_mock)
156+
157+
# Verify the state was updated correctly
158+
context_mock.set_state.assert_called_once_with(5)
159+
self.assertEqual(state, 5)
160+
self.assertEqual(result, None)
161+
```
162+
163+
## Unit testing activity functions
164+
165+
Activity functions require no Durable-specific modifications to be tested. The guidance found in the [Azure Functions Python unit testing overview](../functions-reference-python.md#unit-testing) is sufficient for testing these functions.
166+
167+
## Related content
168+
169+
- [Learn how to improve throughput performance of Python apps in Azure Functions](../python-scale-performance-reference.md)
170+
- [Read the Azure Functions Python Developer Guide](../functions-reference-python.md)
171+
- [Learn about Durable Functions best practices and diagnostic tools](./durable-functions-best-practice-reference.md)

articles/azure-functions/durable/durable-functions-unit-testing.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ms.date: 11/03/2019
77

88
# Durable Functions unit testing (C#)
99

10-
Unit testing is an important part of modern software development practices. Unit tests verify business logic behavior and protect from introducing unnoticed breaking changes in the future. Durable Functions can easily grow in complexity so introducing unit tests will help to avoid breaking changes. The following sections explain how to unit test the three function types - Orchestration client, orchestrator, and activity functions.
10+
Unit testing is an important part of modern software development practices. Unit tests verify business logic behavior and protect from introducing unnoticed breaking changes in the future. Durable Functions can easily grow in complexity so introducing unit tests helps avoid breaking changes. The following sections explain how to unit test the three function types - Orchestration client, orchestrator, and activity functions.
1111

1212
> [!NOTE]
1313
> This article provides guidance for unit testing for Durable Functions apps written in C# for the .NET in-process worker and targeting Durable Functions 2.x. For more information about the differences between versions, see the [Durable Functions versions](durable-functions-versions.md) article.
@@ -28,23 +28,23 @@ The examples in this article require knowledge of the following concepts and fra
2828

2929
Mocking is supported via the following interface:
3030

31-
* [IDurableOrchestrationClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableorchestrationclient), [IDurableEntityClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableentityclient) and [IDurableClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableclient)
31+
* [IDurableOrchestrationClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableorchestrationclient), [IDurableEntityClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableentityclient), and [IDurableClient](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableclient)
3232

3333
* [IDurableOrchestrationContext](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableorchestrationcontext)
3434

3535
* [IDurableActivityContext](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableactivitycontext)
3636

3737
* [IDurableEntityContext](/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableentitycontext)
3838

39-
These interfaces can be used with the various trigger and bindings supported by Durable Functions. When executing your Azure Functions, the functions runtime will run your function code with a concrete implementation of these interfaces. For unit testing, you can pass in a mocked version of these interfaces to test your business logic.
39+
These interfaces can be used with the various trigger and bindings supported by Durable Functions. While it is executing your Azure Functions, the functions runtime runs your function code with a concrete implementation of these interfaces. For unit testing, you can pass in a mocked version of these interfaces to test your business logic.
4040

4141
## Unit testing trigger functions
4242

43-
In this section, the unit test will validate the logic of the following HTTP trigger function for starting new orchestrations.
43+
In this section, the unit test validates the logic of the following HTTP trigger function for starting new orchestrations.
4444

4545
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/HttpStart.cs)]
4646

47-
The unit test task will be to verify the value of the `Retry-After` header provided in the response payload. So the unit test will mock some of `IDurableClient` methods to ensure predictable behavior.
47+
The unit test task verifies the value of the `Retry-After` header provided in the response payload. So the unit test mocks some of `IDurableClient` methods to ensure predictable behavior.
4848

4949
First, we use a mocking framework ([moq](https://github.com/moq/moq4) in this case) to mock `IDurableClient`:
5050

@@ -54,7 +54,7 @@ var durableClientMock = new Mock<IDurableClient>();
5454
```
5555

5656
> [!NOTE]
57-
> While you can mock interfaces by directly implementing the interface as a class, mocking frameworks simplify the process in various ways. For instance, if a new method is added to the interface across minor releases, moq will not require any code changes unlike concrete implementations.
57+
> While you can mock interfaces by directly implementing the interface as a class, mocking frameworks simplify the process in various ways. For instance, if a new method is added to the interface across minor releases, moq doesn't require any code changes unlike concrete implementations.
5858
5959
Then `StartNewAsync` method is mocked to return a well-known instance ID.
6060

@@ -117,39 +117,39 @@ Assert.NotNull(result.Headers.RetryAfter);
117117
Assert.Equal(TimeSpan.FromSeconds(10), result.Headers.RetryAfter.Delta);
118118
```
119119

120-
After combining all steps, the unit test will have the following code:
120+
After you combine all these steps, the unit test has the following code:
121121

122122
[!code-csharp[Main](~/samples-durable-functions/samples/VSSample.Tests/HttpStartTests.cs)]
123123

124124
## Unit testing orchestrator functions
125125

126126
Orchestrator functions are even more interesting for unit testing since they usually have a lot more business logic.
127127

128-
In this section the unit tests will validate the output of the `E1_HelloSequence` Orchestrator function:
128+
In this section, the unit tests validate the output of the `E1_HelloSequence` Orchestrator function:
129129

130130
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/HelloSequence.cs)]
131131

132-
The unit test code will start with creating a mock:
132+
The unit test code starts with creating a mock:
133133

134134
```csharp
135135
var durableOrchestrationContextMock = new Mock<IDurableOrchestrationContext>();
136136
```
137137

138-
Then the activity method calls will be mocked:
138+
Then the activity method calls are mocked:
139139

140140
```csharp
141141
durableOrchestrationContextMock.Setup(x => x.CallActivityAsync<string>("E1_SayHello", "Tokyo")).ReturnsAsync("Hello Tokyo!");
142142
durableOrchestrationContextMock.Setup(x => x.CallActivityAsync<string>("E1_SayHello", "Seattle")).ReturnsAsync("Hello Seattle!");
143143
durableOrchestrationContextMock.Setup(x => x.CallActivityAsync<string>("E1_SayHello", "London")).ReturnsAsync("Hello London!");
144144
```
145145

146-
Next the unit test will call `HelloSequence.Run` method:
146+
Next, the unit test calls the `HelloSequence.Run` method:
147147

148148
```csharp
149149
var result = await HelloSequence.Run(durableOrchestrationContextMock.Object);
150150
```
151151

152-
And finally the output will be validated:
152+
And finally the output is validated:
153153

154154
```csharp
155155
Assert.Equal(3, result.Count);
@@ -158,19 +158,19 @@ Assert.Equal("Hello Seattle!", result[1]);
158158
Assert.Equal("Hello London!", result[2]);
159159
```
160160

161-
After combining all steps, the unit test will have the following code:
161+
After you combine the previous steps, the unit test has the following code:
162162

163163
[!code-csharp[Main](~/samples-durable-functions/samples/VSSample.Tests/HelloSequenceOrchestratorTests.cs)]
164164

165165
## Unit testing activity functions
166166

167-
Activity functions can be unit tested in the same way as non-durable functions.
167+
Activity functions are unit tested in the same way as nondurable functions.
168168

169-
In this section the unit test will validate the behavior of the `E1_SayHello` Activity function:
169+
In this section the unit test validates the behavior of the `E1_SayHello` Activity function:
170170

171171
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/HelloSequence.cs)]
172172

173-
And the unit tests will verify the format of the output. The unit tests can use the parameter types directly or mock `IDurableActivityContext` class:
173+
And the unit tests verify the format of the output. These unit tests either use the parameter types directly or mock `IDurableActivityContext` class:
174174

175175
[!code-csharp[Main](~/samples-durable-functions/samples/VSSample.Tests/HelloSequenceActivityTests.cs)]
176176

articles/azure-functions/durable/quickstart-python-vscode.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,4 @@ If you no longer need the resources that you created to complete the quickstart,
242242
## Related content
243243

244244
* Learn about [common Durable Functions app patterns](durable-functions-overview.md#application-patterns).
245+
* Learn about [Unit Testing Durable Functions in Python](durable-functions-unit-testing-python.md)

articles/azure-functions/functions-reference-python.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,9 @@ class TestFunction(unittest.TestCase):
13441344

13451345
Inside your *.venv* Python virtual environment folder, install your favorite Python test framework, such as `pip install pytest`. Then run `pytest tests` to check the test result.
13461346

1347+
> [!NOTE]
1348+
> Durable Functions require special syntax for unit testing. For more information, refer to [Unit Testing Durable Functions in Python](durable/durable-functions-unit-testing-python.md)
1349+
13471350
::: zone-end
13481351

13491352
## Temporary files

0 commit comments

Comments
 (0)