How to allow other calls to a method than those #expected

25 views
Skip to first unread message

David Trasbo

unread,
Apr 14, 2011, 12:46:12 PM4/14/11
to mocha-developer
A bit of background: I'm implementing a simple game using Gosu and
I've decided to write integration tests for it - which I believe
pretty much nobody did before. I'm using good old Test::Unit and
Mocha.

Here's the problem: Each test case renders the entire game but
generally focuses on one or more similar objects on the screen - how
they act and interact with other objects. Most objects are rendered
with the same method, Gosu::Window#draw_quad, so unless I comment out
the lines that render all other objects than those tested I'll get
tonnes of failures telling me there were unexpected calls to that
method, because it only expects a call that renders the ball, not the
players, e.g.

Is there way to allow "unexpected" calls to a method as long as the
the expectations I set are fulfilled?

Robert Pankowecki

unread,
Apr 14, 2011, 4:24:55 PM4/14/11
to mocha-d...@googlegroups.com
game.stubs(:draw_quad)
game.expects(:draw_quad).with(:pawn)

Expectations are matched in reverse order so if last is matched then
the exceptation is fulfulled otherwise it is interpreted as a call to
this stubbed definition.

Is that clear ?

Robert Pankowecki

Duncan Beevers

unread,
Apr 16, 2011, 10:57:19 AM4/16/11
to mocha-d...@googlegroups.com
Generally I try to avoid both stubbing and mocking the same method in
a single test.
For testing games I highly recommend pursuing a behavior-driven
approach. For example, if you're designing a Vehicle class, instead of
subclassing the vehicle to create a tank, you might mix in an Attack
behavior whose API can be tested independently of being mixed into a
concrete renderable object.
Hope this is clear and aids in your separation of concerns. Good luck.

- Duncan

> --
> You received this message because you are subscribed to the Google Groups
> "mocha-developer" group.
> To post to this group, send email to mocha-d...@googlegroups.com.
> To unsubscribe from this group, send email to
> mocha-develop...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/mocha-developer?hl=en.
>
>

David Trasbo

unread,
Apr 17, 2011, 4:46:38 AM4/17/11
to mocha-developer
That works perfectly! If I decide to move forward with this testing
style that'll be the way to go. Thanks.

On Apr 14, 10:24 pm, Robert Pankowecki <robert.pankowe...@gmail.com>
wrote:

David Trasbo

unread,
Apr 17, 2011, 4:51:42 AM4/17/11
to mocha-developer
Would you say that still applied for a very simple game? (I'm
implementing Pong). This is how I test player movement:
https://gist.github.com/b8ca44d4c77468dda000 The idea is to have an
integration test that #focuses_on a class for each behavior in the
game. Examples are: scoring, serving, bouncing, etc. I would then have
unit tests for everything else, such as core extensions.

On Apr 16, 4:57 pm, Duncan Beevers <dun...@dweebd.com> wrote:
> Generally I try to avoid both stubbing and mocking the same method in
> a single test.
> For testing games I highly recommend pursuing a behavior-driven
> approach. For example, if you're designing a Vehicle class, instead of
> subclassing the vehicle to create a tank, you might mix in an Attack
> behavior whose API can be tested independently of being mixed into a
> concrete renderable object.
> Hope this is clear and aids in your separation of concerns. Good luck.
>
> - Duncan
>

Duncan Beevers

unread,
Apr 18, 2011, 3:00:40 PM4/18/11
to mocha-d...@googlegroups.com
You might consider using a mock Window object rather than the real
Gosu object. That way you can carefully test just your player's
interaction with that piece of the system without invoking the
overhead of actually setting up a game.

It looks like you're doing a lot of sort of setting the Window up and
letting the game run without really decoupling the behavior of the
Player from her rendering.
With this kind of setup, you'll have to simulate batting the ball back
and forth in order to test scoring when batting the ball back and
forth isn't really what's under test.

In Gosu, the Window object does a lot of stuff, so you might consider
picking apart its functionality and injecting pieces into your player
class to drive those parts of your system.
For example, the Window object defines some rendering calls and
drawing bounds. It also takes care of updating the system during
ticks. It also handles user input. Each of these systems can be broken
out from Window and act as an intermediary between the Player and the
real Gosu Window object. This way you can test the interaction of your
player with regards to key-presses independently of how the Player is
rendered.

Hope this makes sense, and good luck.
- Duncan

David Trasbo

unread,
Apr 20, 2011, 5:05:02 PM4/20/11
to mocha-developer
Thanks for you answer!

Mocking out the Window object would only make sense if I was unit
testing the objects on the screen, but I think of these as functional/
integration tests with a focus - they test objects and their
interaction with other objects - so they should include the whole
stack.

Perhaps it's a terrible idea, but that's my aim for now. There are
some drawbacks as you say in that you have to simulate some gameplay/
do some setup to test the desired behavior, but I hope it won't be too
bad. Also, take a look at my refactored movement functional test:
https://gist.github.com/814023f0698cbe4af63d Add an API for simulating
key presses and I think that's pretty good.
> >https://gist.github.com/b8ca44d4c77468dda000The idea is to have an

Duncan Beevers

unread,
Apr 22, 2011, 11:11:15 PM4/22/11
to mocha-d...@googlegroups.com
Thanks for posting your progress and explaining your thinking.

These tests look pretty byzantine to me, and don't seem to really
afford much wiggle room in how player movement is implemented.

Tests are supposed to help you insure that your code works as you
expect while maintaining flexibility in its implementation, or even in
functionality.

For example, if you were to introduce an easing function into your
acceleration / deceleration the tests would be pretty difficult to
modify, and they definitely don't' seem to offer a clear path forward
should you decide to make this change test-first.

Perhaps the tests can be made more granular: When velocity is X,
pressing the Down button increases it by the result of this easing
function. When velocity is MAX, pressing the Down button does nothing.

It just feels like you're testing a potentially large number of
interactions in each test case (one assertion per test?) Which is
tenable in the early phases of a project, but could quickly lead to
brittle, hard-to-maintain tests down the road.

Please do correct me if you find this turns out otherwise.

- Duncan

James Mead

unread,
May 14, 2011, 6:04:51 AM5/14/11
to mocha-d...@googlegroups.com
Duncan,

Thanks for helping David out with lots of good advice.

David,

I hope you've found some useful ways to use Mocha in your tests.

Cheers, James.
----
Reply all
Reply to author
Forward
0 new messages