Skip to main content

CLI Test Framework

中文 | English

A feature-focused automated testing framework for command-line applications. It is built for regression suites that need more than an exit-code check: multi-step commands, numerical result comparison, large configuration sets, parallel execution, and CI-ready reports.

The project grew out of finite-element solver development, where a single test may run several programs, produce HDF5 or CSV results, compare them with tolerances, and track execution time across revisions.

What it solves

CLI Test Framework keeps the execution workflow and its acceptance criteria in one JSON or YAML configuration:

  • Execute workflows — single commands or fail-fast step sequences, with timeouts, retries, variables, tags, and expected-failure support.
  • Verify results — return codes, output text and regular expressions, plus text, JSON, CSV, XML, HDF5, binary, and custom-script file comparisons.
  • Manage large suites — split configurations with import, reuse templates with extends, filter by name or tag, and inspect cases across files in the optional TUI.
  • Iterate and integrate — parallel execution, --last-failed, step-level --resume, runtime history, structured reports, and JUnit XML output.

The emphasis is practical: features are added to solve test workflows that occur in real CLI and scientific-computing projects.

Installation

Python 3.9 or newer is required.

pip install cli-test-framework

YAML and the TUI are optional:

pip install "cli-test-framework[yaml]"
pip install "cli-test-framework[tui]"
pip install "cli-test-framework[all]"

The default installation includes HDF5 and numerical comparison support.

Quick start

Create test_cases.json:

{
  "test_cases": [
    {
      "name": "hello",
      "command": "echo",
      "args": ["Hello World"],
      "tags": ["smoke"],
      "expected": {
        "return_code": 0,
        "output_contains": ["Hello World"]
      }
    }
  ]
}

Run it:

cli-test run test_cases.json

Validate a configuration without executing it:

cli-test validate test_cases.json

Numerical golden-file testing

File comparisons can be part of a test's acceptance criteria. Comparator parameters such as tolerances, table selection, filters, and encodings are declared next to the command:

{
  "test_cases": [
    {
      "name": "FEA displacement check",
      "command": "my_solver",
      "args": ["--input", "case1.dat", "--output", "out.h5"],
      "expected": {
        "return_code": 0,
        "output_contains": ["simulation finished"],
        "compare_files": [
          {
            "actual": "out.h5",
            "baseline": "ref/golden.h5",
            "rtol": 1e-5,
            "atol": 1e-8,
            "tables": ["NASTRAN/RESULT/NODAL/DISPLACEMENT"]
          },
          {
            "actual": "summary.csv",
            "baseline": "ref/summary.csv",
            "rtol": 1e-6
          }
        ]
      }
    }
  ]
}

The comparator type is inferred from the extension when type is omitted. Built-in types are text, json, csv, xml, h5, binary, and script. Workspace comparators can be added without changing the framework.

To intentionally accept changed outputs, use --update-baseline. Because this can overwrite reference files, interactive runs require typing yes; non-interactive runs must explicitly add --yes:

cli-test run test_cases.json --update-baseline
cli-test run test_cases.json --update-baseline --yes   # automation / CI

Keep baselines under version control and review every update.

Multi-step and iterative workflows

A case may contain an ordered steps list. Execution stops at the first failed step. For long workflows, --resume reuses saved state and skips steps that already passed:

cli-test run solver_tests.json
cli-test run solver_tests.json --last-failed
cli-test run solver_tests.json -t long_case --resume

--resume deliberately trusts that workspace artifacts have not changed between runs.

Large test suites and the optional TUI

Large suites can be divided into sub-configurations:

{
  "test_cases": [
    {"import": "cases/text_tests.json", "tags": ["text"]},
    {"import": "cases/h5_tests.json", "tags": ["h5", "regression"]}
  ]
}

The optional TUI provides one searchable view across imported files. It is intended as an aid for locating cases and reviewing scenario coverage in large projects, rather than a requirement for normal test execution.

cli-test tui main_config.json

Parallel execution and resources

cli-test run test_cases.json --parallel --workers 4
cli-test run test_cases.json --parallel --execution-mode process

Thread mode currently supports CPU-token allocation, solver thread environment variables, and longest-processing-time-first scheduling using estimates or runtime history. Process mode provides execution isolation but does not yet use the resource scheduler. Memory enforcement, priority semantics, and broader resource scheduling remain active areas of development.

CI and reports

cli-test run test_cases.json \
  --parallel --workers 4 \
  --junit-xml report.xml

The current suite contains 750 unit, integration, and end-to-end tests with 83% line coverage. CI exercises Windows and Linux across Python 3.9 through 3.13.

Python API

from cli_test_framework.runners import JSONRunner, ParallelJSONRunner

runner = ParallelJSONRunner(
    config_file="test_cases.json",
    max_workers=4,
    execution_mode="thread",
    history_dir="./hist",
    variables={"solver": "/opt/solver/bin/solver"},
)

success = runner.run_tests()
for detail in runner.results["details"]:
    print(detail["name"], detail["status"], detail.get("duration"))

Standalone file comparison

compare-files result1.h5 result2.h5 --h5-table-regex "output_.*" --h5-rtol 1e-5
compare-files data1.csv data2.csv --csv-rtol 1e-4 --csv-data-filter ">1e-6"
compare-files data1.json data2.json --json-compare-mode key-based --json-key-field id

AI-assisted TDD, as a side benefit

The same configuration can serve as a machine-readable acceptance contract. Structured validation failures, comparison details, and targeted reruns work well in an AI-assisted TDD loop:

define acceptance criteria
    → run the relevant cases
    → inspect the structured failure
    → change the implementation
    → rerun with --last-failed
    → run the full regression suite

This is a useful consequence of explicit tests and structured results, not a requirement for using the framework.

Documentation

Development

Install the package with all optional and test dependencies:

pip install -e ".[dev]"
python -m pytest tests/unit tests/integration tests/e2e

Bug fixes, comparator plugins, documentation improvements, and reports from real-world test workflows are welcome.

License

MIT

Release files for cli-test-framework 1.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cli-test-framework 1.2.3
File Size Uploaded
cli_test_framework-1.2.3.tar.gz 831.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cli-test-framework 1.2.3
File Interpreter ABI Platform
cli_test_framework-1.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 956.2 kB

Release files / cli_test_framework-1.2.3.tar.gz

Download URL cli_test_framework-1.2.3.tar.gz
Size 831.2 kB
Tags Source
SHA-256 checksum
How to use checksums
85ee6bf85545fb40e33354f3521fd932ec06da1b6e97dd8d0c42c5d6ce40fcd6
BLAKE2b-256 checksum
How to use checksums
04397be744ab6241258c884d142835ecc8d0e30ac6401c7a9cd5108dfdd93004
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / cli_test_framework-1.2.3-py3-none-any.whl

Download URL cli_test_framework-1.2.3-py3-none-any.whl
Size 125.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
256d163427c410db667561011677b2ab8eba1f804e07181f63abf4b53adb7820
BLAKE2b-256 checksum
How to use checksums
59abe099043b28da64b1168adebf39c1c12b070890fbbe0da0a80d8a0ca3f9c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

1.2.5

2 release files

1.2.4

2 release files

This release

1.2.3 This release

2 release files

1.2.2

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page