Speed up running unit tests with Zeus

This is an effort to vastly decrease the time it takes to run a single
unit test file and therefore increase productivity and happiness for
people working on this project.

If you want to run a unit test file, now you can use `zeus rspec`
instead of `rspec` -- assuming you run `zeus start` first -- and it will
run a LOT faster.

Because test files tend to have long file paths, you can even use a
shorter version of those paths. So instead of saying:

    zeus rspec spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb

you can say:

    zeus rspec active_record/validate_uniqueness_of_matcher_spec.rb
This commit is contained in:
Elliot Winkler 2015-11-29 18:57:45 -07:00
parent 14b5658826
commit 3ee734bb7e
17 changed files with 191 additions and 31 deletions

View File

@ -37,6 +37,13 @@ request.
appraisal 4.2 rspec <path of test file to run>
```
You can also run unit tests by running `zeus start` in one shell, and then
running the following in another:
```
zeus rspec <path of test file to run>
```
And to run the entire test suite again:
```

View File

@ -6,6 +6,7 @@ gem 'pry', github: 'pry/pry'
gem 'pry-byebug'
gem 'rake', '~> 10.0'
gem 'rspec', '~> 3.2'
gem 'zeus'
# YARD
gem 'yard'

View File

@ -47,6 +47,8 @@ GEM
thor (0.19.1)
yajl-ruby (1.1.0)
yard (0.8.7.3)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
@ -62,6 +64,4 @@ DEPENDENCIES
redcarpet
rspec (~> 3.2)
yard
BUNDLED WITH
1.10.6
zeus

View File

