Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 62 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,66 @@ critical:
protected: true # pseudotest-update will never modify this match
```

### Avoiding repetition with scopes

Two scope mechanisms reduce duplication across a test config.

**Execution scope** - `Executable`, `InputMethod`, and `RenameTo` set at the top level act as defaults for every input. Per-input blocks override them selectively:

```yaml
# Without top-level defaults (repetitive)
Inputs:
case_01.in:
InputMethod: stdin
Matches: ...
case_02.in:
InputMethod: stdin
Matches: ...

# With a top-level default
InputMethod: stdin # inherited by all inputs unless overridden
Inputs:
case_01.in:
Matches: ...
case_02.in:
Matches: ...
```

**Match scope** - a named match group passes its parameters (such as `file:` and `tol:`) down to every child match, avoiding repetition when the same parameters are used for many checks. For example, checks that target the same file can be written in two ways:

```yaml
# Without grouping (repetitive)
Matches:
energy:
file: results.txt
grep: "Energy:"
field: 2
value: -42.5
tol: 1e-4
force:
file: results.txt
grep: "Force:"
field: 2
value: -0.001
tol: 1e-4

# With a match group
Matches:
results: # group — file: and tol: are inherited by all children
file: results.txt
tol: 1e-4
energy:
grep: "Energy:"
field: 2
value: -42.5
force:
grep: "Force:"
field: 2
value: -0.001
```

Groups can nest to any depth and share any match parameter (`file:`, `grep:`, `tol:`, `directory:`, etc.).

## MPI support

Set `MPIEXEC` to your MPI launcher to enable parallel execution:
Expand Down Expand Up @@ -289,12 +349,9 @@ exit_code = runner.run(

## Documentation

Detailed MkDocs-ready guides are in `docs/`:

- `docs/user-guide.md` — full feature reference with examples
- `docs/developer-guide.md` — architecture, adding match types, internals
Full documentation is available at **https://micaeljtoliveira.github.io/pseudotest/**.

Run locally:
The MkDocs source lives in `docs/`. To build and serve locally:

```bash
pip install -e .[docs]
Expand Down
126 changes: 126 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,132 @@ Top-level keys (`Executable`, `InputMethod`, `RenameTo`) act as defaults and can

Paths in `ExtraFiles` are resolved relative to the directory containing the YAML test file. All files are copied flat into the temporary working directory before the executable runs.

## Avoiding repetition

Two scope mechanisms let you factor out shared settings so they don't have to be repeated for every input or every match.

### Execution scope

`Executable`, `InputMethod`, and `RenameTo` placed at the top level act as defaults for every input. Any per-input block can override them individually:

```yaml
# Without top-level defaults — InputMethod is repeated for every input
Name: Solver tests
Executable: solver.x
Inputs:
case_01.in:
InputMethod: stdin
Matches: ...
case_02.in:
InputMethod: stdin
Matches: ...
case_03.in:
InputMethod: stdin
Matches: ...

# With a top-level default — InputMethod is written once
Name: Solver tests
Executable: solver.x
InputMethod: stdin # inherited by all inputs
Inputs:
case_01.in:
Matches: ...
case_02.in:
Matches: ...
case_03.in:
InputMethod: argument # override for this input only
Matches: ...
```

Similarly for `RenameTo` when using `InputMethod: rename`, define it once at the top level and only override it in the rare input that needs a different name.

### Match scope

A named match can act as a **group** by containing child matches alongside shared parameters. Any recognised parameter placed directly in the group, such as `file:`, `grep:`, `tol:`, or `directory:`, is automatically inherited by every child match, so it only needs to be written once:

```yaml
# Without grouping — file: and tol: are repeated for every match
Matches:
energy:
file: results.txt
grep: "Total energy:"
field: 3
value: -42.5000
tol: 1e-4
force_x:
file: results.txt
grep: "Force x:"
field: 2
value: -0.00123
tol: 1e-4
force_y:
file: results.txt
grep: "Force y:"
field: 2
value: 0.00045
tol: 1e-4

# With a match group — file: and tol: are written once
Matches:
results: # group: shared parameters for all children
file: results.txt
tol: 1e-4
energy:
grep: "Total energy:"
field: 3
value: -42.5000
force_x:
grep: "Force x:"
field: 2
value: -0.00123
force_y:
grep: "Force y:"
field: 2
value: 0.00045
```

A child match can override an inherited parameter by defining it locally as the child's value takes precedence:

```yaml
Matches:
results:
file: results.txt
tol: 1e-4
energy:
grep: "Total energy:"
field: 3
value: -42.5000
checksum:
file: checksums.txt # overrides the group's file:
grep: "SHA256:"
field: 2
value: abc123def456
```

Groups can nest to any depth. A deeply nested group inherits from all its ancestors:

```yaml
Matches:
results:
file: results.txt
energies:
tol: 1e-6 # tighter tolerance for the energies sub-group
total:
grep: "Total energy:"
field: 3
value: -42.5000
exchange:
grep: "Exchange:"
field: 2
value: -3.1416
forces:
tol: 1e-4 # looser tolerance for forces
atom_1:
grep: "Atom 1:"
field: 2
value: -0.00123
```

## Complete example

This example covers the most common match types in a single config:
Expand Down
Loading