1
0
Fork 0
mirror of https://github.com/imjasonh/testscript-rs synced 2026-07-08 17:16:38 +00:00
testscript-rs/README.md
2025-09-26 19:18:34 -04:00

4.2 KiB

testscript-rs

CI

A Rust crate for testing command-line tools using filesystem-based script files.

testscript-rs provides a framework for writing integration tests for CLI applications using the .txtar format, where test scripts and file contents are combined in a single file.

This crate is inspired by and aims to be compatible with Go's github.com/rogpeppe/go-internal/testscript package.

Testscript is primarily useful for describing testing scenarios involving executing commands and dealing with files. This makes it a good choice for testing CLI applications in a succinct and human-readable way.

Quick Example

use testscript_rs::testscript;

#[test]
fn test_my_cli() {
    testscript::run("testdata")
        .setup(|env| {
            // Compile your CLI tool
            std::process::Command::new("cargo")
                .args(["build", "--bin", "my-cli"])
                .status()?;

            // Copy binary to test environment
            std::fs::copy("target/debug/my-cli", env.work_dir.join("my-cli"))?;
            Ok(())
        })
        .execute()
        .unwrap();
}

With a test script in testdata/basic.txt:

# Test basic functionality
exec ./my-cli --version
stdout "my-cli 1.0"

exec ./my-cli process input.txt
cmp output.txt expected.txt

-- input.txt --
test content

-- expected.txt --
processed: test content

Running the test will compile the CLI program, make it available to the testscript environment, run the specified commands, and check its output.

Installation

Add testscript-rs to your Cargo.toml:

[dev-dependencies]
testscript-rs = "0.1"

Requires Rust 1.70 or later.

Usage

Basic Usage

use testscript_rs::testscript;

#[test]
fn test_cli() {
    testscript::run("testdata").execute().unwrap();
}

With Setup Hook

testscript::run("testdata")
    .setup(|env| {
        // Compile your binary before each test
        std::process::Command::new("cargo")
            .args(["build", "--bin", "my-tool"])
            .status()?;
        Ok(())
    })
    .execute()
    .unwrap();

With Custom Commands

testscript::run("testdata")
    .command("custom-cmd", |env, args| {
        // Your custom command implementation
        println!("Running custom command with args: {:?}", args);
        Ok(())
    })
    .condition("feature-enabled", true)
    .execute()
    .unwrap();

To call the custom command, in your testscript file:

custom-cmd arg1 arg2 arg3

Test Script Format

Test scripts use the .txtar format. For complete format documentation, see the original Go testscript documentation.

Built-in Commands

  • exec - Execute external commands
  • cmp - Compare two files
  • stdout/stderr - Check command output (supports regex)
  • exists - Check file existence
  • mkdir - Create directories
  • cp - Copy files (supports stdout/stderr as source)
  • mv - Move/rename files
  • rm - Remove files/directories
  • chmod - Change file permissions
  • env - Set environment variables
  • cmpenv - Compare files with environment variable substitution
  • stdin - Set stdin for next command
  • cd - Change working directory
  • wait - Wait for background processes
  • kill - Kill background processes
  • skip - Skip test execution
  • stop - Stop test early (pass)
  • unquote - Remove leading > from file lines
  • grep - Search files with regex

Commands can be prefixed with conditions ([unix]) or negated (!).

Note: Some features of testscript in Go are not supported in this Rust port:

  • [gc] for whether Go was built with gc
  • [gccgo] for whether Go was built with gccgo
  • [go1.x] for whether the Go version is 1.x or later

Examples

See examples/sample-cli/ and its testdata directory for more examples.

There are also more tests in testdata that demonstrate and check this implementations behavior.