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.
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:
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
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:
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
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.