During this exercise, you will
- Run a unit test provided for the
translate_term
Activity - Develop and run your own unit test for the
translate_term
Activity - Write assertions for a Workflow test
- Uncover, diagnose, and fix a bug in the Workflow Definition
- Observe the time-skipping feature in the Workflow test environment
Make your changes to the code in the practice
subdirectory (look for
TODO
comments that will guide you to where you should make changes to
the code). If you need a hint or want to verify your changes, look at
the complete version in the solution
subdirectory.
If you haven't already started the Translation Microservice used by this exercise, do so in a separate terminal.
Note: If you're using the Gitpod environment to run this exercise you can skip this step. An instance of the Microservice is already running in your environment
- Ensure that the virtual environment you setup at the beginning of the course is activated as detailed in the course README
- Navigate to the
utilities
directory at the root level of the course - Change directories into the
microservice
directorycd utilities/microservice
- Run the microservice
python microservice.py
We have provided a unit test for the translate_term
Activity
to get you started. This test verifies that the Activity correctly
translates the term "Hello" to German. Take a moment to study the
test, which you'll find in the test_activities.py
file in the tests
directory.
Since the test runs the Activity, which in turn calls the microservice to do
the translation, you'll begin by starting that.
- Run the
python -m pytest
command to execute the provided test
In the previous step you verified that running translate_term
for Hello was
invoking properly. Now it is time to test if Goodbye is also working.
- Edit the
test/test_activities.py
file - Copy the tuple in the
pytest.mark.parametrize
list and paste it into the list, effectively creating a second entry to test the method on. - Change the term for the
TranslationActivityInput
object in this second tuple fromHello
toGoodbye
- Change the language code for the
TranslationActivityInput
object in this second tuple fromde
(German) tolv
(Latvian) - Change the translation for the
TranslationActivityOutput
object in this second tuple fromHallo
toArdievu
- Run the
python -m pytest
command to verify that the method was tested twice and that the test completed successfully.
In addition to verifying that your code behaves correctly when used as you intended, it is sometimes also helpful to verify its behavior with unexpected input. The example below does this, testing that the Activity returns the appropriate error when called with an invalid language code.
@pytest.mark.asyncio
async def test_failed_translate_activity_bad_language_code():
with pytest.raises(Exception) as e:
input = TranslationActivityInput("goodbye", "xq")
async with aiohttp.ClientSession() as session:
activity_environment = ActivityEnvironment()
activities = TranslationActivities(session)
await activity_environment.run(activities.translate_term, input)
assert "Invalid language code" in str(e)
Take a moment to study this code, and then continue with the following steps:
- Edit the
test_activities.py
file - Copy the entire
test_failed_translate_activity_bad_language_code
function provided above and paste it at the bottom of thetest_activities.py
file - Save the changes
- Run
python -m pytest
again to run this new test, in addition to the others
- Edit the
tests/test_workflow.py
file - Add assertions for the following conditions
- The
hello_message
field in the result isBonjour, Pierre
- The
goodbye_message
field in the result isAu revoir, Pierre
- The
- Save your changes
- Run
python -m pytest
. This will fail, due to a bug in the Workflow Definition. - Find and fix the bug in the Workflow Definition
- Run the
python -m pytest
command again to verify that you fixed the bug
There are two things to note about this test.
First, the test completes in under a second, even though the Workflow
Definition contains a await asyncio.sleep(15)
call that adds a 15-second delay
to the Workflow Execution. This is because of the time-skipping feature
provided by the test environment.
Second, calls to RegisterActivity
near the top of the test indicate
that the Activity Definitions are executed as part of this Workflow
test. As you learned, you can test your Workflow Definition in isolation
from the Activity implementations by using mocks. The optional exercise
that follows provides an opportunity to try this for yourself.
If you have time and would like an additional challenge, continue with the following steps.
- Make a copy of the existing Workflow Test by running
cp tests/test_workflow.py tests/test_workflow_with_mocks.py
- Edit the
test_workflow_with_mocks.py
file - Add the following imports
from temporalio import activity from shared import ( TranslationWorkflowInput, TranslationActivityInput, TranslationActivityOutput, )
- Create a new async function to mock your Activity.
- Name it
translate_term_mocked_french
and decorate it with@activity.defn(name="translate_term")
. The function should takeTranslationActivityInput
- In the body of your new mocked Activity, write an if statement that returns
a new
TranslationActivityOutput
object containingBonjour
if the term that was passed in via theTranslationActivityInput
washello
. Otherwise return a newTranslationActivityObject
containingAu revoir
. - The full mocked Activity is shown below:
@activity.defn(name="translate_term") async def translate_term_mocked_french(input: TranslationActivityInput): if input.term == "hello": return TranslationActivityOutput("Bonjour") else: return TranslationActivityOutput("Au revoir")
- Name it
- Delete the context manager and the creation of a
TranslationActivites
object, these are now unnecessary due to the use of a mocked Activity.Once deleted realign your Python code properly now that a scope has been removed.async with aiohttp.ClientSession() as session: activities = TranslationActivities(session)
- In the Worker creation, replace the statement
activities=[activities.translate_term],
withactivities=[translate_term_mocked_french],
- Save your changes
- Run
python -m pytest
to run the tests