State-based expectations (as per jMock in GOOS)

Hi all

I’m working my way through Growing Object-Oriented Software[1],
currently at the start of chapter 15. Chapter 14 introduces a concept I
haven’t seen before, state-based expectations based on sent messages.

The principle appears to be

object O has sent message M => O is in state S

followed by

O is in state S => (expectation E met) passes spec
O is not in state S => (expectation E met) violates spec

Has anyone tried this with RSpec (mocks) yet? Just wondered if it was
doable with the current syntax support or would need an extension.

I thought I’d fire this off now to get ideas, as I won’t be coding using
this technique until I’ve finished the book (a week at least, I
imagine).

Cheers
Ashley

[1] http://www.amazon.co.uk/gp/product/0321503627/


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

On 18 Dec 2009, at 14:35, Ashley M. wrote:

The principle appears to be
object O has sent message M => O is in state S
followed by
O is in state S => (expectation E met) passes spec
O is not in state S => (expectation E met) violates spec

Can you elaborate? From a position of no knowledge, the most obvious
question to me is: why would I care about the state of O? Either the
change in O’s state is observable through its behaviour (in which case I
specify that behaviour) or it’s not (in which case I don’t care).

Cheers,
-Tom

On 18 Dec 2009, at 14:46, Tom S. wrote:

Can you elaborate? From a position of no knowledge, the most obvious question to me is: why would I care about the state of O? Either the change in O’s state is observable through its behaviour (in which case I specify that behaviour) or it’s not (in which case I don’t care).

On further investigation (aka reading up to chapter 24) it’s apparent
that this state-based testing is effectively a flexible form of message
expectation ordering. What’s clever is that it gives an intermediate
level between no ordering and sequential ordering. It’s like ordering
“sets” of expectations, at least that’s how it appears to me at first
glance.

Worth more investigation, I think…

Ashley


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran

On Dec 18, 2009, at 2:46 pm, Tom S. wrote:

Can you elaborate? From a position of no knowledge, the most obvious question to me is: why would I care about the state of O? Either the change in O’s state is observable through its behaviour (in which case I specify that behaviour) or it’s not (in which case I don’t care).

The example given is for an auction sniper (S). So,

Given S has just notified one of its listeners that it’s bidding
When S is informed that a bid has been made by a competitor
And the auction is closed
Then S should notify its listeners that it lost the auction

Given S has just notified one of its listeners that it’s bidding
When S is informed that its bid is highest
And the auction is closed
Then S should notify its listeners that it won the auction

The last one looks like the code below in Java[1], but note this is
further on from the code in chapter 14.

Interestingly, writing it as GWT transforms the style of the
expectations. eg,

“When S is informed that a bid has been made by a competitor”

replaces (something like)

Allow S to notify its listeners that it’s in the bidding state

Am I making sense? Not sure if these examples capture the essense.

Ashley

@Test public void
reportsWonIfAuctionClosesWhenWinning() {
allowingSniperBidding();
allowingSniperWinning();
ignoringAuction();

context.checking(new Expectations() {{
  atLeast(1).of(sniperListener).sniperStateChanged(
    new SniperSnapshot(ITEM_ID, 135, 135, WON));
  when(sniperState.is("winning"));
}});

sniper.currentPrice(123, 12, PriceSource.FromOtherBidder);
sniper.currentPrice(135, 45, PriceSource.FromSniper);
sniper.auctionClosed();

}

private void allowingSniperBidding() {
allowSniperStateChange(BIDDING, “bidding”);
}

private void allowingSniperWinning() {
allowSniperStateChange(WINNING, “winning”);
}

private void allowSniperStateChange(final SniperState newState, final
String oldState) {
context.checking(new Expectations() {{
allowing(sniperListener).sniperStateChanged(with(aSniperThatIs(newState)));
then(sniperState.is(oldState));
}});
}

[1]
http://github.com/sf105/goos-code/blob/master/test/unit/test/auctionsniper/AuctionSniperTest.java


http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran