[rspec-users] Assumption tests

Pat Maddox pergesu at gmail.com
Fri Oct 19 12:29:23 EDT 2007

On 10/19/07, Daniel Tenner <daniel.ruby at tenner.org> wrote:
> > If I read correctly, Daniel is suggesting that this is not behaviour
> > because he's equating behaviour with interaction. This example checks
> > an outcome, not an interaction.
> >
> That's right, one of my axioms is that "specifying" involves
> behaviour/interaction, not state/outcome.

To be honest, I think you're way off the mark.  Objects behave in two
ways: they manipulate their state, or they interact with other
objects.  Both are valid types of behavior and can be used for

There's a more subtle problem with your argument though, and that's
that as far as specs are concerned, there is no state!


# given
@account = Account.new 500

# when
@account.withdraw 300

# then
@account.balance.should == 200

The behavior of this object is quite simple.  However, do we know
anything about the implementation?  Do we care to know?

You might reasonably think Account is implemented as
class Account
  attr_reader :amount

  def initialize(balance = 0)

  def withdraw(amount)
    @balance -= amount

You'd be wrong though.  It's actually implemented as
class Account
  def initialize(balance = 0)
    Transaction.new self, balance

  def withdraw(amount)
    Transaction.new self, -amount

  def balance
    Transaction.for(self).inject(0) { |sum, t| sum += t.amount }

(that's the beauty of mailing list examples - I'm always right! :)

Calling withdraw doesn't reduce the account balance.  It reduces the
balance reported by the account.  It's a subtle distinction, and one
that's not important to think about 99% of the time.  Hopefully though
you see why it's a fallacy to discount state-based testing as a valid
specification technique.  As long as you're using an object's API, and
not digging into it's internal state as in David's evil example,
you're dealing with behavior.


More information about the rspec-users mailing list