Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Testování částí je důležitou součástí moderních postupů vývoje softwaru. Testy jednotek ověřují chování obchodní logiky a chrání před zaváděním nepotřebných zásadních změn v budoucnu. Durable Functions se může snadno stát složitějšími, takže zavedení jednotkových testů pomáhá vyhnout se zásadním změnám v kódu. Následující části vysvětlují, jak testovat tři typy funkcí – klient orchestrace, orchestrátor a funkce entit.
Poznámka:
Tato příručka se vztahuje pouze na aplikace Durable Functions napsané v programovacím modelu Pythonu v2.
Požadavky
Příklady v tomto článku vyžadují znalost následujících konceptů a architektur:
- Testování jednotek
- Odolné funkce
- Testování jednotek v Pythonu
- unittest.mock
Nastavení testovacího prostředí
K otestování Durable Functions je důležité nastavit správné testovací prostředí. To zahrnuje vytvoření testovacího adresáře a instalaci modulu Pythonu unittest do prostředí Pythonu. Další informace najdete v přehledu testování jednotek v Pythonu ve službě Azure Functions.
Funkce triggeru testování jednotek
Aktivační funkce, často označované jako klientské funkce, inicializuje orchestrace a externí události. Testování těchto funkcí:
- Napodobujte
DurableOrchestrationClientsimulaci provádění orchestrace a správy stavu. - Přiřaďte
DurableOrchestrationClientmetody, jakostart_new,get_statusneboraise_eventpomocí napodobených funkcí, které vracejí očekávané hodnoty. - Vyvolejte klientskou funkci přímo pomocí napodobeného klienta a dalších nezbytných vstupů, jako je například
req(objekt požadavku HTTP) pro funkce klienta spuštěného HTTP triggerem. - Pomocí asercí a
unittest.mocknástrojů ověřte očekávané chování při spouštění orchestrace, parametry a HTTP odpovědi.
import asyncio
import unittest
import azure.functions as func
from unittest.mock import AsyncMock, Mock, patch
from function_app import start_orchestrator
class TestFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableOrchestrationClient')
def test_HttpStart(self, client):
# Get the original method definition as seen in the function_app.py file
func_call = http_start.build().get_user_function().client_function
req = func.HttpRequest(method='GET',
body=b'{}',
url='/api/my_second_function',
route_params={"functionName": "my_orchestrator"})
client.start_new = AsyncMock(return_value="instance_id")
client.create_check_status_response = Mock(return_value="check_status_response")
# Execute the function code
result = asyncio.run(func_call(req, client))
client.start_new.assert_called_once_with("my_orchestrator")
client.create_check_status_response.assert_called_once_with(req, "instance_id")
self.assertEqual(result, "check_status_response")
Funkce orchestrátoru jednotkového testování
Funkce orchestratoru spravují provádění více funkcí aktivit. Testování orchestrátoru:
- Napodobte
DurableOrchestrationContextpro řízení provádění funkce. - Nahraďte
DurableOrchestrationContextmetody potřebné pro provedení orchestrátoru, jakocall_activitynebocreate_timerpomocí mock funkcí. Tyto funkce obvykle vrátí objekty typu TaskBase sresultvlastností. - Zavolejte orchestrátor rekurzivně a předejte výsledek úlohy vygenerované předchozím příkazem výnosu na další.
- Ověřte výsledek orchestrátoru pomocí výsledků vrácených z orchestrátoru a
unittest.mock.
import unittest
from unittest.mock import Mock, patch, call
from datetime import timedelta
from azure.durable_functions.testing import orchestrator_generator_wrapper
from function_app import my_orchestrator
class TestFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableOrchestrationContext')
def test_chaining_orchestrator(self, context):
# Get the original method definition as seen in the function_app.py file
func_call = my_orchestrator.build().get_user_function().orchestrator_function
# The mock_activity method is defined above with behavior specific to your app.
# It returns a TaskBase object with the result expected from the activity call.
context.call_activity = Mock(side_effect=mock_activity)
# Create a generator using the method and mocked context
user_orchestrator = func_call(context)
# Use orchestrator_generator_wrapper to get the values from the generator.
# Processes the orchestrator in a way that is equivalent to the Durable replay logic
values = [val for val in orchestrator_generator_wrapper(user_orchestrator)]
expected_activity_calls = [call('say_hello', 'Tokyo'),
call('say_hello', 'Seattle'),
call('say_hello', 'London')]
self.assertEqual(context.call_activity.call_count, 3)
self.assertEqual(context.call_activity.call_args_list, expected_activity_calls)
self.assertEqual(values[3], ["Hello Tokyo!", "Hello Seattle!", "Hello London!"])
Jednotkové testování funkcí entit
Funkce entit spravují stavové objekty pomocí operací. Otestování funkce entity:
- Simulujte
DurableEntityContextk napodobení interního stavu entity a vstupů operací. - Nahraďte
DurableEntityContextmetody jakoget_state,set_stateaoperation_namemocky, které vracejí řízené hodnoty. - Vyvolejte funkci entity přímo pomocí simulovaného kontextu.
- S využitím asercí ověřujte změny stavu a vracené hodnoty spolu s nástroji
unittest.mock.
import unittest
from unittest.mock import Mock, patch
from function_app import Counter
class TestEntityFunction(unittest.TestCase):
@patch('azure.durable_functions.DurableEntityContext')
def test_entity_add_operation(self, context_mock):
# Get the original method definition as seen in function_app.py
func_call = Counter.build().get_user_function().entity_function
# Setup mock context behavior
state = 0
result = None
def set_state(new_state):
nonlocal state
state = new_state
def set_result(new_result):
nonlocal result
result = new_result
context_mock.get_state = Mock(return_value=state)
context_mock.set_state = Mock(side_effect=set_state)
context_mock.operation_name = "add"
context_mock.get_input = Mock(return_value=5)
context_mock.set_result = Mock(side_effect=lambda x: set_result)
# Call the entity function with the mocked context
func_call(context_mock)
# Verify the state was updated correctly
context_mock.set_state.assert_called_once_with(5)
self.assertEqual(state, 5)
self.assertEqual(result, None)
Funkce aktivit při jednotkovém testování
Funkce aktivit nevyžadují žádné specifické úpravy pro Durable k otestování. Pokyny uvedené v přehledu testování jednotek v Pythonu pro Azure Functions jsou dostatečné pro testování těchto funkcí.