---
title: "Diagnostic tests from the description"
---

# Diagnostic tests from the description

Generate UDS tests from the ECU's ODX, PDX or CDD into a documented file, review and edit it, regenerate it when the description changes, run it from the Testing view with the ECU-changing cases confirmed, and keep run records and reports.

**State:** modelled: generated from the UDS ECU simulator's PDX and CDD and run against the simulator on CAN and over DoIP; generated from 12 public PDX files and five CANdela demo files, with the state charts and preconditions read as odxtools reads them. Not run against a real ECU or a production description, and not compared with CANoe.DiVa.

## Generate the tests

Run **Generate Diagnostic Tests...** from the ECUs view's row menu, the context menu of a PDX, ODX or CDD file or its editor tab, or the Command Palette. It writes `<variant>.diagtests.json` where you choose, beside the description by default. The test file holds only what the description establishes:

- the ECU's session and security state charts and each service's preconditions and transitions (CANdela: the state groups);
- the baseline every case starts from, and how each session is reached;
- the timing (P2, P2* and tester present time of the variant's protocol). S3 is not in any description read, so `timing.s3Ms` is left for you, and the cases that need it skip until it is set;
- the negative response codes a refusal may carry.

| Kind | What it checks |
|---|---|
| session | Each reachable session is entered within P2 (and P2* per response pending); the P2 and P2* the ECU reports are not longer than the description's |
| read | Each readable data identifier decodes with no bytes left over and every value within its limits |
| refused | Each restricted service is refused, with one of the description's codes, where it may not run |
| unlock | Each security level unlocks with the ECU definition's seed-key source |
| routine | Each routine starts and its response decodes; results are requested where the description has the service |
| readDtcs | DTCs read by status mask 0xFF decode, are named by the description and match their status availability mask |
| clearDtcs, reset | A positive response |
| write | Each writable identifier is written with the value read and read back unchanged |
| testerPresent, sessionHold, sessionTimeout | Tester present is answered; a session is held by tester present; without requests it times out after S3 |

Routines, clearing, resets and writes are marked as changing the ECU. Everything not generated is listed in the file's `notGenerated` with the reason.

## Review, edit and regenerate

The test file is in the module's documented format, version 1, with a JSON schema. Its problems show in Problems at their place: an unknown setting, a request that is not hexadecimal bytes, two cases with one id, a file written for a later version, and a case that would change the ECU without `"changesEcu": true`. Set S3, leave a case out with `"skip": true`, or add cases of your own.

**Regenerate Diagnostic Tests** generates the tests again from the description, variant and ECU it names, opens a diff of the current and new text, and replaces the file only after you confirm, shown the description's new SHA-256 and the cases added, removed and changed. Your own cases, skips and S3 are kept.

## Run it

In the Testing view, **Diagnostic Tests** shows one item per test file, its cases grouped by what they test, each at its line in the file; the run profile is **Run on the ECU**.

- Running a test file or group runs every case that leaves the ECU as it is.
- A case that changes the ECU runs only when chosen itself, after one confirmation that names the ECU, its interface, the test file and its SHA-256, and every such case with its request.
- Each case shows passed, failed with the reason, errored, or skipped with the reason, what it established, and every request and response with its time; all are in the Operation Log too.
- Responses are decoded through the description, checked against the SHA-256 recorded in the test file.

![Diagnostic tests generated from the description, run from the Testing view with the request and response of each case.](https://neuralinverse.com/docs-images/modules/automotive/diagnostic-tests-run.webp)

## Keep the evidence

Every run writes a record into `build/diagnostic-tests/<name>/<start time>.json` of the test file's workspace folder: the test file, the descriptions with their SHA-256, the ECU and interface, the identification read before the cases, the tool's name, version and commit, the cases confirmed and each case's outcome, requests and responses. **Save Diagnostic Test Report...** writes the latest run's report (an HTML page, CSV tables, the record and a provenance file). Requirements Coverage takes each case's latest result, and **Link Test Case to Requirements...** links a case (see [Requirements coverage](https://neuralinverse.com/docs/modules/automotive/requirements/)).

Agents use `generateDiagnosticTests` (writes the test file after the chat's confirmation) and `runDiagnosticTests` (the ECU-changing cases only when named, confirmed every time).

**Not verified:** the response time is measured at the tester, through the bus host and interface, so on a busy machine it is longer than at the ECU. No public ODX description restricts a UDS service to sessions, so refusals in ODX rest on the simulator's description. The two agent tools were not invoked in the running Editor.
