rspec-2.5.0 is released!

February 6th, 2011

rspec-2.5 is a minor upgrade, and is fully backward compatible with rspec-2.4. It includes several bug fixes, enhancements, and one deprecation. See the changelog below for details.

We had a little glitch publishing the docs to http://relishapp.com/rspec, so the 2.5 docs won’t be up for another day or two, so I’ll detail the noticable differences here.

Autotest/Bundler integration

UPDATE: the –skip-bundler option does not work, and is removed from rspec-core-2.5.1. See the post on the 2.5.1 release for more information.

–skip-bundler

RSpec’s Autotest integration assumes that you want bundle exec in the shell command generated by Autotest if you have a Gemfile. This works fine for some situations, but not all, so we added an opt-out for rspec-2.5:

autotest -- --skip-bundler

Autotest ignores everything after the initial --, so RSpec’s Autotest extension handles the --skip-bundler option.

Autotest’s bundler plugin

Autotest ships with a plugin for bundler. Just add the following to a .autotest file in the project’s root directory, or your home directory:

require 'autotest/bundler'

This prefixes the generated shell command with ‘bundle exec’.

UPDATE: The implicit detection of Gemfile is removed from rspec-core-2.5.1. See the post on the 2.5.1 release for more information.

Implicit detection of Gemfile is deprecated

Given that Autotest has its own way of dealing with Bundler (see above), we deprecated the implicit assumption that Gemfile means “use bundler”. You’ll see a deprecation notice if you are relying on that, but it still works. It’s just a deprecation warning. To silence the warning, either use the --skip-bundler option or Autotest’s bundler plugin, described above.

HTML Formatter

The HTML formatter now has a set of checkboxes in the header that allow you to filter what you’re looking at:

to not, or not to not

Are you the sort of person for whom “expect this block of code to not raise an error” is like nails on chalkboard? If so, relief has arrived. You may now type either of the following, and RSpec will happily service you:

expect { ... }.to_not raise_error
expect { ... }.not_to raise_error

Changelog

rspec-core-2.5.0

full changelog

  • Enhancements

    • Autotest::Rspec2 parses command line args passed to autotest after ‘–’
    • –skip-bundler option for autotest command
    • Autotest regexp fixes (Jon Rowe)
    • Add filters to html and textmate formatters (Daniel Quimper)
    • Explicit passing of block (need for JRuby 1.6) (John Firebaugh)
  • Bug fixes

    • fix dom IDs in HTML formatter (Brian Faherty)
    • fix bug with –drb + formatters when not running in drb
    • include –tag options in drb args (monocle)
    • fix regression so now SPEC_OPTS take precedence over CLI options again (Roman Chernyatchik)
    • only call its(:attribute) once (failing example from Brian Dunn)
    • fix bizarre bug where rspec would hang after String.alias :to_int :to_i (Damian Nurzynski)
  • Deprecations

    • implicit inclusion of ‘bundle exec’ when Gemfile present (use autotest’s bundler plugin instead)

rspec-expectations-2.5.0

full changelog

  • Enhancements

    • should exist works with exist? or exists? (Myron Marston)
    • expect { ... }.not_to do_something (in addition to to_not)
  • Documentation

    • improved docs for raise_error matcher (James Almond)

rspec-mocks-2.5.0

full changelog

  • Bug fixes
    • message expectation counts now work in combination with a stub (Damian Nurzynski)
    • fix failure message when message received with incorrect args (Josep M. Bach)

rspec-rails-2.5.0

full changelog

  • Enhancements

    • use index_helper instead of table_name when generating specs (Reza Primardiansyah)
  • Bug fixes

    • fixed bug in which render_views in a nested group set the value in its parent group.
    • only include MailerExampleGroup when it is defiend (Steve Sloan)
    • mock_model.as_null_object.attribute.blank? returns false (Randy Schmidt)
    • fix typo in request specs (Paco Guzman)

rspec-2 and autotest

March 15th, 2010

[Updated on 17 March, 2010]

I just released rspec-2.0.0.beta.4 with support for autotest, among other enhancements. Autotest integration is going to be a bit different in rspec-2. We’re removing the autospec command, which did nothing but set an environment variable and call autotest.

In rspec-2, you’ll use the autotest command directly, but doing so requires a small bit of configuration. As of beta.4, you’ll have to do add this configuration manually. Just create an autotest directory in the root of your project, put the following statement in ./autotest/discover.rb:

Autotest.add_discovery { "rspec2" }

The final 2.0.0 release will include a generator (even for non-rails projects) that will add this for you.

limiting scope of autotest

