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 1 commit
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
Next Next commit
Primer uses 'given' as the primary block name and 'setup' is the alias.
  • Loading branch information
BurkHufnagel committed Oct 29, 2017
commit dea39bbc250315e85f1552b57fc90ec1f581a4b1
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.
76 changes: 40 additions & 36 deletions docs/spock_primer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ 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 +89,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 +136,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` given block.
Copy link
Member

@leonard84 leonard84 Nov 15, 2017

Choose a reason for hiding this comment

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

one given to many

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change made.


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 +150,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 configuration for the feature that you are describing. It may not be preceded by
Copy link
Member

Choose a reason for hiding this comment

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

I think setup work is better than configuration

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change made.

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 +294,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,8 +312,9 @@ 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.
Suppose we want to describe the flow of events from a publisher to its subscribers. Here is the code:
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]
----
Expand Down Expand Up @@ -363,7 +365,7 @@ to create more expressive and succinct conditions.

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

Expand All @@ -386,7 +388,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 +411,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 +500,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 +541,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 +552,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 +588,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,19 +600,21 @@ 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
Copy link
Member

Choose a reason for hiding this comment

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

Please set your IDE to softwraps instead of introducing needless newlines. Also fix the other additional line breaks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Change made to align with current line breaks.

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.
`@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
Although Spock uses a different terminology, many of its concepts and features are inspired by JUnit. Here is a rough
comparison:

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