DRYing up Jasmine Specs with Shared Behavior

May 29, 2011 Davis W. Frank

When writing nicely encapsulated code and you have a group of objects that share an interface (pick your favorite patterns), you often want to share your test code as well. If the system models financial accounts with credits and debits, and you make a change to the reconciliation code, you want to run a core set of specs against all cash, loan, and credit card account objects.

People ask how to do this in JavaScript on the Jasmine mailing list every so often.

So here’s an example of “Shared Example Groups” in Jasmine.

This Game spec looks totally fine for a basic ball game. But what if I want to have multiple different types of ball games?

Here are specs for Basketball and (American) Football:

The specs related to the Game itself are inline. That doesn’t feel very DRY and really, we want to test the interface with the same code. We’re working in JavaScript. So we write a function.

Jasmine works by building up all the functions to execute at spec run time. When you call describe, the passed-in function is executed immediately. Inside the describe, the calls to beforeEach, afterEach and it queue up the passed-in functions for execution later, when you want to run your specs.

This means you can put all of your shared specs, including any beforeEach calls, in a function that can be executed as needed. Like this:

Each time sharedBehaviorForGameOf is called, the three before and two spec functions are queued up. Call it twice and you’ll wind up with four new specs in your Jasmine environment.

And since it’s a function, yes, you can pass parameters. The context parameter can be used to pass in a ball and a game for use in the shared specs. Since the “(shared)” describe function is called each time sharedBehaviorForGameOf is called, there will be a separate closure for the local ball and game.

So now we can refactor our specs to use our function.

This is a useful technique, but use it appropriately and with a little caution. Use it in situations for consistent testing, not just to DRY up your specs for DRY-ness’s sake.

Keep the varied behavior (like the field goal scoring above) outside your shared behavior function instead of using the parameters. The parameters should be for the object(s) under test, not their behavior.

And lastly, (as always) keep your mind on your JavaScript closures.

About the Author

Biography

More Content by Davis W. Frank
Previous
The Business of Apps: Farhan Thawar @meshconference 2011
The Business of Apps: Farhan Thawar @meshconference 2011

Xtreme Labs’ Farhan Thawar, VP of Engineering spoke at the 2011 mesh Conference in Toronto, Ontario. Togeth...

Next
A Few of Our Favorite Cloud Foundry Apps
A Few of Our Favorite Cloud Foundry Apps

Since Cloud Foundry’s launch six weeks ago, there have been thousands of applications deployed on CloudFoun...