Home > Articles

  • Print
  • + Share This
This chapter is from the book

3.6 Advanced Testing Setup

This optional section describes the testing setup used in the Ruby on Rails Tutorial screencast series. There are two main elements: an enhanced pass/fail reporter (Section 3.6.1), and an automated test runner that detects file changes and automatically runs the corresponding tests (Section 3.6.2). The code in this section is advanced and is presented for convenience only; you are not expected to understand it at this time.

The changes in this section should be made on the master branch:

$ git checkout master

3.6.1 Minitest Reporters

To get the default Rails tests to show RED and GREEN at the appropriate times, I recommend adding the code in Listing 3.44 to your test helper file,18 thereby making use of the minitest-reporters gem included in Listing 3.2.

Listing 3.44: Configuring the tests to show RED and GREEN.
test/test_helper.rb

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__ )
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!


class ActiveSupport::TestCase
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
  fixtures :all

  # Add more helper methods to be used by all tests here...
end

The resulting transition from RED to GREEN in the cloud IDE appears as in Figure 3.8.19

Figure 3.8

Figure 3.8: Going from RED to GREEN in the cloud IDE.

3.6.2 Automated Tests with Guard

One annoyance associated with using the rails test command is having to switch to the command line and run the tests by hand. To avoid this inconvenience, we can use Guard to automate the running of the tests. Guard monitors changes in the filesystem so that, for example, when we change the static_pages_controller_test.rb file, only those tests get run. Even better, we can configure Guard so that when, say, the home.html.erb file is modified, the static_pages_controller_test.rb automatically runs.

The Gemfile in Listing 3.2 has already included the guard gem in our application, so to get started we just need to initialize it:

$ bundle exec guard init
Writing new Guardfile to /home/ubuntu/workspace/sample_app/Guardfile
00:51:32 INFO minitest guard added to Guardfile, feel free to edit it

We then edit the resulting Guardfile so that Guard will run the right tests when the integration tests and views are updated (Listing 3.45). (Given its length and advanced nature, I recommend just copy-and-pasting the contents of Listing 3.45.)

Note: As of this writing, there is an interaction bug between Guard and Spring that causes all the tests to run every time. I’m keeping an eye on the issue and will update this section when it’s resolved.

Listing 3.45: A custom Guardfile.

# Defines the matching rules for Guard.
guard :minitest, spring: "bin/rails test", all_on_start: false do
  watch(%r{^test/(.*)/?(.*)_test\.rb$})
  watch('test/test_helper.rb') { 'test' }
  watch('config/routes.rb')    { integration_tests }
  watch(%r{^app/models/(.*?)\.rb$}) do |matches|
    "test/models/#{matches[1]}_test.rb"
  end
  watch(%r{^app/controllers/(.*?)_controller\.rb$}) do |matches|
    resource_tests(matches[1])
  end
  watch(%r{^app/views/([^/]*?)/.*\.html\.erb$}) do |matches|
    ["test/controllers/#{matches[1]}_controller_test.rb"] +
    integration_tests(matches[1])
  end
    watch(%r{^app/helpers/(.*?)_helper\.rb$}) do |matches|
      integration_tests(matches[1])
  end
  watch('app/views/layouts/application.html.erb') do
    'test/integration/site_layout_test.rb'
  end
  watch('app/helpers/sessions_helper.rb') do
    integration_tests << 'test/helpers/sessions_helper_test.rb'
  end
  watch('app/controllers/sessions_controller.rb') do
    ['test/controllers/sessions_controller_test.rb',
     'test/integration/users_login_test.rb']
  end
  watch('app/controllers/account_activations_controller.rb') do
    'test/integration/users_signup_test.rb'
  end
  watch(%r{app/views/users/*}) do
    resource_tests('users') +
    ['test/integration/microposts_interface_test.rb']
  end
end

# Returns the integration tests corresponding to the given resource.
def integration_tests(resource = :all)
  if resource == :all
    Dir["test/integration/*"]
  else
    Dir["test/integration/#{resource}_*.rb"]
  end
end

# Returns the controller tests corresponding to the given resource.
def controller_test(resource)
  "test/controllers/#{resource}_controller_test.rb"
end

# Returns all tests for the given resource.
def resource_tests(resource)
  integration_tests(resource) << controller_test(resource)
end

Here the line

guard :minitest, spring: "bin/rails test", all_on_start: false do

causes Guard to use the Spring server supplied by Rails to speed up loading times, while also preventing Guard from running the full test suite upon starting.

To prevent conflicts between Spring and Git when using Guard, you should add the spring/ directory to the .gitignore file used by Git to determine what to ignore when adding files or directories to the repository. The way to do this using the cloud IDE is as follows:

  1. Click on the gear icon in the upper right part of the file navigation pane (Figure 3.9).

    Figure 3.9

    Figure 3.9: The (rather subtle) gear icon in the file navigator pane.

  2. Select “Show hidden files” to show the .gitignore file in the application’s root directory (Figure 3.10).

    Figure 3.10

    Figure 3.10: Showing hidden files in the file navigator.

  3. Double-click on the .gitignore file (Figure 3.11) to open it, and then fill it with the contents of Listing 3.46.

    Figure 3.11

    Figure 3.11: The normally hidden .gitignore file made visible.

Listing 3.46: Adding Spring to the .gitignore file.

# See https://help.github.com/articles/ignoring-files for more about
# ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '˜/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore Byebug command history file.
.byebug_history

# Ignore Spring files.
/spring/*.pid

The Spring server is still a little quirky as of this writing, and sometimes Spring processes will accumulate and slow performance of your tests. If your tests seem to be getting unusually sluggish, it’s thus a good idea to inspect the system processes and kill them if necessary (Box 3.4).

Once Guard is configured, you should open a new terminal and (as with the Rails server in Section 1.3.2) run it at the command line as follows:

$ bundle exec guard

The rules in Listing 3.45 are optimized for this tutorial, automatically running (for example) the integration tests when a controller is changed. To run all the tests, hit return at the guard> prompt. (This may sometimes give an error indicating a failure to connect to the Spring server. To fix the problem, just hit return again.)

To exit Guard, press Ctrl-D. To add additional matchers to Guard, refer to the examples in Listing 3.45, the Guard README, and the Guard wiki.

Before proceeding, you should add your changes and make a commit:

$ git add -A
$ git commit -m "Complete advanced setup"
  • + Share This
  • 🔖 Save To Your Account