Skip to main content

Test & simulation toolkit for German market-communication (MaKo) platforms

Project description

makotest

Test & simulation toolkit for German market-communication (MaKo) platforms.

Generates regulator-conformant inputs — EDIFACT, EPEX price curves, meter data — simulates the external counterparties a MaKo platform talks to, and asserts on the result.

makotest targets mako first but is not mako-specific: everything it drives is a public wire contract (EDIFACT over AS4, REST, CloudEvents), so it can exercise any MaKo implementation.

from makotest import malo_from_base, add_werktage, validate_edifact

malo_from_base("5123869678")      # '51238696780' — BDEW check digit applied
add_werktage("2026-12-24", 2)     # '2026-12-29' — skips holidays and the weekend

report = validate_edifact(utilmd_bytes, "2026-10-01")
report.is_valid                   # MIG + AHB + semantic rules, on that FV

Why

The regulated domain makes this sharper than ordinary integration testing: deadlines are legal obligations, message content is defined by AHB rule tables, and a wrong Prüfidentifikator is a compliance defect rather than a bug. Tests need to express "this is what the counterparty is entitled to send, and this is what we owe them by when" — which a curl script cannot.

Design

One source of truth for wire formats. EDIFACT validation, identifier check digits and the Werktag calendar come from the same Rust crates the platform runs, through PyO3 bindings. They are never reimplemented in Python: a second implementation would drift from the BDEW profiles at the first Formatumstellung, and a harness that disagrees with production about validity is worse than none.

The rule for what goes where: anything a regulator defines in a table is Rust; anything shaped by test ergonomics is Python.

Concern Home
EDIFACT MIG/AHB/semantic validation Rust (edi-energy)
MaLo/MeLo check digits and formats Rust (rubo4e)
Werktag / Feiertag calendar Rust (mako-engine::fristen)
EPEX curves, load profiles Python
Counterparty behaviour, fixtures, DSL Python

A consequence worth stating: because validation runs the platform's own AHB engine, makotest proves process and integration behaviour — it is not an independent check of mako's format conformance. The BDEW reference examples remain the authority for that.

Deterministic by construction. Every generator takes a seed; every clock is injected. A test that passes on Tuesday and fails on a Feiertag is not a test of the system.

Framework-agnostic core, pytest on top. The generators and simulators are plain objects usable from a script or a notebook. Only makotest.plugin imports pytest, so a demo and a CI test drive the same code path.


Building EDIFACT

makotest builds messages through the same Rust builders the platform uses, so a message it constructs is one the platform would accept.

from makotest import UtilmdTransaction, build_utilmd, build_interchange

msg = build_utilmd(
    pruefidentifikator=55001,
    sender="4012345000023",
    receiver="9900357000004",
    release="S2.1",
    document_date="20251101",
    transactions=[
        UtilmdTransaction(
            object_type="melo",
            object_id="DE00014559929E00856996N5139699L01",
            process_dates=[("163", "20251101")],   # delivery start
            references=[("Z13", "55001")],
        )
    ],
)

build_utilmd and build_mscons return a message (UNHUNT). That is not sendable on its own — the wire unit a market partner receives is an interchange:

wire = build_interchange(
    sender="4012345000023",
    receiver="9900357000004",
    dar="REF001",
    messages=[msg],
    date="260802", time="0915",
)
# UNB+UNOC:3+4012345000023:14+9900357000004:500+260802:0915+REF001'...UNZ+1+REF001'

Building and validation are deliberately separate steps: a test must be able to construct a knowingly-invalid message and assert that the right rule rejects it. Pass the result to assert_edifact_valid when you want the happy path.

Install

pip install makotest                  # core: identifiers, Fristen, EDIFACT
pip install 'makotest[data]'          # + EPEX / Lastgang generators (numpy, pandas)
pip install 'makotest[bo4e]'          # + BO4E business objects
pip install 'makotest[hypothesis]'    # + property-based strategies

pytest usage

The plugin registers itself through the pytest11 entry point — no conftest.py wiring needed.

def test_frist_is_met(frozen_clock, epex_sim):
    frozen_clock.advance_werktage(4)     # BDEW calendar, not naive +4 days
    assert frozen_clock.date == "2026-11-09"

