Running Tests
Relevant source files
The following files were used as context for generating this wiki page:The Ralph for Claude Code project maintains a comprehensive test suite to ensure stability, correctness, and prevent regressions. The testing framework is built upon the Bash Automated Testing System (BATS). As of the latest update, the suite consists of 276 tests with a 100% pass rate, enforced by a CI/CD pipeline on GitHub Actions.
This guide provides a detailed overview of the test architecture, how to run tests, and best practices for writing new tests. Adherence to these testing standards is mandatory for all contributions. For more information on the contribution process, see the CONTRIBUTING.md guide.
Sources: TESTING.md:3-5, README.md:6, CONTRIBUTING.md:120-122
Quick Start
Before running tests, ensure the necessary prerequisites are installed. The test suite is executed via npm scripts defined in package.json.
Sources: TESTING.md:15-18
Prerequisites
- Node.js 18+
- npm
- jq (for JSON processing in fixtures)
- git
Sources: TESTING.md:18-26, CONTRIBUTING.md:21-26
Test Commands
After cloning the repository, install the testing dependencies first.
# Install BATS and other dependencies
npm install
The following commands can then be used to run the test suite.
| Command | Description |
|---|---|
npm test | Runs the complete test suite, including unit and integration tests. |
npm run test:unit | Runs only the fast, isolated unit tests. |
npm run test:integration | Runs tests that verify interactions between different components. |
npm run test:e2e | Runs end-to-end workflow tests (currently planned). |
bats tests/unit/test_file.bats | Runs a specific test file. |
bats ... --filter "pattern" | Runs a single test function matching a pattern. |
Sources: TESTING.md:34-58, CONTRIBUTING.md:143-148
Test Organization
The test suite is structured into categories based on scope and purpose, located within the tests/ directory. This organization separates fast, isolated unit tests from slower, more complex integration tests.
Sources: TESTING.md:63-65, CONTRIBUTING.md:133-135
Directory Structure
The diagram below illustrates the layout of the tests/ directory.
This diagram shows the organization of test files into unit, integration, and helper directories.
Sources: TESTING.md:66-83, IMPLEMENTATION_STATUS.md:15-27
Test Categories
| Category | Purpose | Speed | Dependencies |
|---|---|---|---|
| Unit | Test individual functions in isolation. | Fast (<1s per file) | None (uses mocks) |
| Integration | Test interactions between components. | Medium (1-5s per file) | Real git, filesystem |
| E2E | Test complete end-to-end workflows. | Slow (>5s per file) | Full environment |
Sources: TESTING.md:85-90
Writing Tests
Tests are written using the BATS framework. Each test case is defined with @test "description" { ... } and runs in an isolated subshell.
Sources: TESTING.md:97-99
BATS Test Lifecycle
A typical BATS test follows a setup-act-assert-teardown pattern. The run command is used to execute a function or script and capture its exit status and output for assertion.
This diagram shows the execution flow of a single BATS test case, including setup and teardown hooks.
Sources: TESTING.md:104-115, CONTRIBUTING.md:153-171
Example Unit Test
This example from test_rate_limiting.bats demonstrates a simple unit test for the can_make_call function.
#!/usr/bin/env bats
# Unit Tests for Rate Limiting Logic
load '../helpers/test_helper'
setup() {
# ... setup code ...
export MAX_CALLS_PER_HOUR=100
export CALL_COUNT_FILE=".call_count"
cd "$(mktemp -d)"
}
teardown() {
# ... teardown code ...
}
# Define the function being tested
can_make_call() {
local calls_made=$(cat "$CALL_COUNT_FILE")
[[ $calls_made -ge $MAX_CALLS_PER_HOUR ]] && return 1
return 0
}
@test "can_make_call returns success when under limit" {
# Arrange
echo "50" > "$CALL_COUNT_FILE"
# Act
run can_make_call
# Assert
assert_success
}
@test "can_make_call returns failure when at limit" {
# Arrange
echo "100" > "$CALL_COUNT_FILE"
# Act
run can_make_call
# Assert
assert_failure
}
Sources: TESTING.md:143-181
Test Helpers, Mocks, and Fixtures
The test suite relies on a collection of shared utilities in tests/helpers/ to provide assertions, mock external commands, and generate test data.
Sources: TESTING.md:227-229
test_helper.bash
This file provides core assertion functions and setup utilities to simplify test writing.
| Helper Function | Description |
|---|---|
assert_success | Asserts that the last run command exited with status 0. |
assert_failure | Asserts that the last run command exited with a non-zero status. |
assert_equal "$1" "$2" | Compares two string values for equality. |
assert_output "text" | Compares the $output variable from run with the expected text. |
assert_file_exists "path" | Asserts that a file exists at the given path. |
assert_dir_exists "path" | Asserts that a directory exists at the given path. |
assert_valid_json "file.json" | Validates that a file contains syntactically correct JSON. |
create_mock_prompt | Creates a sample PROMPT.md file for testing. |
create_mock_fix_plan 5 2 | Creates a sample @fix_plan.md with 5 total and 2 completed tasks. |
create_mock_status ... | Creates a sample status.json file. |
Sources: TESTING.md:233-259, CONTRIBUTING.md:185-194
mocks.bash
This helper provides mock implementations for external commands like git, tmux, and the Claude Code CLI, allowing for isolated unit tests.
| Mock Function | Controllable Behavior |
|---|---|
mock_claude_code | MOCK_CLAUDE_SUCCESS, MOCK_CLAUDE_OUTPUT, MOCK_CLAUDE_EXIT_CODE |
mock_tmux | MOCK_TMUX_AVAILABLE |
mock_git | MOCK_GIT_AVAILABLE, MOCK_GIT_REPO |
mock_notify_send | Mocks desktop notifications. |
To use mocks, source mocks.bash and call setup_mocks in setup() and teardown_mocks in teardown().
Sources: TESTING.md:261-299
fixtures.bash
This file contains functions to generate sample data and complete project structures for integration testing.
| Fixture Function | Description |
|---|---|
create_sample_prd_md "file" | Creates a sample Product Requirements Document in Markdown. |
create_sample_fix_plan "file" 10 3 | Creates a sample @fix_plan.md with 10 tasks, 3 completed. |
create_sample_claude_output_success "file" | Creates a log file simulating a successful Claude Code run. |
create_sample_status_running "file" | Creates a status.json file for a running state. |
create_test_project "name" | Creates a complete test project structure with all necessary files. |
Sources: tests/helpers/fixtures.bash
CI/CD Integration
All tests are automatically executed on every push and pull request via a GitHub Actions workflow defined in .github/workflows/test.yml. A 100% test pass rate is a mandatory quality gate for merging code.
Sources: TESTING.md:341-343, CONTRIBUTING.md:122
GitHub Actions Pipeline
The pipeline consists of a test job that runs the full suite and an informational coverage job.
This diagram shows the GitHub Actions pipeline for running tests and generating coverage reports.
Sources: TESTING.md:345-365
Code Coverage
The project aims for an 85% code coverage ratio, but this is informational, not a blocking requirement. The primary quality gate is the 100% test pass rate. This is due to a technical limitation in kcov (the coverage tool) which cannot properly trace subprocesses spawned by BATS, leading to inaccurate coverage reports.
Sources: TESTING.md:320-330, CONTRIBUTING.md:124-128, CLAUDE.md:131-134
Quality Standards
Testing is a critical part of the development workflow. All new features or bug fixes must be accompanied by corresponding tests.
| Requirement | Standard | Enforcement |
|---|---|---|
| Test Pass Rate | 100% | Mandatory. CI blocks merges on failure. |
| Test Coverage | 85% (Aspirational) | Informational only. |
| New Features | Must include tests. | Mandatory, enforced during code review. |