Skip to content

Testing

The code that you write in the bricks is just Python. That means you can use your favorite tools as you would with any mainstream Python project.

Testing Bricks

By default, tests are added when creating a new component or base with the poly create command. This is optional and can be turned off in the Workspace configuration. The tests are added in a test folder at the root of the workspace with the same kind of folder structure as the bricks.

Example

Creating a new parser component. This will add a new brick to the components folder.

Poetry

poetry poly create component --name parser

Hatch

hatch run poly create component --name parser

PDM

pdm run poly create component --name parser

Rye

rye run poly create component --name parser

uv

uv run poly create component --name parser

A corresponding unit test will also be created in the test folder:

from my_top_namespace.parser import core


def test_sample():
    assert core is not None

Add the proper assertions to your tests during development of the bricks.

Running tests

Running Pytest from the workspace root:

Poetry

poetry run pytest

Hatch

hatch run pytest

PDM

pdm run pytest

Rye

rye run pytest

uv

uv run pytest

Running tests with pytest and the TDD Theme

This configuration ensures the entire namespace of your brick is included when pytest does it's test lookup. Without it, pytest will raise errors because of the default way it does module lookups. This occurs when using Polylith with the TDD theme.

[tool.pytest.ini_options]
addopts = [
    "--import-mode=importlib",
]

Running tests for changed code

The Python tools for the Polylith Architecture doesn't (yet) have a specific test command. You can use poly diff and your favorite test runner to only run the corresponding tests for changed code.

The diff command has support for displaying the changed bricks by using --bricks. Append the --short option for a scripting-friendly output.

You can use the output from the poly diff command to run specific tests. Storing a list of bricks in a bash variable:

Poetry

changes="$(poetry poly diff --bricks --short)"

Hatch

changes="$(hatch run poly diff --bricks --short)"

PDM

changes="$(pdm run poly diff --bricks --short)"

Rye

changes="$(rye run poly diff --bricks --short)"

uv

changes="$(uv run poly diff --bricks --short)"

To include bricks that use any of the changed bricks, you can add the --deps option. This will append any dependent bricks to the output.

By having tests in the same kind of structure as the bricks, you can use the output from the poly diff command to pick the tests to run. You can also name the individual test functions to include brick names, or use decorators (such as pytest markers).

Pytest

Transform the result of the poly diff command into a Pytest keyword or marker expression. (i.e. from hello,world,something to hello or world or something).

  • -k is for running tests by keyword expressions.
  • -m is for running tests by marker expressions.

Poetry

query="${changes//,/ or }"

poetry run pytest -k <<< echo "$query"

Hatch

query="${changes//,/ or }"

hatch run pytest -k <<< echo "$query"

PDM

query="${changes//,/ or }"

pdm run pytest -k <<< echo "$query"

Rye

query="${changes//,/ or }"

rye run pytest -k <<< echo "$query"

uv

query="${changes//,/ or }"

uv run pytest -k <<< echo "$query"

Manually testing and running services

The bases and components is plain Python, and the code can be run as you would if it were a single project repository. The bases are the entry points to your services and apps.

Example: running a FastAPI service locally

Start the service by specifying the namespace path to your entry point (i.e. the base).

uvicorn my_top_namespace.my_fastapi_service.core:app

It is also possible to test out project-specific entries that are defined in a pyproject.toml as you would in a mainstream Poetry project.