Archive

Archive for the ‘Spock Framework’ Category

Poll: Help us make Spock rock the (testing) universe!

July 7, 2010 5 comments

Since its first release in March 2009, Spock has come a long way. Time to ask you where to head next! Please take a moment to share your thoughts. Thanks!

Categories: Spock Framework

What’s New In Spock 0.4? Episode 2: Better Mocking

June 13, 2010 7 comments

As you may know, Spock comes with its own mocking framework, tightly integrated with the rest of the specification language. While certainly useful and already quite powerful, the mocking framework used to be one of the lesser developed parts of Spock, and had a few rough edges. Well, not anymore! Here are the improvements we’ve made for 0.4:

1. All mocks are thread-safe

Previously, things could go wrong if a mock was called from a thread other than the spec runner’s thread. Now, the mocking framework will behave correctly no matter how many threads you throw at it.

2. Vararg syntax

In Groovy, all methods whose last parameter has an array type can be called with vararg syntax (even methods implemented in Java). Therefore, it was only logical for Spock to support the same vararg syntax when defining interactions with such methods. Here is an example.

Suppose you have the following Java interface:

class Subscriber {
  public void receive(String... messages); // or: receive(String[] messages)
}

An interaction between a Publisher and its Subscriber could be described as follows:

given:
def publisher = new Publisher() // this is the object under test
def subscriber = Mock(Subscriber)
publisher.add(subscriber)

when:
publisher.sendNotifications() // let's say this should send "foo", "bar", and "baz"

then:
1 * subscriber.receive("foo", "bar", "baz") // vararg syntax

Alternatively, you could describe the interaction as follows:

then:
1 * subscriber.receive(["foo", "bar", "baz"]) // list syntax

Prior to 0.4, only the list syntax would have worked; the vararg syntax would have resulted in an InteractionNotSatisfiedError.

3. Sensible defaults for toString(), equals(), and hashCode()

Previously, a mock object’s toString(), equals(), and hashCode() methods didn’t get any special treatment. If you didn’t say otherwise, they would always return null, false, and 0, respectively. As of 0.4, more sensible defaults are in place: toString() now returns a descriptive message, equals() implements object identity, and hashCode() delegates to System.identityHashCode() (which behaves like Object.hashCode()).

Another change is that toString(), equals(), and hashCode() no longer match the wildcard method (as in “1 * foo._()”). This prevents tests from failing in the presence of tools like debuggers, which often call these methods for their own purposes.

Despite all this, toString(), equals(), and hashCode() can still be stubbed (and even mocked) like any other method, overriding their default behavior. Most Java mocking frameworks don’t support this feature.

4. _ as an abbreviation for _._

By default, Spock allows interactions that haven’t been specified explicitly, and returns default values (null, 0, false) for them. This helps to avoid over-specification and makes tests more resilient to change. In cases where you want to be more strict, add the following as your last interaction:

0 * _._ // no (other) call of any method on any mock object

In 0.4, this can be abbreviated to:

0 * _  // nothing else!
5. Support for property syntax

Properties and getter methods can now be stubbed with property syntax:

item.price >> 42

However, mocking a property setter still requires method syntax:

1 * item.setPrice(42) // not: 1 * (item.price = 42)
6. Ordered interactions

By default, interactions may occur in any order. For example:

when:
...

then:
1 * foo.moo()
2 * bar.baz()

Here we are expecting a total of three calls, but don’t demand a particular order. As a consequence, the following invocation order would be acceptable:

bar.baz()
foo.moo()
bar.baz()

In general this is a good thing, because it prevents you from specifying unimportant details which might change over time. However, sometimes order is really important. Therefore, you can now impose ordering constraints by using multiple then-blocks:

when:
...

then:
1 * tank.fill()
1 * door.close()

then:
1 * plane.takeOff()

To paraphrase: “I don’t care if you first fill the tank or close the cabin door, but you must do both before takeoff!” If this constraint isn’t met, Spock will throw a WrongInvocationOrderError.

That’s it for better mocking in Spock 0.4. In the next part of this series, we’ll have a look at how Spock 0.4 simplifies testing concurrent code.

Categories: Spock Framework

What’s New In Spock 0.4? Episode 1: Data Tables

March 11, 2010 22 comments

With the Spock Framework 0.4 release around the corner, I thought it was time to demonstrate some of the upcoming new features (which are already available in recent snapshots). So here comes the first episode in the mini-series “What’s New In Spock 0.4”. Today’s topic is data tables, a new way to write data-driven test methods.

Data-driven testing has always been one of Spock’s strong points. To give you some background, let’s have a look at a typical example taken from the spock-example project:

def "maximum of two numbers"() {
  expect:
  Math.max(a, b) == c

  where:
  a << [3, 5, 9]
  b << [7, 4, 9]
  c << [7, 5, 9]
}

This method is testing the Math.max() operation. The expect block contains the test logic (what we expect from the Math.max() operation), and the where block contains the test data. The key to interpreting the where block is to read it from top to bottom. That is, variables a, b, and c will be assigned values 3, 7, and 7 for the first run of the method; values 5, 4, and 4 for the second run; and values 9, 9, and 9 for the third run. We say that the method has three iterations.

Data-driven test methods are a powerful tool, but the where block syntax shown above suffers from two problems:
1. It is a bit noisy (shift operators, brackets, commas)
2. It is read from top to bottom, which is less intuitive than reading from left to right (at least for people used to left-to-right languages).

This is where data tables come in. Their purpose is to provide a convenient syntax for in-line test data. Let’s modify the previous example to use a data table:

def "maximum of two numbers"() {
  expect:
  Math.max(a, b) == c

  where:
  a | b | c
  3 | 7 | 7
  5 | 4 | 5
  9 | 9 | 9
}

Run this example in Spock Web Console

Now the where block reads like a table. The first row (the table header) specifies the data variables, and the remaining rows specify their values for each iteration. Compared to the previous example, this one is both nicer to read and write.

As demonstrated in their specification, data tables cannot just hold literals but also more complex expressions. However, other forms of parameterizing a test method (like the one we saw in the first example) haven’t lost their value. For example, loading data from external sources is still best left to multi-parameterizations:

where:
[a, b, c] << sql.rows("select a, b, c from maxdata")

See DatabaseDriven for the full example.

Apart from the different syntax, data tables behave like all other forms of parameterizations. For example, their data variables can be optionally declared as method parameters, and they can be combined with derived parameterizations. To learn more about the different forms of parameterizations, see their documentation.

That’s it for the first episode of “What’s New In Spock 0.4”. Please tune in tomorrow for the second episode. Until then, I’ll leave you with a real-world usage of data tables taken straight from the Sales Intelligence Engine codebase:

@Unroll
def "determine dominant color"() {
  when:
  action.image = image
  action.ignoreWhite = ignoreWhite	
  action.execute()
	
  then:
  action.dominantColor == dominantColor		
			
  where:
  image                   | ignoreWhite | dominantColor 
  '/images/white.png'     | false       | 'ffffff'
  '/images/black.png'     | true        | '000000'
  '/images/28843_300.jpg' | true        | 'ffcc33' 
  '/images/20341_300.jpg' | true        | 'cc6666'
  '/images/20692_300.jpg' | true        | 'cccccc' 
  '/images/7870_300.jpg'  | true        | '993333'
}
Categories: Spock Framework