Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer block name 'given' over 'setup' #786

Merged
merged 3 commits into from
Nov 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions docs/data_driven_testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Math.max(a, b) == c

The obvious question is: Which iteration failed, and what are its data values? In our example, it isn't hard to figure
out that it's the second iteration that failed. At other times this can be more difficult or even impossible.
footnote:[For example, a feature method could use data variables in its `setup:` block, but not in any conditions.]
footnote:[For example, a feature method could use data variables in its `given:` block, but not in any conditions.]
In any case, it would be nice if Spock made it loud and clear which iteration failed, rather than just reporting the
failure. This is the purpose of the `@Unroll` annotation.

Expand Down Expand Up @@ -289,5 +289,3 @@ include::{sourcedir}/datadriven/DataSpec.groovy[tag=unrolled-3a]
...
include::{sourcedir}/datadriven/DataSpec.groovy[tag=unrolled-3b]
----


Binary file modified docs/images/Blocks2Phases.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions docs/interaction_based_testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ target constraint
A stubbed interaction can be declared in the usual places: either inside a `then:` block, or anywhere before a
`when:` block. (See <<Where to Declare Interactions>> for the details.) If a mock object is only used for stubbing,
it's common to declare interactions <<declaring-interactions-at-creation-time,at mock creation time>> or in a
`setup:` block.
`given:` block.

=== Returning Fixed Values

Expand Down Expand Up @@ -649,7 +649,7 @@ statements will _not_ work:

[source,groovy]
----
setup:
given:
subscriber.receive("message1") >> "ok"

when:
Expand All @@ -662,7 +662,7 @@ then:
As explained in <<Where to Declare Interactions>>, the `receive` call will first get matched against
the interaction in the `then:` block. Since that interaction doesn't specify a response, the default
value for the method's return type (`null` in this case) will be returned. (This is just another
facet of Spock's lenient approach to mocking.). Hence, the interaction in the `setup:` block will never
facet of Spock's lenient approach to mocking.). Hence, the interaction in the `given:` block will never
get a chance to match.

NOTE: Mocking and stubbing of the same method call has to happen in the same interaction.
Expand Down Expand Up @@ -974,4 +974,3 @@ http://martinfowler.com/articles/mocksArentStubs.html[Mocks Aren't Stubs]::

http://www.growing-object-oriented-software.com[Growing Object-Oriented Software Guided by Tests]::
TDD pioneers Steve Freeman and Nat Pryce explain in detail how test-driven development and mocking work in the real world.

66 changes: 33 additions & 33 deletions docs/spock_primer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ To learn more about unit testing, go to http://en.wikipedia.org/wiki/Unit_testin

== Terminology

Let's start with a few definitions: Spock lets you write _specifications_ that describe expected _features_ (properties,
aspects) exhibited by a system of interest. The system of interest could be anything between a single class and a whole
application, and is also called _system under specification (SUS)_. The description of a feature starts from a specific
snapshot of the SUS and its collaborators; this snapshot is called the feature's _fixture_.
Let's start with a few definitions: Spock lets you write https://en.wikipedia.org/wiki/Specification_by_example[_specifications_]
that describe expected _features_ (properties, aspects) exhibited by a system of interest. The system of interest could be
anything between a single class and a whole application, and is also called the _system under specification or SUS_.
The description of a feature starts from a specific snapshot of the SUS and its collaborators; this snapshot is called the feature's _fixture_.

The following sections walk you through all building blocks of which a Spock specification may be composed. A typical
specification uses only a subset of them.
Expand Down Expand Up @@ -88,10 +88,10 @@ respect to sharing are more well-defined.

[source,groovy]
----
def setup() {} // run before every feature method
def cleanup() {} // run after every feature method
def setupSpec() {} // run before the first feature method
def cleanupSpec() {} // run after the last feature method
def setupSpec() {} // runs once - before the first feature method
def setup() {} // runs before every feature method
def cleanup() {} // runs after every feature method
def cleanupSpec() {} // runs once - after the last feature method
----

Fixture methods are responsible for setting up and cleaning up the environment in which feature methods are run.
Expand Down Expand Up @@ -135,8 +135,8 @@ interacting feature methods), and may occur more than once.

Spock has built-in support for implementing each of the conceptual phases of a feature method. To this end, feature
methods are structured into so-called _blocks_. Blocks start with a label, and extend to the beginning of the next block,
or the end of the method. There are six kinds of blocks: `setup`, `when`, `then`, `expect`, `cleanup`, and `where` blocks.
Any statements between the beginning of the method and the first explicit block belong to an implicit `setup` block.
or the end of the method. There are six kinds of blocks: `given`, `when`, `then`, `expect`, `cleanup`, and `where` blocks.
Any statements between the beginning of the method and the first explicit block belong to an implicit `given` block.

A feature method must have at least one explicit (i.e. labelled) block - in fact, the presence of an explicit block is
what makes a method a feature method. Blocks divide a method into distinct sections, and cannot be nested.
Expand All @@ -149,19 +149,19 @@ The picture on the right shows how blocks map to the conceptual phases of a feat
special role, which will be revealed shortly. But first, let's have a closer look at the other blocks.
--

==== Setup Blocks
==== Given Blocks

[source,groovy]
----
setup:
given:
def stack = new Stack()
def elem = "push me"
----