March 5th, 2008

If you use autotest with rspec or test/unit, you’ve probably had this experience (or one like it):

You want to add some new behaviour to a model object, so you write a spec, watch it fail, make it pass, and then wait until the entire spec suite runs. Even if you’ve got a fast-running suite, this can be painful sometimes.

Wouldn’t it be great if you could limit the scope of what directories autotest observes? Well it turns out that you can! Recent releases of ZenTest include a find_directories attribute on the autotest object. Just add this to your .autotest file:

Autotest.add_hook :initialize do |at|
  unless ARGV.empty?
    at.find_directories = ARGV.dup
  end
end

and then you can say:

autotest app/models spec/models

and it will only observe those directories. This is nice and flexible, but I find that most of the time I’m wanting pairs like that: app/models and spec/models, or app/views/accounts and spec/views/accounts. In that case, I’d really like to just say:

autotest models

To accomplish that you can do this to the hook instead:

Autotest.add_hook :initialize do |at|
  unless ARGV.empty?
    at.find_directories = ["spec/#{ARGV.first}","app/#{ARGV.first}"]
  end
end

Want the best of both worlds? Try this:

Autotest.add_hook :initialize do |at|
  unless ARGV.empty?
    at.find_directories = ARGV.length == 1 ? ["spec/#{ARGV.first}","app/#{ARGV.first}"] : ARGV.dup
  end
end

The only limitation of this is that it’s based on directories, not files. Once in a while, when I’m bootstrapping a new object, I’ll keep the examples and the implementation in the same file until I’ve got things fleshed out a bit the object is ready to play nice with others. In that case, I might like to just point autotest to that one file. I started working on a patch for this for ZenTest, but I’m not sure it’s worth the extra effort. What do you think?

Regardless – happy auto-exemplifying!

RSpec-1.1.2 and ZenTest-3.8.0

January 15th, 2008

The RSpec-1.1.2 release includes changes to keep RSpec compatible with autotest in ZenTest-3.8.0. This new ZenTest release boasts an improved cascading configuration model that works well for subclasses (like those that ship with RSpec) and allows users to override the mappings of specs (or tests) to code as well as the list of files that get ignored by autotest.

To support this, Autotest now loads the following files in the following order:

Autotest
AutotestSubClass
~/.autotest
./.autotest

This allows RSpec (or any other library) to override defaults set in Autotest, and then provides users both generic (~/.autotest) and project specific (./.autotest) control over the mappings and exceptions.

How can you take advantage of this?

When autotest begins to run, it calls its :initialize hook. This hook is exposed by the add_hook method. You can use this to access the mappings and exceptions using the following methods on Autotest:

clear_mappings()
add_mapping(regexp, proc)
remove_mapping(regexp)
 
clear_exceptions()
add_exception(string)
remove_exception(string)

add_mapping

The add_mapping method adds a key/value pair to a hash that maps regexps to procs. Whenever autotest senses that a file is touched, it looks for the regexp that matches the file name and the runs all the files returned by the associated proc.

Imagine you’re working on a shopping cart app. You have some currency conversion behaviour in a Product model that you’d like to extract to an acts_as_currency plugin, and you want autotest to observe the process. You might add a mapping like this to .autotest:

Autotest.add_hook :initialize do |at|
  at.add_mapping(%r%^plugins/acts_as_currency/lib/.*\.rb$%) {
    at.files_matching %r%^spec/models/product_spec\.rb$% +
    at.files_matching %r%^plugins/acts_as_currency/spec/.*_spec\.rb$%
  }
end

In this case, a change to any of the files in the plugin’s lib directory would cause all the plugins specs to run, as well as the spec for the Product model.

add_exception

The add_exception method adds paths to a list of paths that Autotest ignores.

I like to run autotest in verbose mode (autotest -v) because it tells me when I change a file that it doesn’t know what to do with. The drawback is that it wants to tell me every time I commit because files in the .svn/.hg/.git directories change. So I’ve got these all listed as exceptions in my ~/.autotest file, along with assorted others:

Autotest.add_hook :initialize do |at|
  %w{.svn .hg .git}.each {|exception|at.add_exception(exception)}
end

Note that autotest compiles this list to a Regexp with no anchors, so .hgignore and .gitignore would also get ignored in this case.

Cascading config and granular control

One of the coolest changes in ZenTest-3.8.0 is that autotest loads both ~/.autotest and ./.autotest. So now you can have the hooks you like on every project (like growl notifation) all in one place and still have project specific settings.

This also allows you to set up global mappings/exceptions and modify them at the project level. See Autotest’s RDoc for more info.