This project is a Rust-based CLI tool for integration testing of command-line applications.
- Use
cargo buildto build the project (notnpmorbun) - Use
cargo testfor unit tests - Use
cargo run -- <args>to run the CLI during development - Use
cargo run --release -- <args>for optimized builds - Use
cargo clippyfor linting - Use
cargo fmtfor formatting - Always run
cargo clippyandcargo fmt --checkbefore considering code changes complete to catch warnings and ensure code quality
The project tests itself using .hone test files:
# Run all integration tests
cargo run --release -- tests/integration/*.hone
# Run example tests
cargo run --release -- examples/*.hone
# Run a specific test file
cargo run --release -- tests/integration/exit-codes.honehone/
├── src/
│ ├── main.rs # CLI entry point
│ ├── lib.rs # Library exports
│ ├── parser/ # DSL parser
│ │ ├── mod.rs
│ │ ├── parser.rs
│ │ ├── lexer.rs
│ │ ├── ast.rs
│ │ └── errors.rs
│ ├── runner/ # Test execution
│ │ ├── mod.rs
│ │ ├── executor.rs
│ │ ├── shell.rs
│ │ ├── sentinel.rs
│ │ └── reporter.rs
│ ├── assertions/ # Assertion implementations
│ │ ├── mod.rs
│ │ ├── output.rs
│ │ ├── exitcode.rs
│ │ ├── timing.rs
│ │ └── filesystem.rs
│ └── utils/
│ ├── mod.rs
│ └── ansi.rs
├── tests/integration/ # .hone integration tests
├── examples/ # .hone example files
├── Cargo.toml
└── README.md
- Async Runtime: Uses Tokio for async/await
- Shell Execution: Spawns shell processes and tracks output via PTY
- Sentinel Protocol: Wraps commands with markers to detect completion
- Multi-file Tests: Each test file gets its own shell session
- Error Handling: Uses anyhow for error propagation
- Avoid excessive comments: Code should be self-documenting through clear naming
- Only add comments for non-obvious logic, complex algorithms, or important context
- Avoid inline comments that restate what the code does (e.g.,
// Loop through items) - Prefer doc comments (
///) for public APIs over inline comments
- Use
snake_casefor functions, methods, variables, and modules - Use
PascalCasefor types, traits, and enum variants - Use
SCREAMING_SNAKE_CASEfor constants and statics - Prefer
impl Traitover explicit generics when possible - Use
?operator for error propagation instead of explicitmatch - Prefer iterators and combinators over explicit loops when clearer
- Use
#[must_use]for functions where ignoring the return value is likely a bug - Derive common traits (
Debug,Clone,PartialEq) when appropriate - Use
Selfto refer to the implementing type inimplblocks - Prefer
&stroverStringfor function parameters when ownership isn't needed - Use
OptionandResultidiomatically; avoid sentinel values - Prefer explicit error types over
unwrap/expectpatterns - Use
.to_string_lossy().into_owned()instead of.to_string_lossy().to_string()for converting to owned string values
- All commits must follow the Convential Commit format.
- Commits MUST NOT be co-authored by the agent.
- Keep modules focused and cohesive
- Use
mod.rsto re-export public items from submodules - Place tests in the same file using
#[cfg(test)]modules - Group related imports; separate std, external crates, and local imports
- Use
crate::for all internal imports; avoidsuper::(exception:use super::*in test modules is acceptable)
- Unit tests in Rust using
#[test]annotations - Integration tests using
.honefiles that test the compiled binary - Examples serve as both documentation and smoke tests
- Binaries are cross-compiled for multiple platforms using
cross - GitHub Actions builds for Linux (x64, ARM64) and macOS (x64, ARM64)
- Version is managed in
Cargo.toml