A universal test runner that distributes tests across multiple workers for parallel execution.
- ✅ Parallel test execution with multiple workers
- ✅ RSpec support (by-file strategy)
- ✅ In-memory queue for local execution
- ✅ Simple CLI interface
- 🚧 GitHub Actions integration (planned)
- 🚧 Jest and pytest support (planned)
- Go 1.23 or later
- RSpec (for running Ruby tests)
go build -o speq .Or using mise:
mise install
mise exec -- go build -o speq .# Run with 4 workers (default)
./speq test spec/
# Run with custom number of workers
./speq test --workers 8 spec/
# Run with custom batch size
./speq test --workers 4 --batch-size 10 spec/# Generate manifest for spec/ directory
./speq manifest spec/
# Custom output file
./speq manifest --output my-manifest.json spec/--config string # Config file (default: ./speq.yml)
--strategy string # Distribution strategy: by-file (default)
--batch-size int # Tests per batch (default: 7)speq can be used as a reusable GitHub Actions composite action in your workflows.
name: RSpec Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests with speq
uses: ryotoya/speq@main
with:
workers: 4
batch-size: 7
test-directory: spec
ruby-version: '3.3'For private repositories, you need to checkout the speq action using a Personal Access Token (PAT):
name: RSpec Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Checkout speq action from private repository
- name: Checkout speq action
uses: actions/checkout@v4
with:
repository: ryotoya/speq
token: ${{ secrets.GH_PAT }} # PAT with repo scope
path: .github/actions/speq
# Use the checked-out action
- name: Run tests with speq
uses: ./.github/actions/speq
with:
workers: 4
batch-size: 7
test-directory: spec
ruby-version: '3.3'| Input | Description | Required | Default |
|---|---|---|---|
workers |
Number of workers to run in parallel | No | 4 |
batch-size |
Number of tests to pull from queue at a time | No | 7 |
test-directory |
Directory containing test files | No | spec |
ruby-version |
Ruby version to use | No | 3.3 |
go-version |
Go version for building speq | No | 1.23 |
For private repositories, you need to create a PAT:
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate new token with
reposcope - Add the token as a secret in your repository:
- Repository Settings → Secrets and variables → Actions
- New repository secret:
GH_PAT= your token value
If your project has a Gemfile, the action will automatically run bundle install:
- name: Run tests with speq
uses: ./.github/actions/speq
with:
workers: 8
batch-size: 10
test-directory: spec┌─────────────┐
│ Queue │ ← In-memory queue manages test distribution
│ (LocalQueue)│
└──────┬──────┘
│
├─────────┬─────────┬─────────┐
↓ ↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│Worker 0│ │Worker 1│ │Worker 2│ │Worker 3│
└────────┘ └────────┘ └────────┘ └────────┘
- Discovery: Parse test directory to find all
*_spec.rbfiles - Distribution: Queue distributes tests in batches to workers
- Execution: Each worker executes tests using RSpec
- Aggregation: Results are collected and displayed
speq/
├── cmd/ # CLI commands
│ ├── root.go # Root command and config
│ ├── manifest.go # Generate test manifest
│ └── test.go # Run tests command
├── internal/
│ ├── queue/ # Queue implementations
│ │ ├── queue.go # Queue interface
│ │ └── local.go # In-memory local queue
│ ├── parser/
│ │ └── rspec.go # RSpec test parser
│ ├── worker/
│ │ ├── worker.go # Worker implementation
│ │ └── executor.go # RSpec test executor
│ └── reporter/
│ ├── reporter.go # Result aggregation
│ └── terminal.go # Terminal output
└── pkg/protocol/
└── messages.go # Data structures
- Project setup and structure
- Data structures (TestCase, TestResult, TestManifest)
- RSpec parser (by-file strategy)
- Local in-memory queue
- Worker implementation
- RSpec executor with JSON output parsing
- Result aggregation and reporting
- CLI commands (test, manifest)
- Parallel execution with goroutines
- GitHub Actions integration (file-based queue)
- Report command for result aggregation
- Jest support
- pytest support
- by-test distribution strategy
- Automatic retry of flaky tests
- Historical data-based optimization
Create a speq.yml file in your project root:
version: 1
# Test framework
framework: rspec
# Distribution strategy
strategy: by-file # or by-test (future)
# Batch size
batch_size: 7
# Test directory
test_dir: spec🚀 Starting speq with 4 workers
Test directory: spec/
Strategy: by-file
Batch size: 7
📋 Discovered 24 test files
[Worker 0] ✓ spec/models/user_spec.rb (0.45s)
[Worker 1] ✓ spec/models/post_spec.rb (0.32s)
[Worker 2] ✓ spec/controllers/users_controller_spec.rb (0.78s)
[Worker 3] ✓ spec/services/auth_service_spec.rb (0.56s)
...
============================================================
Test Results Summary
============================================================
✓ Passed: 23
✗ Failed: 1
- Skipped: 0
Total: 24 tests
Duration: 5.32s
Workers: 4
Worker Statistics:
Worker 0: 6 tests in 4.23s
Worker 1: 6 tests in 4.87s
Worker 2: 6 tests in 5.12s
Worker 3: 6 tests in 4.56s
MIT