On Github tbialecki / spock-workshop-lectures
... a developer testing and specification framework
... for Java and Groovy
... compatible with most IDEs, build tools, and continuous integration servers
... is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans
public class HelloWorldTest { @Test public void plusPlusIShouldIterate() { //given int i = 0; //when i = ++i; //then assertEquals(i, 1); } }
class HelloWorldTest extends Specification { def "++i should iterate"() { given: def i = 0 when: i = ++i then: i == 1 } }
class HelloWorldTest extends Specification { def "++i should iterate"() { given: "i variable" def i = 0 when: "using ++ operator" i = ++i then: "i should be equal 1" i == 1 } }
class HelloWorldTest extends Specification { def "++i should iterate"() { given: "i variable" def i = 0 and: "some programming skills" //the programming skills when: "using ++ operator" i = ++i then: "i should be equal 1" i == 1 } }
class HelloWorldTest extends Specification { def "++i should iterate"() { given: def i = 0 expect: ++i == 1 } }
class LifecycleTest extends Specification { @Shared def objectUnderTest = new Simple(); def setup() { ... } def cleanup() { ... } def setupSpec() { ... } def cleanupSpec() { ... } }
class HelloWorldTest extends Specification { def "failing tests should give reasonable output message"() { when: def list = [[1, 2, 3], [2, 3, 4]]; then: list.get(0).sum() == 7 } }
Condition not satisfied: list.get(0).sum() == 7 | | | | | | 6 false | [1, 2, 3] [[1, 2, 3], [2, 3, 4]]
...
class DataDrivenTest extends Specification { def "Math.max should determine max value"(int a, int b, int max) { expect: Math.max(a, b) == max where: a | b || max 1 | 2 || 2 1 | 1 || 1 3 | 2 || 3 } }
class DataDrivenTest extends Specification { def "Math.max should determine max value"() { expect: Math.max(a, b) == max where: a | b || max 1 | 2 || 2 1 | 1 || 1 3 | 2 || 3 } }
class DataDrivenTest extends Specification { def "Math.max should determine max value"(int a, int b, int max) { expect: Math.max(a, b) == max where: a << [1, 1, 3] b << [2, 1, 2] max << [2, 1, 3] } }
...
Own mocking implementation
... tightly integrated with Spock features
... but not obligatory
class Publisher { List<Subscriber> subscribers void send(String message) } interface Subscriber { void receive(String message) }
def "should notify subscriber"() { given: def publisher = new Publisher(); def subscriber = Mock(Subscriber); publisher.subscribers << subscriber; when: publisher.send("hello") then: 1 * subscriber.receive("hello") }
1 * subscriber.receive("hello") // exactly one call 0 * subscriber.receive("hello") // zero calls (1..3) * subscriber.receive("hello") // between one and three calls (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls
1 * subscriber.receive("hello") // a call to 'subscriber' 1 * _.receive("hello") // a call to any mock object
1 * subscriber.receive("hello") // a method named 'receive' 1 * subscriber./r.*e/("hello") // a method whose name matches // the given regular expression
1 * subscriber.receive("hello") // an argument that is equal // to the String "hello" 1 * subscriber.receive(!"hello") // an argument that is unequal // to the String "hello"
1 * subscriber.receive() // the empty argument list
1 * subscriber.receive(_) // any single argument
1 * subscriber.receive(*_) // any argument list
1 * subscriber.receive(!null) // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument // that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies // the given predicate
1 * process.invoke("ls", "-a", _, !null, { ["abcd"].contains(it) })
interface Subscriber { String receive(String message) }
subscriber.receive("message1") >> "ok" subscriber.receive("message2") >> "fail"
subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
subscriber.receive(_) >> { args -> args[0].size()>3 ? "ok": "nok" }
subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw new InternalError() } >> "ok"
@Ignore def "I won't run"() { ... } @IgnoreRest def "Only it will run"() { ... } @IgnoreIf({ os.windows }) def "I'll run everywhere but on Windows"() { ... } @Requires({ os.windows }) def "I'll only run on Windows"() { ... }
@Stepwise class RunInOrderSpec extends Specification { ... } @Timeout(10) class TimedSpec extends Specification { ... }
@ContextConfiguration(classes = SampleComponentTestConfig) class SampleComponentTest extends Specification { @Autowired SampleComponent sampleComponent; def "should do it"() { when: def output = sampleComponent.doIt(); then: output == "I`m doing"; } @Configuration public static class SampleComponentTestConfig { @Bean public SampleComponent sampleComponent() { return new SampleComponent(); } } }