@ -221,6 +221,52 @@ Shoulda::Matchers.configure do |config|
end
```
## Running tests
### Unit tests
Unit tests are the most common kind of tests in this gem, and the best way to
run them is by using [Zeus].
You'll want to run `zeus start` in one shell, then in another shell, instead of
using `rspec` to run tests, you can use `zeus rspec`. So for instance, you might
say:
```
zeus rspec spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb
```
As a shortcut, you can also drop the initial part of the path and say this
instead:
```
zeus rspec active_model/validate_inclusion_of_matcher_spec.rb
```
### Acceptance tests
The gem uses [Appraisal] to test against multiple versions of Rails and Ruby.
This means that if you're trying to run a single test file, you'll need to
specify which appraisal to use. For instance, you can't simply say:
```
rspec spec/acceptance/active_model_integration_spec.rb
```
Instead, you need to say
```
bundle exec appraisal 4.2 rspec spec/acceptance/active_model_integration_spec.rb
```
### All tests
You can run all tests by saying:
```
bundle exec rake
```
## Generating documentation
YARD is used to generate documentation, which can be viewed [online][rubydocs].
@ -284,3 +330,5 @@ We are [available for hire][hire].
[contributors]: https://github.com/thoughtbot/shoulda-matchers/contributors
[shoulda]: http://github.com/thoughtbot/shoulda
[shoulda-context]: http://github.com/thoughtbot/shoulda-context
[Zeus]: https://github.com/burke/zeus
[Appraisal]: https://github.com/thoughtbot/appraisal

88
custom_plan.rb Normal file
View File

@ -0,0 +1,88 @@
require 'zeus/rails'
require_relative 'spec/support/tests/current_bundle'
class CustomPlan < Zeus::Plan
def initialize
super
@rails_plan = Zeus::Rails.new
end
def boot
ENV['BUNDLE_GEMFILE'] = File.expand_path(
"../gemfiles/#{latest_appraisal}.gemfile",
__FILE__
)
require 'bundler/setup'
$LOAD_PATH << File.expand_path('../lib', __FILE__)
$LOAD_PATH << File.expand_path('../spec', __FILE__)
require_relative 'spec/support/unit/load_environment'
end
def after_fork
# @rails_plan.reconnect_activerecord
end
def test_environment
require_relative 'spec/unit_spec_helper'
end
def rspec
ARGV.replace(file_paths_to_run)
RSpec::Core::Runner.invoke
end
private
def latest_appraisal
current_bundle.latest_appraisal
end
def current_bundle
Tests::CurrentBundle.instance
end
def file_paths_to_run
if given_file_paths.empty?
['spec/unit']
else
given_file_paths.map do |given_path|
determine_file_path_to_run(given_path)
end
end
end
def determine_file_path_to_run(given_rspec_argument)
expanded_file_path, location =
expand_rspec_argument(given_rspec_argument)
if File.exist?(expanded_file_path)
if location
expanded_file_path + location
else
expanded_file_path
end
else
given_rspec_argument
end
end
def expand_rspec_argument(rspec_argument)
match = rspec_argument.match(/\A(.+?)(:\d+|\[[\d:]+\])?\Z/)
file_path, location = match.captures
expanded_file_path = File.expand_path(
"../spec/unit/shoulda/matchers/#{file_path}",
__FILE__
)
[expanded_file_path, location]
end
def given_file_paths
ARGV
end
end
Zeus.plan = CustomPlan.new

View File

@ -8,6 +8,7 @@ gem "pry", :github => "pry/pry"
gem "pry-byebug"
gem "rake", "~> 10.0"
gem "rspec", "~> 3.2"
gem "zeus"
gem "yard"
gem "redcarpet"
gem "pygments.rb"

View File

@ -177,6 +177,8 @@ GEM
json (>= 1.8.0)
yajl-ruby (1.2.1)
yard (0.8.7.6)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
@ -215,6 +217,4 @@ DEPENDENCIES
turbolinks
uglifier (>= 1.3.0)
yard
BUNDLED WITH
1.10.6
zeus

View File

@ -8,6 +8,7 @@ gem "pry", :github => "pry/pry"
gem "pry-byebug"
gem "rake", "~> 10.0"
gem "rspec", "~> 3.2"
gem "zeus"
gem "yard"
gem "redcarpet"
gem "pygments.rb"

View File

@ -179,6 +179,8 @@ GEM
json (>= 1.8.0)
yajl-ruby (1.2.1)
yard (0.8.7.6)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
@ -217,6 +219,4 @@ DEPENDENCIES
turbolinks
uglifier (>= 1.3.0)
yard
BUNDLED WITH
1.10.6
zeus

View File

@ -8,6 +8,7 @@ gem "pry", :github => "pry/pry"
gem "pry-byebug"
gem "rake", "~> 10.0"
gem "rspec", "~> 3.2"
gem "zeus"
gem "yard"
gem "redcarpet"
gem "pygments.rb"

View File

@ -174,6 +174,8 @@ GEM
json (>= 1.8.0)
yajl-ruby (1.2.1)
yard (0.8.7.6)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
@ -212,6 +214,4 @@ DEPENDENCIES
turbolinks
uglifier (>= 1.3.0)
yard
BUNDLED WITH
1.10.6
zeus

View File

@ -8,6 +8,7 @@ gem "pry", :github => "pry/pry"
gem "pry-byebug"
gem "rake", "~> 10.0"
gem "rspec", "~> 3.2"
gem "zeus"
gem "yard"
gem "redcarpet"
gem "pygments.rb"

View File

@ -197,6 +197,8 @@ GEM
json (>= 1.8.0)
yajl-ruby (1.2.1)
yard (0.8.7.6)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
@ -235,6 +237,4 @@ DEPENDENCIES
turbolinks
uglifier (>= 1.3.0)
yard
BUNDLED WITH
1.10.6
zeus

View File

@ -24,6 +24,10 @@ EOT
path.dirname == root.join('gemfiles')
end
def current_or_latest_appraisal
current_appraisal || latest_appraisal
end
def latest_appraisal
available_appraisals.sort.last
end

View File

@ -0,0 +1,12 @@
require_relative '../tests/current_bundle'
require_relative 'rails_application'
Tests::CurrentBundle.instance.assert_appraisal!
$test_app = UnitTests::RailsApplication.new
$test_app.create
$test_app.load
require 'active_record/base'
ENV['RAILS_ENV'] = 'test'

View File

@ -1,19 +1,4 @@
require_relative 'support/tests/current_bundle'
Tests::CurrentBundle.instance.assert_appraisal!
#---
require File.expand_path('../support/unit/rails_application', __FILE__)
$test_app = UnitTests::RailsApplication.new
$test_app.create
$test_app.load
require 'active_record/base'
ENV['BUNDLE_GEMFILE'] ||= app.gemfile_path
ENV['RAILS_ENV'] = 'test'
require_relative 'support/unit/load_environment'
require 'rspec/rails'
require 'shoulda-matchers'

11
zeus.json Normal file
View File

@ -0,0 +1,11 @@
{
"command": "ruby -rubygems -r./custom_plan -eZeus.go",
"plan": {
"boot": {
"test_environment": {
"rspec": []
}
}
}
}