The `setup` block is where you do any setup work for the feature that you are describing. It may not be preceded by
other blocks, and may not be repeated. A `setup` block doesn't have any special semantics. The `setup:` label is
optional and may be omitted, resulting in an _implicit_ `setup` block. The `given:` label is an alias for `setup:`,
and sometimes leads to a more readable feature method description (see <<specs-as-doc,Specifications as Documentation>>).
The `given` block is where you do any setup work for the feature that you are describing. It may not be preceded by
other blocks, and may not be repeated. A `given` block doesn't have any special semantics. The `given:` label is
optional and may be omitted, resulting in an _implicit_ `given` block. Originally, the alias `setup:` was the preferred block name,
but using `given:` often leads to a more readable feature method description (see <<specifications_as_documentation,Specifications as Documentation>>).

==== When and Then Blocks

Expand Down Expand Up @@ -293,7 +293,7 @@ implementing this method? After all, where are the conditions? Fortunately, we c
[source,groovy]
----
def "HashMap accepts null key"() {
setup:
given:
def map = new HashMap()

when:
Expand All @@ -311,12 +311,13 @@ the method will also fail if any other exception is thrown.
===== Interactions

Whereas conditions describe an object's state, interactions describe how objects communicate with each other.
Interactions are devoted a whole <<interaction_based_testing.adoc#,chapter>>, and so we only give a quick example here.
Interactions and Interaction based testing are described in a separate <<interaction_based_testing.adoc#,chapter>>, so we only give a quick example here.
Suppose we want to describe the flow of events from a publisher to its subscribers. Here is the code:

[source,groovy]
----
def "events are published to all subscribers"() {
given:
def subscriber1 = Mock(Subscriber)
def subscriber2 = Mock(Subscriber)
def publisher = new Publisher()
Expand Down Expand Up @@ -363,7 +364,7 @@ to create more expressive and succinct conditions.

[source,groovy]
----
setup:
given:
def file = new File("/some/path")
file.createNewFile()

Expand All @@ -386,7 +387,7 @@ is automatically reclaimed by the garbage collector. More coarse-grained specifi
block to clean up the file system, close a database connection, or shut down a network service.

TIP: If a specification is designed in such a way that all its feature methods require the same resources, use a
`cleanup()` method; otherwise, prefer `cleanup` blocks. The same trade-off applies to `setup()` methods and `setup` blocks.
`cleanup()` method; otherwise, prefer `cleanup` blocks. The same trade-off applies to `setup()` methods and `given` blocks.

==== Where Blocks

Expand All @@ -409,9 +410,9 @@ def "computing the maximum of two numbers"() {
This `where` block effectively creates two "versions" of the feature method: One where `a` is 5, `b` is 1, and `c` is 5,
and another one where `a` is 3, `b` is 9, and `c` is 9.

Although it is declared last the `where` block is evaluated before feature method runs.
Although it is declared last, the `where` block is evaluated before the feature method containing it runs.

The `where` block will be further explained in the <<data_driven_testing.adoc#,Data Driven Testing>> chapter.
The `where` block is further explained in the <<data_driven_testing.adoc#,Data Driven Testing>> chapter.

== Helper Methods

Expand Down Expand Up @@ -498,7 +499,6 @@ A final advice: Although code reuse is generally a good thing, don't take it too
and helper methods can increase the coupling between feature methods. If you reuse too much or the wrong code, you will
end up with specifications that are fragile and hard to evolve.

[[specs-as-doc]]

== Using `with` for expectations

Expand Down Expand Up @@ -540,6 +540,8 @@ with(service) {
1 * stop()
}
----

[[specifications_as_documentation]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will conflict with your other #787 please align them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these lines to this file in #787 per request.

== Specifications as Documentation

Well-written specifications are a valuable source of information. Especially for higher-level specifications targeting
Expand All @@ -549,15 +551,15 @@ attach textual descriptions to blocks:

[source,groovy]
----
setup: "open a database connection"
given: "open a database connection"
// code goes here
----

Individual parts of a block can be described with `and:`:
Use the `and:` label to describe logically different parts of a block:

[source,groovy]
----
setup: "open a database connection"
given: "open a database connection"
// code goes here

and: "seed the customer table"
Expand Down Expand Up @@ -585,8 +587,6 @@ then: "the account's balance is $10"
// ...
----

As noted before, `given:` is just an alias for `setup:`.

Block descriptions are not only present in source code, but are also available to the Spock runtime. Planned usages of
block descriptions are enhanced diagnostic messages, and textual reports that are equally understood by all stakeholders.

Expand All @@ -599,20 +599,19 @@ activated by annotations called _directives_. Currently, Spock ships with the fo
[horizontal]
`@Timeout`:: Sets a timeout for execution of a feature or fixture method.

`@Ignore`:: Ignores a feature method.
`@Ignore`:: Ignores any feature method carrying this annotation.

`@IgnoreRest`:: Ignores all feature methods not carrying this annotation. Useful for quickly running just a single method.
`@IgnoreRest`:: Any feature method carrying this annotation will be executed, all others will be ignored. Useful for quickly running just a single method.

`@FailsWith`:: Expects a feature method to complete abruptly. `@FailsWith` has two use cases: First, to document known bugs that cannot
be resolved immediately. Second, to replace exception conditions in certain corner cases where the latter cannot be
used (like specifying the behavior of exception conditions). In all other cases, exception conditions are preferable.

To learn how to implement your own directives and extensions, go to the <<extensions.adoc#,Extensions>> chapter.
Go to the <<extensions.adoc#,Extensions>> chapter to learn how to implement your own directives and extensions.

== Comparison to JUnit

Although Spock uses a different terminology, many of its concepts and features are inspired from JUnit. Here is a rough
comparison:
Although Spock uses a different terminology, many of its concepts and features are inspired by JUnit. Here is a rough comparison:

|===
|Spock |JUnit
Expand All @@ -629,3 +628,4 @@ comparison:
|Exception condition |`@Test(expected=...)`
|Interaction | Mock expectation (e.g. in Mockito)
|===
`