TL;DR:
- Setup Guard and Guard::Minitest
- Add this to your
Guardfile
:
watch( %r{^exercises/(.*)/(.*)\.rb$} ) { |matches| "exercises/#{matches[1]}/#{matches[1]}_test.rb" }
- Run
bundler exec guard
Skip down to the Setup Steps section below for more details.
Background: Learning Ruby
One of the things I love the most about Automattic is how it’s focused on investing in people for the long term. Part of that is the perk of getting a 2-3 month sabbatical every five years. I started my first one last month, and have been playing around with some technologies that I don’t normally work with in my day-to-day job, to get some exposure to how other communities have approached problems, in hopes of becoming a more well-rounded developer.One of the things I’ve been learning is the Ruby language (and of course, the Rails framework. Side note: The Rails Doctrine is a very good read, regardless of whether or not you agree with everything in it). I started by taking some of the Treehouse courses, but as an experienced developer, I found them frustratingly slow. I felt like I was spending hours learning things that I could easily pick up in a few minutes in a different format.
So, I decided to try a different approach, and read through the Learn X in Y Minutes summary of Ruby’s syntax and core API. That gave me enough familiarity with the basics to start playing around with some small scripts.
I think I learn best by doing, and using each obstacle that comes up as an opportunity to find the answers to all the questions it raises, so I wanted to have some real(ish) problems to solve. My search led me to Exercism.io, which turned out to be a great resource. They have dozens of sample exercises available for Ruby (and many other languages), along with solutions that you can review after you’ve completed your own. Seeing how other people solved the problem has been a very helpful way to improve on my solutions, and learn more in the process.
That brief Learn X in Y Minutes introduction to the language, the practices exercises, and the Ruby documentation, have turned out to be a much better way for me to learn than sitting through video courses with minimal hands-on exercises, and overly-simplistic standardized tests.
Automatically Running Tests
That leads me to the catalyst for writing this post, though. I found it tedious to have to manually execute the unit tests throughout the development process; I wanted them to run automatically every time I saved a file, like they do when working on WordPress Core and Calypso.
I looked around and, of course, there were several options for accomplishing this. I chose to use Guard along with Guard::Minitest, since it fit the workflow I was looking for, and felt similar to what I’ve implemented before with Grunt.
Not surprisingly, I had to struggle with the Guardfile
for awhile in order to get things working, but I finally did. Here’s what I came up with:
Setup Steps
git clone git@github.com:exercism/ruby.git exercism-ruby
- There’s also a CLI client for Exercism if you prefer to use that. You may need to modify the following steps if you do.
- Add
gem 'guard'
andgem 'guard-minitest'
to yourGemfile
, then runbundle
- In this case it’s necessary to explicitly add
guard
, even though normally the dependency would handled bybundler
.
- In this case it’s necessary to explicitly add
- Add this to your
Guardfile
:
guard :minitest, test_folders: 'exercises', test_file_patterns: '*_test.rb', all_on_start: false do # This is saying watch for any changes to any .rb file in any subdirectory of exercises # Then modify the name of the file that gets passed to minitest, so that it just passes exercises/foo/foo_test.rb watch( %r{^exercises/(.*)/(.*)\.rb$} ) { |matches| "exercises/#{matches[1]}/#{matches[1]}_test.rb" } end
- From inside the
exercism-ruby
folder, runbundler exec guard
- If your changes aren’t being detected, you may need to use the
-p
flag to enable polling,
- If your changes aren’t being detected, you may need to use the
Customizing Minitest Output
If you also want to have color output, or hide the verbose messages for skipped tests, you can follow these steps:
- Add
gem 'minitest-reporters'
to yourGemfile
and runbundler
- Add this to all of your
exercism-ruby/exercises/*/*_test.rb
files:- There’s probably a more DRY way to do it, but I haven’t spent the time to get that working yet.
require 'minitest/reporters' minitest_options = { color: true, detailed_skip: false } Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new( minitest_options )]
I have found https://github.com/alexch/rerun to be very simple. No counter-intuitive config file but a couple useful command line arguments.
Does a great job when you don’t need anything complicated: just run that command again when files change.