Skip to content

Instantly share code, notes, and snippets.

@ryanb
Created December 6, 2012 01:04
Show Gist options
  • Save ryanb/4221051 to your computer and use it in GitHub Desktop.
Save ryanb/4221051 to your computer and use it in GitHub Desktop.
Alternative expectation interface for MiniTest and RSpec

Expectations

I took the ideas presented here and built a gem called Mustard. Check it out!

There are several expectation/assertion interfaces available for writing tests/specs. Here are some issues I have with them.

Test::Unit/MiniTest

  • The order of assert_equals feels backwards
  • Oh wait, that should be assert_equal (that too)
  • I like to write the subject first

MiniTest::Spec

  • Adds 30+ methods to Object
  • Any matchers you want to add are another method on Object
  • Still too few matchers, so it's ugly: foo.must_be :<, 10

Bacon

  • too.many.method.calls.to.simulate.english

RSpec Should

  • The space makes for some awkward syntaxes that cause warnings (when used with ==, >, etc.)
  • eq() and such aren't bad, but may need parenthesis
  • Pollutes the spec context with methods for each matcher

I haven't used the RSpec expect() interface enough to know cons.

Proposed Solution

# should returns an object which can have matchers called on it
5.should.eq 5
5.should.equal 5

# should_not can be used to do a reverse match
5.should_not.equal 7

# some comparison matchers
5.should.be_less_than 8
5.should.be_greater_than 3
5.should.be_lt 8
5.should.be_gt 3
5.should.be_gte 5
true.should.be_true
false.should.be_false

# call the method and see if it is true
[].should.be :empty?
5.should.be :between?, 3, 7

# add matchers
Should.matcher :be_empty do # any args will be passed into block
  empty? # runs in the context of the object and returns true/false
end
[].should.be_empty
[].should_not.be_empty # message: Expected [] to not be empty

# add matcher through class
Should.matcher :be_empty, BeEmptyMatcher
class BeEmptyMatcher
  # methods in here for defining behavior and messages.
end

I like this because it does not pollute the Object space much (just shouldand should_not). Also every method called after it is simply a matcher. No crazy method chains.

What do you think? If there's enough interest I'll write this up as a plugin for both RSpec-Core and MiniTest.

@mattconnolly
Copy link

I would prefer:

[].must.be_empty

I think is better than be :empty? What if something was supposed to be a symbol and you are explicitly looking for the symbol :empty? ??

@jonah-williams
Copy link

If you're still considering interfaces have you looked at https://github.com/sconover/wrong ?

@hopsoft
Copy link

hopsoft commented Dec 7, 2012

I have similar objections to the test frameworks you call out. Unfortunately I don't care for expectations either. Here's my attempt to answer the problem. MicroTest

@aptinio
Copy link

aptinio commented Dec 8, 2012

+1 on checking Wrong out (https://github.com/sconover/wrong). I think it addresses a lot of the issues you listed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment