New mock objects framework

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

New mock objects framework

Denis Kudriashov
I realize new smalltalk mock objects framework named BehaviorMockup with SSpec functionality.
There is Squeak (http://www.squeaksource.com/BehaviorMockup.html) and VW versions (cincom public repository)

Simplest language for behavior specfications:

[:mock | mock someMessage] should strictly satisfy: [:mock | mock someMessage willReturn: 'some']

or

[:mock | mock someMessage] should lenient satisfy: [:mock | mock someMessage willReturn: 'some']

SSpec functionality:

  • 5 should equals: 6
  • and ...
For more detailes see Wiki on SqueakSource and many acceptance tests in package

Best regards,
Denis


Reply | Threaded
Open this post in threaded view
|

Re: New mock objects framework

Robert Krahn
Hello Denis,

I dipped into your BehaviorMockup package and it seems really powerful. I like the block notation so that the expected behavior is stated after the exercised code. This way the tests can be more uniform (Four-Phase Test) and clearer.

One thing I didn't found out is how to have the mocks ignore certain message calls.
E.g. I want this to pass:
[:mock | mock m1; m2] should lenient satisfy: [:mock | mock m1]

I tried it the 'lenient way' as above but I get a SpecFailed: WrongMessageSelector. How can one do this?

Best regards,
Robert

Am 20.08.2007 um 11:32 schrieb Denis Kudriashov:

I realize new smalltalk mock objects framework named BehaviorMockup with SSpec functionality.
There is Squeak (http://www.squeaksource.com/BehaviorMockup.html) and VW versions (cincom public repository)

Simplest language for behavior specfications:

[:mock | mock someMessage] should strictly satisfy: [:mock | mock someMessage willReturn: 'some']

or

[:mock | mock someMessage] should lenient satisfy: [:mock | mock someMessage willReturn: 'some']

SSpec functionality:

  • 5 should equals: 6
  • and ...
For more detailes see Wiki on SqueakSource and many acceptance tests in package

Best regards,
Denis




Reply | Threaded
Open this post in threaded view
|

Re: New mock objects framework

Denis Kudriashov
2007/9/19, Robert Krahn <[hidden email]>:
Hello Denis,

I dipped into your BehaviorMockup package and it seems really powerful. I like the block notation so that the expected behavior is stated after the exercised code. This way the tests can be more uniform (Four-Phase Test) and clearer.

One thing I didn't found out is how to have the mocks ignore certain message calls.
E.g. I want this to pass:
[:mock | mock m1; m2] should lenient satisfy: [:mock | mock m1]

I tried it the 'lenient way' as above but I get a SpecFailed: WrongMessageSelector. How can one do this?

Best regards,
Robert

p.s.
I wrote this mail to the squeak-dev mailing list first but forgot to add your mail address in the header so I am writing you an extra mail.

Hi Robert.

Expression

[:mock | mock m1; m2] should lenient satisfy: [:mock | mock m1]

creates and verifies LenientBehaviorSpec. It only defines arbitrary message sends order.

If you want mock ignores any message sends you must write something like:

[:mock | mock m1; m2] should lenient satisfy: [:mock | mock anyMessage. mock m1]

But it is not implemented yet. I think it takes a few hours work..

Possible implementation:
  • Create subclass MessageSemanticsSpec named like AnyMessageSemanticsSpec
  • Implement #validate: method like in MessageSemanticsSpec but without some testings for message selector and arguments
  • Change method BehaviorSpecBuilder>>evaluateBehavior:
aMessageSend selector = #anyMessage ifTrue: [
messageSendSpec := MessageSendSpec new.
messageSendSpec add: (AnyMessageSemanticsSpec from: aMessageSend).
spec add: messageSendSpec.
 ^MessageSendSpecBuilder on: messageSendSpec]
 
messageSendSpec := MessageSendSpec withMessageSemanticsLike: aMessageSend.
spec add: messageSendSpec.
 ^MessageSendSpecBuilder on: messageSendSpec

With that stuff you can write specification for ignoring any message any times:

mock anyMessage useArbitrary

And use null object (with eating message sends):

mock anyMessage
useArbitrary
willReturn: Null new

Of course you can implement some nice helper messages for it.

Sorry for my english.

Best regards,
Denis



Reply | Threaded
Open this post in threaded view
|

Re: New mock objects framework

Robert Krahn
Hello Denis,

thank you very much for your detailed explanations! This was really helpful for understanding how the behavior verification works. The implementation of ignoring of message sends basically worked fine this way.

Concerning this I would like to know if the following expression should pass or raise a WrongMessageSelector failure:

[:mock | mock message1; message2]  should strictly satisfy: 
[:mock | mock message2 useArbitrarily. mock message1.].

Actually the StrictBehaviorSpec requires that #message2 should be called before #message1. The arbitrarily property only specifies that the number of invocations of #message2 is not important. If so, the expression ought to fail with the invocation of #message2. Is that correct?

Best regards,
Robert

Am 19.09.2007 um 14:32 schrieb Denis Kudriashov:

2007/9/19, Robert Krahn <[hidden email]>:
Hello Denis,

I dipped into your BehaviorMockup package and it seems really powerful. I like the block notation so that the expected behavior is stated after the exercised code. This way the tests can be more uniform (Four-Phase Test) and clearer.

One thing I didn't found out is how to have the mocks ignore certain message calls.
E.g. I want this to pass:
[:mock | mock m1; m2] should lenient satisfy: [:mock | mock m1]

I tried it the 'lenient way' as above but I get a SpecFailed: WrongMessageSelector. How can one do this?

Best regards,
Robert

p.s.
I wrote this mail to the squeak-dev mailing list first but forgot to add your mail address in the header so I am writing you an extra mail.

Hi Robert.

Expression

[:mock | mock m1; m2] should lenient satisfy: [:mock | mock m1]

creates and verifies LenientBehaviorSpec. It only defines arbitrary message sends order.

If you want mock ignores any message sends you must write something like:

[:mock | mock m1; m2] should lenient satisfy: [:mock | mock anyMessage. mock m1]

But it is not implemented yet. I think it takes a few hours work..

Possible implementation:
  • Create subclass MessageSemanticsSpec named like AnyMessageSemanticsSpec
  • Implement #validate: method like in MessageSemanticsSpec but without some testings for message selector and arguments
  • Change method BehaviorSpecBuilder>>evaluateBehavior:
aMessageSend selector = #anyMessage ifTrue: [
messageSendSpec := MessageSendSpec new.
messageSendSpec add: (AnyMessageSemanticsSpec from: aMessageSend).
spec add: messageSendSpec.
 ^MessageSendSpecBuilder on: messageSendSpec]
 
messageSendSpec := MessageSendSpec withMessageSemanticsLike: aMessageSend.
spec add: messageSendSpec.
 ^MessageSendSpecBuilder on: messageSendSpec

With that stuff you can write specification for ignoring any message any times:

mock anyMessage useArbitrary

And use null object (with eating message sends):

mock anyMessage
useArbitrary
willReturn: Null new

Of course you can implement some nice helper messages for it.

Sorry for my english.

Best regards,
Denis





Reply | Threaded
Open this post in threaded view
|

Re: New mock objects framework

Denis Kudriashov
Hi Robert,

thank you very much for your detailed explanations!

 Thank you for your interest! :)

Concerning this I would like to know if the following expression should pass or raise a WrongMessageSelector failure:

[:mock | mock message1; message2]  should strictly satisfy: 
[:mock | mock message2 useArbitrarily. mock message1.].

This should pass. #useArbitrarily here specifies that #message2 can be recieved "anywhere" (zero or several times). And it also means that the message invocation does not depend on the kind of specification (strict or lenient etc.).
 
The idea of #useArbitrarily here is to stress the fact, that though invokation of #message2 is expected, it's not the essence of the spec. But #message1 actually is. And we give some freedom for the sequense of sends in implementation.

Best regards,
Denis