mighty_test (mt
) is a TDD-friendly Minitest runner for Ruby projects. It includes a Jest-inspired interactive watch mode, focus mode, CI sharding, run by directory/file/line number, fail-fast, and color formatting.
Quick Start
Features
- βοΈ CI Mode
- π§βπ¬ Watch Mode
- π¬ Focus Mode
- π Fail Fast
- π₯ Color Output
- π¬ More Options
Community
The mighty_test gem provides an mt
binary. To install it into a Ruby project, first add the gem to your Gemfile and run bundle install
.
gem "mighty_test"
Then generate a binstub:
bundle binstub mighty_test
Now you can run mighty_test with bin/mt
.
Tip
When installing mighty_test in a Rails project, make sure to put the gem in the :test
Gemfile group. Although Rails has a built-in test runner (bin/rails test
) that already provides a lot of what mighty_test offers, you can still use bin/mt
with Rails projects for its unique --watch
mode and CI --shard
feature.
mighty_test requires modern versions of Minitest and Ruby.
- Minitest 5.15+
- Ruby 3.1+
Support for older Ruby versions will be dropped when they reach EOL. The EOL schedule can be found here: https://endoflife.date/ruby
Note
mighty_test currently assumes that your tests are stored in test/
and are named *_test.rb
. Watch mode expects implementation files to be in app/
and/or lib/
.
mt
defaults to running all tests, excluding slow tests (see the explanation of slow tests below). You can also run tests by directory, file, or line number.
# Run all tests, excluding slow tests
bin/mt
# Run all tests, slow tests included
bin/mt --all
# Run a specific test file
bin/mt test/cli_test.rb
# Run a test by line number
bin/mt test/importer_test.rb:43
# Run a directory of tests
bin/mt test/commands
Tip
mighty_test is optimized for TDD, and excludes slow tests by default. Slow tests are defined as those found in test/{e2e,feature,features,integration,system}
directories. You can run slow tests with --all
or by specifying a slow test file or directory explicitly, like bin/mt test/system
.
If the CI
environment variable is set, mighty_test defaults to running all tests, including slow tests. This is equivalent to passing --all
.
mighty_test can also distribute test files evenly across parallel CI jobs, using the --shard
option. The shard nomenclature has been borrowed from similar features in Jest and Playwright.
# Run the 1st group of tests out of 4 total groups
bin/mt --shard 1/4
In GitHub Actions, for example, you can use --shard
with a matrix strategy to easily divide tests across N jobs.
jobs:
test:
strategy:
matrix:
shard:
- "1/4"
- "2/4"
- "3/4"
- "4/4"
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: bin/mt --shard ${{ matrix.shard }}
In CircleCI, you can use the parallelism
setting, which automatically injects $CIRCLE_NODE_INDEX
and $CIRCLE_NODE_TOTAL
environment variables. Note that $CIRCLE_NODE_INDEX
is zero-indexed, so it needs to be incremented by 1.
jobs:
test:
parallelism: 4
steps:
- checkout
- ruby/install-deps
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; bin/mt --shard ${SHARD}/${CIRCLE_NODE_TOTAL}
Tip
--shard
will shuffle tests and automatically distribute slow tests evenly across jobs.
mighty_test includes a Jest-style watch mode, which can be started with --watch
. This is ideal for TDD.
# Start watch mode
bin/mt --watch
In watch mode, mighty_test will listen for file system activity and run a test file whenever it is modified.
When you modify an implementation file, mighty_test will find the corresponding test file and run it automatically. This works as long as your implementation and test files follow a standard path naming convention: e.g. lib/commands/init.rb
is expected to have a corresponding test file named test/commands/init_test.rb
.
Watch mode also offers a menu of interactive commands:
> Press Enter to run all tests.
> Press "a" to run all tests, including slow tests.
> Press "d" to run tests for files diffed or added since the last git commit.
> Press "h" to show this help menu.
> Press "q" to quit.
You can focus a specific test by annotating the method definition with focus
.
class MyTest < Minitest::Test
focus def test_something_important
assert # ...
end
Now running bin/mt
will execute only the focused test:
# Only runs MyTest#test_something_important
bin/mt
In Rails projects that use the test
syntax, focus
must be placed on the previous line.
class MyTest < ActiveSupport::TestCase
focus
test "something important" do
assert # ...
end
This functionality is provided by the minitest-focus plugin, which is included with mighty_test.
By default, mighty_test runs the entire test suite to completion. With the --fail-fast
option, it will stop on the first failed test.
# Stop immediately on first test failure
bin/mt --fail-fast
# Use with watch mode for even faster TDD
bin/mt --watch --fail-fast
This functionality is provided by the minitest-fail-fast plugin, which is included with mighty_test.
Successes, failures, errors, and skips are colored appropriately by default.
# Run tests with color output (if terminal supports it)
bin/mt
# Disable color
bin/mt --no-rg
This functionality is provided by the minitest-rg plugin, which is included with mighty_test.
Use -w
to enable Ruby warnings when running tests:
bin/mt -w
Minitest options are passed through to Minitest.
# Run tests with Minitest pride color output
bin/mt --pride
# Run tests with an explicit seed value for test ordering
bin/mt --seed 4519
# Run tests with detailed progress and explanation of skipped tests
bin/mt --verbose
# Show the full list of possible options
bin/mt --help
If you have Minitest extensions installed, like minitest-snapshots, the command line options of those extensions are supported as well.
# Update snapshots
bin/mt -u
If you want to report a bug, or have ideas, feedback or questions about the gem, let me know via GitHub issues and I will do my best to provide a helpful answer. Happy hacking!
The gem is available as open source under the terms of the MIT License.
Everyone interacting in this projectβs codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Pull requests are welcome!