Fixtures: epex_sim, frozen_clock, makotest_seed, mako_endpoint. Markers: @pytest.mark.regulatory("GPKE Teil 2"), @pytest.mark.requires_docker. Options: --mako-endpoint URL (run against a live deployment), --makotest-seed N (reproduce a failing run exactly).

BO4E generation

makotest builds business objects from BO4E 202607 — the same release mako's rubo4e generates from. Assert it once per session; testing v202607 objects against a platform on another generation produces passes that mean nothing:

from makotest.assertions import assert_bo4e_generation_matches
assert_bo4e_generation_matches(platform.bo4e_version)

Development

makotest is a member of the mako Cargo workspace and builds with maturin:

cd makotest
maturin develop --extras dev
pytest

pyo3/extension-module is deliberately not a Cargo feature of this crate — maturin enables it at build time. Declaring it would make cargo test --workspace --all-features link the test harness against it and fail on undefined Python symbols.

Design rationale and the roadmap for the simulator suite (market partner over AS4, BIKO, iMSys/SMGW) live in concepts/MAKOTEST.md.

Status

Pre-1.0 and incomplete. Shipping today: the Rust core (identifiers, Fristen, EDIFACT build + interchange envelope + validation), the EPEX generator, domain assertions, and the pytest plugin. The counterparty simulators are specified but not yet built.

The package version tracks workspace.package.version through Cargo.toml (dynamic = ["version"]), so the wheel and the crates it binds can never report different versions.

Licence

MIT OR Apache-2.0, matching mako.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

makotest-0.15.0.tar.gz (936.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

makotest-0.15.0-cp311-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.11+Windows x86-64

makotest-0.15.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

makotest-0.15.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

makotest-0.15.0-cp311-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

makotest-0.15.0-cp311-abi3-macosx_10_12_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file makotest-0.15.0.tar.gz.

File metadata

  • Download URL: makotest-0.15.0.tar.gz
  • Upload date:
  • Size: 936.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for makotest-0.15.0.tar.gz
Algorithm Hash digest
SHA256 3584aac9ba236af51203d1fef76fbc963804e75e54122bba51512361f7585aba
MD5 a74c03560533db9871253727d8cc32aa
BLAKE2b-256 da786e17a48963e1aaf17fcd9f837eadf1915ee7e405d0f0d3c037ece95afea3

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0.tar.gz:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file makotest-0.15.0-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: makotest-0.15.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for makotest-0.15.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7adc4f64f3433bcac9802ed60ebafaf27dcc476d7af11c71b7974df491762d50
MD5 83a555e7bacb15f5b769936e21ea8955
BLAKE2b-256 f02737054695829c9a7d025532c917e1311b59b381121b827eb4b8a1cd9f51f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0-cp311-abi3-win_amd64.whl:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file makotest-0.15.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for makotest-0.15.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2012f610edd9640c0b46b08f3f631615676132a677804191abe024bf39cb6962
MD5 f0d23a1087492a301b1787bc914a22c1
BLAKE2b-256 9c5002b2fbe268bac42bd245049ef772ba7efe0629d3f1b0f8eb925d0fbde878

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file makotest-0.15.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for makotest-0.15.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ffb432f7a40a69e9ca35b0b1a83658431927e9b443117ad704c967c1f886531b
MD5 cae919d8874ae9440e7b6ff99b173c45
BLAKE2b-256 dfa64b5015730c369ab67d7e5a03f4ea2df4236649c59b7068bedc67c3562117

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file makotest-0.15.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for makotest-0.15.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cfc53a6441666d7ee70eeafe3998c3595dbdb77469fdc8942d6dface19d450d1
MD5 284059f01126775b8e7293a49a880b32
BLAKE2b-256 6d51dcdc7daae824b204e5936d8fa93ae0fc7ab75848ba3a12e8fafa3f3efffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file makotest-0.15.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for makotest-0.15.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 50df89818a18382cab582e45e88db5f34c07320c76915785a043774231fcaccc
MD5 fd4019fe684b1e2fce690cec812a36e7
BLAKE2b-256 75fa56787ee51c8aa45e63ca969cac47c8d02a2fc367746e85af6b818f9472cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for makotest-0.15.0-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on hupe1980/mako

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page