Free, open-source Python UDS (ISO 14229) client, ECU simulator, and campaign runner. No hardware. No CAN interface. No commercial diagnostic tool required.
pipx run --spec xaloqi-tester xaloqi-sim --demo
That's it. The command starts an in-process simulated ECU and runs a real UDS conversation against it: session control, VIN read, AES-CMAC SecurityAccess unlock, a security-gated DID read, DTC read — the same protocol traffic a real bench would see.
Or install it:
pip install xaloqi-tester
xaloqi-sim --demo
Build diagnostics? → Xaloqi EDS — generate production UDS implementations for Zephyr and FreeRTOS. Test diagnostics? You're in the right place.

Recorded from the actual published package — not a mockup. Command and output are real; only the reveal pacing of the (near-instantaneous) result lines was adjusted for legibility.
Exercising UDS normally means an ECU on the bench, a CAN interface, a diagnostic tool, and hand-maintained test scripts. TestLab Core gives you a test environment before any of that exists:
your test campaign (YAML)
│
▼
┌────────────────┐
│ TestLab Core │
│ UDS client │
│ campaign runner│
│ ECU simulator │
└────────┬────────┘
│
▼
virtual ECU
— no hardware —
The same campaign YAML runs against the simulator locally and in CI, then against real hardware unmodified once you add Xaloqi TestLab Pro.
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual --json reports/run.json
testlab analyze --results reports/run.json
campaigns/*.yaml define test jobs — session control, SecurityAccess,
DID/memory read-write, DTC handling, firmware transfer, expected NRCs,
variable capture/interpolation — as data, not code. --virtual runs them
against the built-in simulator.
xaloqi.tester.UdsTester) — async and sync, all major UDS
services including 0x27 SecurityAccess (AES-CMAC) and the
0x34/0x35/0x36/0x37 firmware up/download sequence. ISO-TP multi-frame
sends honour the ECU's real Flow Control: BlockSize, STmin (both the
millisecond and the 100–900us encodings), WAIT with a bounded WFTmax,
and OVERFLOW.xaloqi.sim, also the xaloqi-sim command).testlab-run) — 20 UDS actions, expect_nrc,
variable capture/interpolation, JSON output (schema shared with the
Xaloqi EDS diagnostics stack, so the same result format works with
either).testlab analyze — terminal summary of a run's JSON results.Core is licensed under Apache-2.0 — use it for learning UDS, local diagnostic development, virtual ECU testing, campaign development, automated CI validation, and building your own integrations.
If you are doing UDS in Python, you have almost certainly found the established stack: python-can (the CAN bus layer) + can-isotp (ISO 15765-2 transport) + udsoncan (the ISO 14229 client). They are good, mature libraries and this project does not try to replace them.
They answer a different question. That stack is a client — it speaks UDS to an ECU that already exists. TestLab Core is a test harness — a campaign runner plus an ECU that answers, so you can write and run tests before any hardware does.
| udsoncan + python-can + can-isotp | TestLab Core | |
|---|---|---|
| What it is | UDS client library stack | Campaign runner + simulated ECU |
| Something that answers you | Needs a real ECU. FakeConnection replays a 2-entry static dict — enough to smoke-test your own plumbing, not an ECU | Stateful simulator: sessions, SecurityAccess seed/key (AES-CMAC), DTCs, NRCs |
| Real CAN / DoIP hardware | Yes, free — socketcan, J2534, and every python-can interface | Not in core. Core is virtual-transport only; real transports are Pro |
| Raw UDS service coverage | Broader — 27 services, 91 client methods, incl. the full ReadDTCInformation subfunction set, 0x29 Authentication, DynamicallyDefineDataIdentifier | Focused on the ~20 actions a validation campaign uses |
| How you express a test | Write Python | Declarative YAML campaign |
| Pass/fail + timing report | Build it yourself | Built in (testlab-run, testlab analyze, JSON out) |
| Time to first result | A CAN interface and an ECU — or write your own responder | pip install xaloqi-tester && xaloqi-sim --demo |
| License | MIT (udsoncan, can-isotp), LGPL-3.0-only (python-can) | Apache-2.0 |
ResponseOnEvent, RequestFileTransfer, the deeper
ReadDTCInformation subfunctions, LinkControl.They also compose. Nothing stops you developing campaigns against the simulator here and driving real hardware with udsoncan — the JSON result schema is documented, and the same campaign YAML runs unmodified on real transports if you later move to Pro.
Comparison verified 2026-09-04 against udsoncan 1.26.1, python-can 4.6.1, can-isotp 2.0.7 and xaloqi-tester 1.5.2, by installing each from PyPI and inspecting the actual APIs — not from documentation. If something here is out of date or wrong, open an issue and it will be corrected.
A virtual ECU is useful in CI precisely because the test doesn't depend on a bench being available. A minimal GitHub Actions job:
name: UDS tests
on: [push, pull_request]
jobs:
uds:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install xaloqi-tester
- run: |
mkdir -p reports
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual --json reports/run.json
- run: testlab analyze --results reports/run.json
Repeatable diagnostic tests on every push and pull request, no ECU hardware allocated to the CI runner.
| Recipe | What you'll prove | Hardware |
|---|---|---|
| SecurityAccess | Protected resources stay locked until UDS 0x27 unlock | None |
| GitHub Actions | Run UDS regression tests on every PR | None |
| Negative responses | Assert the ECU rejects what it should, with the right NRC | None |
| DTCs | Read, clear and re-read Diagnostic Trouble Codes (0x19 / 0x14) | None |
| Firmware download | Exercise the 0x34 → 0x36 → 0x37 programming flow | None |
| DoIP | Move the same UDS testing model to Automotive Ethernet | DoIP endpoint (Pro) for real-network testing |
Start here: pipx run --spec xaloqi-tester xaloqi-sim --demo
Every recipe above is run and verified against the real published package before being committed — not just described.
The bundled config and campaigns are meant to be changed, not just run:
examples/diagnostics_config.yaml
campaigns/standalone_validation.yaml
campaigns/basic_validation.yaml
testlab_config.yaml
Run the bundled campaign first:
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual
Then fork this repository and adapt it to your own ECU: change a DID or expected value, add an expected NRC, add another diagnostic step, run it locally, then put it in CI. If you build a useful campaign for a common ECU workflow, contributions are welcome.
Xaloqi Compatibility Tests
runs the same UDS campaign against every combination of transport (CAN,
DoIP) and RTOS (Zephyr, FreeRTOS) Xaloqi EDS ships examples for, using
xaloqi-tester's Python client against EDS's C runtime — a genuine
cross-language, cross-implementation check, not two halves of one
codebase validating each other. Honestly: the virtual-ECU check
there is green and reproducible by anyone with no license; the
real-transport matrix is still being wired up (tracked openly at
xaloqi-compatibility-tests#2,
including EDS#230 — EDS's own
DoIP Integration CI job currently skips this exact check rather than
proving it).
TestLab is the test side of the Xaloqi workflow. Xaloqi EDS is the build side — generate production ISO 14229 diagnostics for Zephyr and FreeRTOS from YAML.
diagnostics_config.yaml
│
▼
┌──────────────┐
│ Xaloqi EDS │ BUILD
└──────┬───────┘
│ generated ECU diagnostics
▼
┌──────────────┐
│ TestLab │ TEST
└──────────────┘
│
▼
virtual ECU / CI / real hardware
Need to implement ISO 14229 diagnostics on Zephyr or FreeRTOS? → Xaloqi EDS. Already have an ECU and need to test it? Stay here.
Real transports (SocketCAN, PCAN/Kvaser, DoIP, SOME/IP), the SOVD client,
multi-ECU workspace mode, RTOS comparison, HTML reports/trends/dashboard,
and AI-assisted failure analysis are part of
Xaloqi TestLab Pro — installed as an additional wheel
alongside this package. Core discovers Pro automatically through Python
entry points: install Pro and every testlab command and campaign action
above works unchanged, plus the paid ones. Without Pro installed, a paid
transport, action, or subcommand fails with one clear message telling you
what it needs.
git clone https://github.com/Xaloqi/xaloqi-testlab-core
cd xaloqi-testlab-core
pip install -e ".[dev]"
XALOQI_LICENSE_SKIP=1 pytest tests/ -v
Automotive ECUs, software-defined vehicles, battery management systems, motor controllers, gateways, embedded controllers, diagnostic bootloaders, Zephyr or FreeRTOS projects, CI pipelines for embedded software — and learning ISO 14229 without buying hardware first.
See CONTRIBUTING.md. If you've built something with TestLab, opening a discussion or linking your project helps us understand which workflows deserve more attention. Found a security issue? See SECURITY.md — please don't open a public issue for it.
Apache License 2.0 — see LICENSE.
If TestLab saved you from setting up a bench just to exercise a UDS flow, consider starring the repository. More usefully: fork it, change a campaign, and make it test your ECU.
Build diagnostics: Xaloqi EDS · Test diagnostics: Xaloqi TestLab Core · Commercial tooling: xaloqi.com
18 commits
Python
100.0%
Free, open-source Python UDS (ISO 14229) client, ECU simulator, and campaign runner. No hardware. No CAN interface. No commercial diagnostic tool required.
pipx run --spec xaloqi-tester xaloqi-sim --demo
That's it. The command starts an in-process simulated ECU and runs a real UDS conversation against it: session control, VIN read, AES-CMAC SecurityAccess unlock, a security-gated DID read, DTC read — the same protocol traffic a real bench would see.
Or install it:
pip install xaloqi-tester
xaloqi-sim --demo
Build diagnostics? → Xaloqi EDS — generate production UDS implementations for Zephyr and FreeRTOS. Test diagnostics? You're in the right place.

Recorded from the actual published package — not a mockup. Command and output are real; only the reveal pacing of the (near-instantaneous) result lines was adjusted for legibility.
Exercising UDS normally means an ECU on the bench, a CAN interface, a diagnostic tool, and hand-maintained test scripts. TestLab Core gives you a test environment before any of that exists:
your test campaign (YAML)
│
▼
┌────────────────┐
│ TestLab Core │
│ UDS client │
│ campaign runner│
│ ECU simulator │
└────────┬────────┘
│
▼
virtual ECU
— no hardware —
The same campaign YAML runs against the simulator locally and in CI, then against real hardware unmodified once you add Xaloqi TestLab Pro.
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual --json reports/run.json
testlab analyze --results reports/run.json
campaigns/*.yaml define test jobs — session control, SecurityAccess,
DID/memory read-write, DTC handling, firmware transfer, expected NRCs,
variable capture/interpolation — as data, not code. --virtual runs them
against the built-in simulator.
xaloqi.tester.UdsTester) — async and sync, all major UDS
services including 0x27 SecurityAccess (AES-CMAC) and the
0x34/0x35/0x36/0x37 firmware up/download sequence. ISO-TP multi-frame
sends honour the ECU's real Flow Control: BlockSize, STmin (both the
millisecond and the 100–900us encodings), WAIT with a bounded WFTmax,
and OVERFLOW.xaloqi.sim, also the xaloqi-sim command).testlab-run) — 20 UDS actions, expect_nrc,
variable capture/interpolation, JSON output (schema shared with the
Xaloqi EDS diagnostics stack, so the same result format works with
either).testlab analyze — terminal summary of a run's JSON results.Core is licensed under Apache-2.0 — use it for learning UDS, local diagnostic development, virtual ECU testing, campaign development, automated CI validation, and building your own integrations.
If you are doing UDS in Python, you have almost certainly found the established stack: python-can (the CAN bus layer) + can-isotp (ISO 15765-2 transport) + udsoncan (the ISO 14229 client). They are good, mature libraries and this project does not try to replace them.
They answer a different question. That stack is a client — it speaks UDS to an ECU that already exists. TestLab Core is a test harness — a campaign runner plus an ECU that answers, so you can write and run tests before any hardware does.
| udsoncan + python-can + can-isotp | TestLab Core | |
|---|---|---|
| What it is | UDS client library stack | Campaign runner + simulated ECU |
| Something that answers you | Needs a real ECU. FakeConnection replays a 2-entry static dict — enough to smoke-test your own plumbing, not an ECU | Stateful simulator: sessions, SecurityAccess seed/key (AES-CMAC), DTCs, NRCs |
| Real CAN / DoIP hardware | Yes, free — socketcan, J2534, and every python-can interface | Not in core. Core is virtual-transport only; real transports are Pro |
| Raw UDS service coverage | Broader — 27 services, 91 client methods, incl. the full ReadDTCInformation subfunction set, 0x29 Authentication, DynamicallyDefineDataIdentifier | Focused on the ~20 actions a validation campaign uses |
| How you express a test | Write Python | Declarative YAML campaign |
| Pass/fail + timing report | Build it yourself | Built in (testlab-run, testlab analyze, JSON out) |
| Time to first result | A CAN interface and an ECU — or write your own responder | pip install xaloqi-tester && xaloqi-sim --demo |
| License | MIT (udsoncan, can-isotp), LGPL-3.0-only (python-can) | Apache-2.0 |
ResponseOnEvent, RequestFileTransfer, the deeper
ReadDTCInformation subfunctions, LinkControl.They also compose. Nothing stops you developing campaigns against the simulator here and driving real hardware with udsoncan — the JSON result schema is documented, and the same campaign YAML runs unmodified on real transports if you later move to Pro.
Comparison verified 2026-09-04 against udsoncan 1.26.1, python-can 4.6.1, can-isotp 2.0.7 and xaloqi-tester 1.5.2, by installing each from PyPI and inspecting the actual APIs — not from documentation. If something here is out of date or wrong, open an issue and it will be corrected.
A virtual ECU is useful in CI precisely because the test doesn't depend on a bench being available. A minimal GitHub Actions job:
name: UDS tests
on: [push, pull_request]
jobs:
uds:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install xaloqi-tester
- run: |
mkdir -p reports
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual --json reports/run.json
- run: testlab analyze --results reports/run.json
Repeatable diagnostic tests on every push and pull request, no ECU hardware allocated to the CI runner.
| Recipe | What you'll prove | Hardware |
|---|---|---|
| SecurityAccess | Protected resources stay locked until UDS 0x27 unlock | None |
| GitHub Actions | Run UDS regression tests on every PR | None |
| Negative responses | Assert the ECU rejects what it should, with the right NRC | None |
| DTCs | Read, clear and re-read Diagnostic Trouble Codes (0x19 / 0x14) | None |
| Firmware download | Exercise the 0x34 → 0x36 → 0x37 programming flow | None |
| DoIP | Move the same UDS testing model to Automotive Ethernet | DoIP endpoint (Pro) for real-network testing |
Start here: pipx run --spec xaloqi-tester xaloqi-sim --demo
Every recipe above is run and verified against the real published package before being committed — not just described.
The bundled config and campaigns are meant to be changed, not just run:
examples/diagnostics_config.yaml
campaigns/standalone_validation.yaml
campaigns/basic_validation.yaml
testlab_config.yaml
Run the bundled campaign first:
testlab-run --config testlab_config.yaml \
--campaign campaigns/standalone_validation.yaml \
--job basic_validation --virtual
Then fork this repository and adapt it to your own ECU: change a DID or expected value, add an expected NRC, add another diagnostic step, run it locally, then put it in CI. If you build a useful campaign for a common ECU workflow, contributions are welcome.
Xaloqi Compatibility Tests
runs the same UDS campaign against every combination of transport (CAN,
DoIP) and RTOS (Zephyr, FreeRTOS) Xaloqi EDS ships examples for, using
xaloqi-tester's Python client against EDS's C runtime — a genuine
cross-language, cross-implementation check, not two halves of one
codebase validating each other. Honestly: the virtual-ECU check
there is green and reproducible by anyone with no license; the
real-transport matrix is still being wired up (tracked openly at
xaloqi-compatibility-tests#2,
including EDS#230 — EDS's own
DoIP Integration CI job currently skips this exact check rather than
proving it).
TestLab is the test side of the Xaloqi workflow. Xaloqi EDS is the build side — generate production ISO 14229 diagnostics for Zephyr and FreeRTOS from YAML.
diagnostics_config.yaml
│
▼
┌──────────────┐
│ Xaloqi EDS │ BUILD
└──────┬───────┘
│ generated ECU diagnostics
▼
┌──────────────┐
│ TestLab │ TEST
└──────────────┘
│
▼
virtual ECU / CI / real hardware
Need to implement ISO 14229 diagnostics on Zephyr or FreeRTOS? → Xaloqi EDS. Already have an ECU and need to test it? Stay here.
Real transports (SocketCAN, PCAN/Kvaser, DoIP, SOME/IP), the SOVD client,
multi-ECU workspace mode, RTOS comparison, HTML reports/trends/dashboard,
and AI-assisted failure analysis are part of
Xaloqi TestLab Pro — installed as an additional wheel
alongside this package. Core discovers Pro automatically through Python
entry points: install Pro and every testlab command and campaign action
above works unchanged, plus the paid ones. Without Pro installed, a paid
transport, action, or subcommand fails with one clear message telling you
what it needs.
git clone https://github.com/Xaloqi/xaloqi-testlab-core
cd xaloqi-testlab-core
pip install -e ".[dev]"
XALOQI_LICENSE_SKIP=1 pytest tests/ -v
Automotive ECUs, software-defined vehicles, battery management systems, motor controllers, gateways, embedded controllers, diagnostic bootloaders, Zephyr or FreeRTOS projects, CI pipelines for embedded software — and learning ISO 14229 without buying hardware first.
See CONTRIBUTING.md. If you've built something with TestLab, opening a discussion or linking your project helps us understand which workflows deserve more attention. Found a security issue? See SECURITY.md — please don't open a public issue for it.
Apache License 2.0 — see LICENSE.
If TestLab saved you from setting up a bench just to exercise a UDS flow, consider starring the repository. More usefully: fork it, change a campaign, and make it test your ECU.
Build diagnostics: Xaloqi EDS · Test diagnostics: Xaloqi TestLab Core · Commercial tooling: xaloqi.com
18 commits
Python
100.0%