spock-spock-0.7-groovy-2.0/ 0000775 0000000 0000000 00000000000 12034506303 0015430 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/.gitignore 0000664 0000000 0000000 00000000524 12034506303 0017421 0 ustar 00root root 0000000 0000000 # entries starting with and ending in / will be excluded from root IDEA module,
# and entries ending in / from all IDEA modules (see ide.gradle)
# Gradle
.gradle/
build/
# Maven
target/
# IDEA
.idea/
*.iml
*.ipr
*.iws
out/
# Eclipse
.project
.classpath
.settings/
bin/
# Grails
stacktrace.log
# Sphinx
/docs/_build/
# Other
.DS_Store spock-spock-0.7-groovy-2.0/.travis.yml 0000664 0000000 0000000 00000000100 12034506303 0017530 0 ustar 00root root 0000000 0000000 script: ./gradlew clean build
jdk:
- oraclejdk7
- openjdk6
spock-spock-0.7-groovy-2.0/LICENSE 0000664 0000000 0000000 00000026135 12034506303 0016444 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. spock-spock-0.7-groovy-2.0/NOTICE 0000664 0000000 0000000 00000001326 12034506303 0016336 0 ustar 00root root 0000000 0000000 =========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Spock distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
It includes the following other software:
gentyref (http://code.google.com/p/gentyref/)
For licenses see the LICENSE file.
If any software distributed with Spock does not have an Apache 2 License, its license is explicitly listed in the
LICENSE file. spock-spock-0.7-groovy-2.0/README 0000664 0000000 0000000 00000004372 12034506303 0016316 0 ustar 00root root 0000000 0000000 Spock Framework README
======================
Spock is a developer testing and specification framework for Java and Groovy applications. To learn more about Spock,
visit http://spockframework.org. To run your first spec right away, visit http://meet.spockframework.org.
Current release versions: 0.6-groovy-1.7, 0.6-groovy-1.8 (released 2012-03-02)
Current development versions: 0.7-groovy-1.8-SNAPSHOT, 0.7-groovy-2.0-SNAPSHOT
Modules
-------
spock-core: Core framework.
spock-specs: Specifications for spock-core, written with Spock. Not required for using the framework.
spock-maven: Extended Maven support (optional).
spock-example: Self-contained example project with Ant, Gradle, and Maven build. See spock-example/README for more information.
spock-spring: Integration with the Spring TestContext Framework.
spock-tapestry: Integration with the Tapestry 5 IoC container.
spock-guice: Integration with Guice 2.
spock-unitils: Integration with Unitils (http://www.unitils.org/).
spock-grails: The Grails plugin is now its own project hosted at https://github.com/spockframework/spock-grails.
Building Spock yourself
-----------------------
Prerequisites: JDK 5 or higher
Type: ./gradlew clean build
If not already present, build dependencies (including Gradle itself) will be downloaded automatically.
Further Resources
-----------------
Spock homepage http://spockframework.org
Spock web console http://webconsole.spockframework.org
Main documentation http://wiki.spockframework.org/SpockBasics
User discussion group http://forum.spockframework.org
Dev discussion group http://dev.forum.spockframework.org
Issue tracker http://issues.spockframework.org
Build server http://builds.spockframework.org
Maven repository http://m2repo.spockframework.org (releases are also available from Maven Central)
Spock blog http://blog.spockframework.org
Spock on Twitter http://twitter.com/pniederw
Ant homepage http://ant.apache.org
Gradle homepage http://www.gradle.org
Groovy homepage http://groovy.codehaus.org
Maven homepage http://maven.apache.org
If you have any comments or questions, please direct them to the Spock discussion group. All feedback is appreciated!
Happy spec'ing!
Peter Niederwieser
Creator, Spock Framework spock-spock-0.7-groovy-2.0/build.gradle 0000775 0000000 0000000 00000004554 12034506303 0017722 0 ustar 00root root 0000000 0000000 description = "Spock Framework"
ext {
libs = [
ant: "org.apache.ant:ant:1.8.4", // use same version as Groovy 2.0
asm: "org.ow2.asm:asm:4.0", // use same version as Groovy 2.0
cglib: "cglib:cglib-nodep:2.2.2",
easymock: "org.easymock:easymock:3.0",
groovy: "org.codehaus.groovy:groovy-all:2.0.5",
h2database: "com.h2database:h2:1.3.164",
jmock: "org.jmock:jmock:2.5.1",
jmock_junit4: "org.jmock:jmock-junit4:2.5.1",
junit: ["junit:junit-dep:4.10@jar", "org.hamcrest:hamcrest-core:1.3"],
log4j: "log4j:log4j:1.2.16",
mockito: "org.mockito:mockito-all:1.9.0",
objenesis: "org.objenesis:objenesis:1.2"
]
}
allprojects {
group = "org.spockframework"
version = "0.7-groovy-2.0"
apply from: script("common")
}
apply from: script("ide")
subprojects {
apply plugin: "groovy"
apply plugin: "signing"
sourceCompatibility = 1.5
repositories {
mavenCentral()
maven { url "http://snapshots.repository.codehaus.org" }
}
configurations {
all*.exclude module: "junit" // we use junit-dep instead
}
dependencies {
groovy libs.groovy
}
signing {
sign configurations.archives
}
signArchives {
onlyIf { gradle.taskGraph.hasTask(uploadArchives) }
}
configureJavadoc(javadoc)
task sourcesJar(type: Jar) {
classifier "sources"
from sourceSets.main.allSource
}
task javadocJar(type: Jar) {
classifier "javadoc"
from javadoc
}
artifacts {
archives sourcesJar, javadocJar
}
}
task javadoc(type: Javadoc) {
title "Spock Framework API Documentation ($version)"
destinationDir file("build/javadoc")
source subprojects.javadoc.source
classpath = files(subprojects.javadoc.classpath)
}
configureJavadoc(javadoc)
task publishJavadoc(type: Sync) {
from javadoc
into "file:///var/www/spock/javadoc/$version/"
}
task wrapper(type: Wrapper) {
gradleVersion = "1.2"
}
File script(String name) {
project.file("gradle/${name}.gradle")
}
def configureJavadoc(task) {
configure(task) {
include "spock/**"
include "org/spockframework/mock/*"
configure(options) {
links "http://download.oracle.com/javase/1.5.0/docs/api/"
links "http://groovy.codehaus.org/gapi"
links "http://kentbeck.github.com/junit/javadoc/4.10"
links "http://www.jarvana.com/jarvana/inspect/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar"
}
}
}
spock-spock-0.7-groovy-2.0/config/ 0000775 0000000 0000000 00000000000 12034506303 0016675 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/config/ant-junit/ 0000775 0000000 0000000 00000000000 12034506303 0020606 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/config/ant-junit/junit-frames.xsl 0000664 0000000 0000000 00000101523 12034506303 0023744 0 ustar 00root root 0000000 0000000
Unit Test Results..
body {
font:normal 68% verdana,arial,helvetica;
color:#000000;
}
table tr td, table tr th {
font-size: 68%;
}
table.details tr th{
font-weight: bold;
text-align:left;
background:#a6caf0;
}
table.details tr td{
background:#eeeee0;
}
p {
line-height:1.5em;
margin-top:0.5em; margin-bottom:1.0em;
}
h1 {
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
}
h3 {
margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
}
h4 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h5 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h6 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
.Error {
font-weight:bold; color:red;
}
.Failure {
font-weight:bold; color:purple;
}
.Properties {
text-align:right;
}
All FailuresAll ErrorsAll TestsUnit Test Results: open('allclasses-frame.html','classListFrame')
spock-spock-0.7-groovy-2.0/docs/ 0000775 0000000 0000000 00000000000 12034506303 0016360 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/docs/Makefile 0000664 0000000 0000000 00000011016 12034506303 0020017 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SpockFramework.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SpockFramework.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/SpockFramework"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SpockFramework"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
make -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
spock-spock-0.7-groovy-2.0/docs/conf.py 0000664 0000000 0000000 00000015771 12034506303 0017672 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
#
# Spock Framework documentation build configuration file, created by
# sphinx-quickstart on Sat Jul 16 14:17:19 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Spock Framework'
copyright = u'2012, Peter Niederwieser'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.7'
# The full version, including alpha/beta/rc tags.
release = '0.7'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
html_title = 'Spock 0.7'
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
html_domain_indices = False
# If false, no index is generated.
html_use_index = False
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'SpockFrameworkdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'SpockFramework.tex', u'Spock Framework Documentation',
u'Peter Niederwieser', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
latex_domain_indices = False
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'spockframework', u'Spock Framework Documentation',
[u'Peter Niederwieser'], 1)
]
# -- Options added by us -------------------------------------------------------
highlight_language = 'java'
spock-spock-0.7-groovy-2.0/docs/data_driven_testing.rst 0000664 0000000 0000000 00000026613 12034506303 0023137 0 ustar 00root root 0000000 0000000 .. _DataDrivenTesting:
Data Driven Testing
===================
Oftentimes, it is useful to exercise the same test code multiple times, with varying inputs and expected results.
Spock's data driven testing support makes this a first class feature.
Introduction
------------
Suppose we want to specify the behavior of the ``Math.max`` method::
class MathSpec extends Specification {
def "maximum of two numbers"() {
expect:
// exercise math method for a few different inputs
Math.max(1, 3) == 3
Math.max(7, 4) == 7
Math.max(0, 0) == 0
}
}
Although this approach is fine in simple cases like this one, it has some potential drawbacks:
* Code and data are mixed and cannot easily be changed independently
* Data cannot easily be auto-generated or fetched from external sources
* In order to exercise the same code multiple times, it either has to be duplicated or extracted into a separate method
* In case of a failure, it may not be immediately clear which inputs caused the failure
* Exercising the same code multiple times does not benefit from the same isolation as executing separate methods does
Spock's data-driven testing support tries to address these concerns. To get started, let's refactor above code into a
data-driven feature method. First, we introduce three method parameters (called *data variables*) that replace the
hard-coded integer values::
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
...
}
}
We have finished the test logic, but still need to supply the data values to be used. This is done in a ``where:`` block,
which always comes at the end of the method. In the simplest (and most common) case, the ``where:`` block holds a *data table*.
Data Tables
-----------
Data tables are a convenient way to exercise a feature method with a fixed set of data values::
class Math extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 4
0 | 0 | 0
}
}
The first line of the table, called the *table header*, declares the data variables. The subsequent lines, called
*table rows*, hold the corresponding values. For each row, the feature method will get executed once; we call this an
*iteration* of the method. If an iteration fails, the remaining iterations will nevertheless be executed. All
failures will be reported.
Data tables must have at least two columns. A single-column table can be written as::
where:
a | _
1 | _
7 | _
0 | _
Isolated Execution of Iterations
--------------------------------
Iterations are isolated from each other in the same way as separate feature methods. Each iteration gets its own instance
of the specification class, and the ``setup`` and ``cleanup`` methods will be called before and after each iteration,
respectively.
Sharing of Objects between Iterations
-------------------------------------
In order to share an object between iterations, it has to be kept in a ``@Shared`` or static field.
.. note:: Only ``@Shared`` and static variables can be accessed from within a ``where:`` block.
Note that such objects will also be shared with other methods. There is currently no good way to share an object
just between iterations of the same method. If you consider this a problem, consider putting each method into a separate
spec, all of which can be kept in the same file. This achieves better isolation at the cost of some boilerplate code.
Syntactic Variations
--------------------
The previous code can be tweaked in a few ways. First, since the ``where:`` block already declares all data variables, the
method parameters can be omitted. [#methodParameters]_. Second, inputs and expected outputs can be separated with a
double pipe symbol (``||``) to visually set them apart. With this, the code becomes::
class DataDriven extends Specification {
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b || c
3 | 5 || 5
7 | 0 || 7
0 | 0 || 0
}
}
Reporting of Failures
---------------------
Let's assume that our implementation of the ``max`` method has a flaw, and one of the iterations fails::
maximum of two numbers FAILED
Condition not satisfied:
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
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 [#impossible]_.
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.
Method Unrolling
----------------
.. code-block::
@Unroll
def "maximum of two numbers"() { ... }
.. sidebar:: Why isn't ``@Unroll`` the default?
One reason why ``@Unroll`` isn't the default is that some execution environments (in particular IDEs) expect to be
told the number of test methods in advance, and have certain problems if the actual number varies. Another reason
is that ``@Unroll`` can drastically change the number of reported tests, which may not always be desirable.
A method annotated with ``@Unroll`` will have its iterations reported independently. Note that unrolling has no
effect on the execution itself - it is only an alternation in reporting. Depending on the execution environment, the
output will look something like::
maximum of two numbers[0] PASSED
maximum of two numbers[1] FAILED
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
maximum of two numbers[2] PASSED
This tells us that the second iteration (with index 1) failed. With a bit of effort, we can do even better::
@Unroll
def "maximum of #a and #b is #c"() { ... }
This method name uses placeholders, denoted by a leading hash sign (``#``), to refer to data variables ``a``, ``b``,
and ``c``. In the output, the placeholders will be replaced with concrete values::
maximum of 3 and 5 is 5 PASSED
maximum of 7 and 0 is 7 FAILED
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
maximum of 0 and 0 is 0 PASSED
Now we can tell at a glance that the ``max`` method failed for inputs ``7`` and ``0``. See `More on Unrolled Method Names`_
for further details on this topic.
The ``@Unroll`` annotation can also be placed on a spec. This has the same effect as placing it on each data-driven
feature method of the spec.
Data Pipes
----------
Data tables aren't the only way to supply values to data variables. In fact, a data table is just syntactic sugar for
one or more *data pipes*::
...
where:
a << [3, 7, 0]
b << [5, 0, 0]
c << [5, 7, 0]
A data pipe, indicated by the left-shift (``<<``) operator, connects a data variable to a *data provider*. The data
provider holds all values for the variable, one per iteration. Any object that Groovy knows how to iterate over can be
used as a data provider. This includes objects of type ``Collection``, ``String``, ``Iterable``, and objects implementing the
``Iterable`` contract. Data providers don't necessarily have to *be* the data (as in the case of a ``Collection``);
they can fetch data from external sources like text files, databases and spreadsheets, or generate data randomly.
Data providers are queried for their next value only when needed (before the next iteration).
Multi-Variable Data Pipes
-------------------------
If a data provider returns multiple values per iteration (as an object that Groovy knows how to iterate over),
it can be connected to multiple data variables simultaneously. The syntax is somewhat similar to Groovy multi-assignment
but uses brackets instead of parentheses on the left-hand side::
@Shared sql = Sql.newInstance("jdbc:h2:mem:", "org.h2.Driver")
def "maximum of two numbers"() {
...
where:
[a, b, c] << sql.rows("select a, b, c from maxdata")
}
Data values that aren't of interest can be ignored with an underscore (``_``)::
...
where:
[a, b, _, c] << sql.rows("select * from maxdata")
Data Variable Assignment
------------------------
A data variable can be directly assigned a value::
...
where:
a = 3
b = Math.random() * 100
c = a > b ? a : b
Assignments are re-evaluated for every iteration. As already shown above, the right-hand side of an assignment may refer
to other data variables::
...
where:
row << sql.rows("select * from maxdata")
// pick apart columns
a = row.a
b = row.b
c = row.c
Combining Data Tables, Data Pipes, and Variable Assignments
-----------------------------------------------------------
Data tables, data pipes, and variable assignments can be combined as needed::
...
where:
a | _
3 | _
7 | _
0 | _
b << [5, 0, 0]
c = a > b ? a : b
Number of Iterations
--------------------
The number of iterations depends on how much data is available. Successive executions of the same method can
yield different numbers of iterations. If a data provider runs out of values sooner than its peers, an exception will occur.
Variable assignments don't affect the number of iterations. A ``where:`` block that only contains assignments yields
exactly one iteration.
Closing of Data Providers
-------------------------
After all iterations have completed, the zero-argument ``close`` method is called on all data providers that have
such a method.
More on Unrolled Method Names
-----------------------------
An unrolled method name is similar to a Groovy ``GString``, except for the following differences:
* Expressions are denoted with ``#`` instead of ``$`` [#noDollar]_, and there is no equivalent for the ``${...}`` syntax
* Expressions only support property access and zero-arg method calls
Given a class ``Person`` with properties ``name`` and ``age``, and a data variable ``person`` of type ``Person``, the
following are valid method names::
def "#person is #person.age years old"() { ... } // property access
def "#person.name.toUpperCase()"() { ... } // zero-arg method call
Non-string values (like ``#person`` above) are converted to Strings according to Groovy semantics.
The following are invalid method names::
def "#person.name.split(' ')[1]" { ... } // cannot have method arguments
def "#person.age / 2" { ... } // cannot use operators
If necessary, additional data variables can be introduced to hold more complex expression::
def "#lastName"() {
...
where:
person << ...
lastName = person.name.split(' ')[1]
}
.. rubric:: Footnotes
.. [#methodParameters] The idea behind allowing method parameters is to enable better IDE support. However, recent
versions of IntelliJ IDEA recognize data variables automatically, and even infer their types from the values contained
in the data table.
.. [#impossible] For example, a feature method could use data variables in its ``setup:`` block, but not in any conditions.
.. [#noDollar] Groovy syntax does not allow dollar signs in method names.
spock-spock-0.7-groovy-2.0/docs/getting_started.rst 0000664 0000000 0000000 00000002217 12034506303 0022303 0 ustar 00root root 0000000 0000000 Getting Started
===============
It's really easy to get started with Spock. This section shows you how.
Spock Web Console
-----------------
`Spock Web Console`_ is a website that allows you to instantly view, edit, run, and even publish Spock specifications. It is the perfect place to toy around with Spock without making any commitments. So why not run `Hello, Spock!`_ right now?
Spock Example Project
---------------------
To try Spock on your own computer, download and unzip the Example Project (`download link`_). It comes with fully working Ant, Gradle, and Maven builds that require no further setup. The Gradle build even bootstraps Gradle itself and gets you up and running in Eclipse or IDEA with a single command. See the README for detailed instructions.
Next Steps
----------
The following sections provide further information on how to use Spock in a number of different environments:
* Ant
* Gradle
* Maven
* Groovy Console
* Eclipse
* IDEA
.. _Spock Web Console: http://meet.spockframework.org
.. _Hello, Spock!: http://meet.spockframework.org/?id=9001
.. _download link: http://files.spockframework.org/spock-example-0.5-groovy-1.7.zip
spock-spock-0.7-groovy-2.0/docs/index.rst 0000664 0000000 0000000 00000001311 12034506303 0020215 0 ustar 00root root 0000000 0000000 .. Spock Framework documentation master file, created by
sphinx-quickstart on Sat Jul 16 14:17:19 2011.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Spock Framework Reference Documentation
---------------------------------------
Authors: Peter Niederwieser
Version: 0.7
.. note:: This documentation effort is a work in progress. For the time being, we also recommend to check out the old documentation at http://wiki.spockframework.org.
Table of Contents
-----------------
.. toctree::
:maxdepth: 2
introduction
getting_started
data_driven_testing
interaction_based_testing
new_and_noteworthy
migration_guide
spock-spock-0.7-groovy-2.0/docs/interaction_based_testing.rst 0000664 0000000 0000000 00000115414 12034506303 0024332 0 ustar 00root root 0000000 0000000 .. _InteractionBasedTesting:
Interaction Based Testing
=========================
Interaction-based testing is a design and testing technique that emerged in the Extreme Programming
(XP) community in the early 2000's. Focusing on the behavior of objects rather than their state, it explores how
the object(s) under specification interact, by way of method calls, with their collaborators.
For example, suppose we have a ``Publisher`` that sends messages to its ``Subscriber``'s::
class Publisher {
List subscribers
void send(String message)
}
interface Subscriber {
void receive(String message)
}
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
}
How are we going to test ``Publisher``? With state-based testing, we can verify that the publisher keeps track of its
subscribers. The more interesting question, though, is whether a message sent by the publisher
is received by the subscribers. To answer this question, we need a special implementation of
``Subscriber`` that listens in on the conversation between the publisher and its subscribers. Such an
implementation is often called a *mock object*.
While we could certainly create a mock implementation of ``Subscriber`` by hand, writing and maintaining this code
can get unpleasant as the number of methods and complexity of interactions increases. This is where mocking frameworks
come in: They provide a way to describe the expected interactions between an object under specification and its
collaborators, and can generate mock implementations of collaborators that verify these expectations.
.. sidebar:: How Are Mock Implementations Generated?
Like most Java mocking frameworks, Spock uses `JDK dynamic proxies `_
(when mocking interfaces) and `CGLIB `_ proxies (when mocking classes)
to generate mock implementations at runtime. Compared to implementations based on Groovy meta-programming,
this has the advantage that it also works for testing Java code.
The Java world has no shortage of popular and mature mocking frameworks: `JMock `_,
`EasyMock `_, `Mockito `_, to name just a few.
Although each of these tools can be used together with Spock, we decided to roll our own mocking framework,
tightly integrated with Spock's specification language. This decision was driven by the desire to leverage all of
Groovy's capabilities to make interaction-based tests easier to write, more readable, and ultimately more fun.
We hope that by the end of this chapter, you will agree that we have achieved these goals.
Except where indicated, all features of Spock's mocking framework work both for testing Java and Groovy code.
Creating Mock Objects
---------------------
Mock objects are created with the ``MockingApi.Mock()`` method [#creating]_. Let's create two mock subscribers::
def subscriber = Mock(Subscriber)
def subscriber2 = Mock(Subscriber)
Alternatively, the following Java-like syntax is supported, which may give better IDE support::
Subscriber subscriber = Mock()
Subscriber subscriber2 = Mock()
Here, the mock's type is inferred from the variable type on the left-hand side of the assignment.
.. note:: If the mock's type is given on the left-hand side of the assignment, it's permissible
(though not required) to omit it on the right-hand side.
Mock objects literally implement (or, in the case of a class, extend) the type they stand in for. In other
words, in our example ``subscriber`` *is-a* ``Subscriber``. Hence it can be passed to statically typed (Java)
code that expects this type.
Default Behavior of Mock Objects
--------------------------------
.. sidebar:: Lenient vs. Strict Mocking Frameworks
Like Mockito, we firmly believe that a mocking framework should be lenient by default. This means that unexpected
method calls on mock objects (or, in other words, interactions that aren't relevant for the test at hand) are allowed
and answered with a default response. Conversely, mocking frameworks like EasyMock and JMock are strict by default,
and throw an exception for every unexpected method call. While strictness enforces rigor, it can also lead
to over-specification, resulting in brittle tests that fail with every other internal code change. Spock's mocking
framework makes it easy to describe only what's relevant about an interaction, avoiding the over-specification trap.
Initially, mock objects have no behavior. Calling methods on them is allowed but has no effect other than returning
the default value for the method's return type (``false``, ``0``, or ``null``). An exception are the ``Object.equals``,
``Object.hashCode``, and ``Object.toString`` methods, which have the following default behavior: A mock object is only
equal to itself, has a unique hash code, and a string representation that includes the name of the type it represents.
This default behavior is overridable by stubbing the methods, which we will learn about in the `Stubbing`_ section.
Injecting Mock Objects into Code Under Specification
----------------------------------------------------
After creating the publisher and its subscribers, we need to make the latter known to the former::
class PublisherSpec extends Specification {
Publisher publisher = new Publisher()
Subscriber subscriber = Mock()
Subscriber subscriber2 = Mock()
def setup() {
publisher << subscriber // << is a Groovy shorthand for List.add()
publisher << subscriber2
}
}
We are now ready to describe the expected interactions between the two parties.
Mocking
-------
Mocking is the act of describing (mandatory) interactions between the object under specification and its collaborators.
Here is an example::
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello")
1 * subscriber2.receive("hello")
}
Read out aloud: "When the publisher sends a 'hello' message, then both subscribers should receive that message exactly once."
When this feature method gets run, all invocations on mock objects that occur while executing the
``when`` block will be matched against the interactions described in the ``then:`` block. If one of the interactions isn't
satisfied, a (subclass of) ``InteractionNotSatisfiedError`` will be thrown. This verification happens automatically
and does not require any additional code.
Interactions
~~~~~~~~~~~~
.. sidebar:: Is an Interaction Just a Regular Method Invocation?
Not quite. While an interaction looks similar to a regular method invocation, it is simply a way to express which
method invocations are expected to occur. A good way to think of an interaction is as a regular expression
that all incoming invocations on mock objects are matched against. Depending on the circumstances, the interaction
may match zero, one, or multiple invocations.
Let's take a closer look at the ``then:`` block. It contains two *interactions*, each of which has four distinct
parts: a *cardinality*, a *target constraint*, a *method constraint*, and an *argument constraint*::
1 * subscriber.receive("hello")
| | | |
| | | argument constraint
| | method constraint
| target constraint
cardinality
Cardinality
~~~~~~~~~~~
The cardinality of an interaction describes how often a method call is expected. It can either be a fixed number or
a range::
1 * subscriber.receive("hello") // exactly one call
0 * subscriber.receive("hello") // zero calls
(1..3) * subscriber.receive("hello") // between one and three calls (inclusive)
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
_ * subscriber.receive("hello") // any number of calls, including zero
// (rarely needed; see 'Strict Mocking')
Target Constraint
~~~~~~~~~~~~~~~~~
The target constraint of an interaction describes which mock object is expected to receive the method call::
1 * subscriber.receive("hello") // a call to 'subscriber'
1 * _.receive("hello") // a call to any mock object
Method Constraint
~~~~~~~~~~~~~~~~~
The method constraint of an interaction describes which method is expected to be called::
1 * subscriber.receive("hello") // a method named 'receive'
1 * subscriber./r.*e/("hello") // a method whose name matches the given regular expression
// (here: method name starts with 'r' and ends in 'e')
When expecting a call to a getter method, Groovy property syntax *can* be used instead of method syntax::
1 * subscriber.status // same as: 1 * subscriber.getStatus()
When expecting a call to a setter method, only method syntax can be used::
1 * subscriber.setStatus("ok") // NOT: 1 * subscriber.status = "ok"
Argument Constraints
~~~~~~~~~~~~~~~~~~~~
The argument constraints of an interaction describe which method arguments are expected::
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 (would never match in our example)
1 * subscriber.receive(_) // any single argument (including null)
1 * subscriber.receive(*_) // any argument list (including the empty 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
// (here: message length is greater than 3)
Argument constraints work as expected for methods with multiple arguments::
1 * process.invoke("ls", "-a", _, !null, { ["abcdefghiklmnopqrstuwx1"].contains(it) })
When dealing with vararg methods, vararg syntax can also be used in the corresponding interactions::
interface VarArgSubscriber {
void receive(String... messages)
}
...
subscriber.receive("hello", "goodbye")
.. admonition:: Spock Deep Dive: Groovy Varargs
Groovy allows any method whose last parameter has an array type to be called in vararg style. Consequently,
vararg syntax can also be used in interactions matching such methods.
Matching Any Method Call
~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes it can be useful to match "anything", in some sense of the word::
1 * subscriber._(*_) // any method on subscriber, with any argument list
1 * subscriber._ // shortcut for and preferred over the above
1 * _._ // any method call on any mock object
1 * _ // shortcut for and preferred over the above
.. note:: Although ``(_.._) * _._(*_) >> _`` is a valid interaction declaration,
it is neither good style nor particularly useful.
Strict Mocking
~~~~~~~~~~~~~~
Now, when would matching any method call be useful? A good example is *strict mocking*,
a style of mocking where no interactions other than those explicitly declared are allowed::
when:
publisher.publish("hello")
then:
1 * subscriber.receive("hello") // demand one 'receive' call on `subscriber`
_ * auditing._ // allow any interaction with 'auditing'
0 * _ // don't allow any other interaction
``0 *`` only makes sense as the last interaction of a ``then:`` block or method. Note the
use of ``_ *`` (any number of calls), which allows any interaction with the auditing component.
.. note:: ``_ *`` is only meaningful in the context of strict mocking. In particular, it is never necessary
when :ref:`stubbing ` an invocation. For example, ``_ * auditing.record(_) >> "ok"``
can (and should!) be simplified to ``auditing.record(_) >> "ok"``.
.. _WhereToDeclareInteractions:
Where to Declare Interactions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So far, we declared all our interactions in a ``then:`` block. This often results in a spec that reads naturally.
However, it is also permissible to put interactions anywhere *before* the ``when:`` block that is supposed to satisfy
them. In particular, this means that interactions can be declared in a ``setup`` method. Interactions can also be
declared in any "helper" instance method of the same specification class.
When an invocation on a mock object occurs, it is matched against interactions in the interactions' declared order.
If an invocation matches multiple interactions, the earliest declared interaction that hasn't reached its upper
invocation limit will win. There is one exception to this rule: Interactions declared in a ``then:`` block are
matched against before any other interactions. This allows to override interactions declared in, say, a ``setup``
method with interactions declared in a ``then:`` block.
.. admonition:: Spock Deep Dive: How Are Interactions Recognized?
In other words, what makes an expression an interaction declaration, rather than, say, a regular method call?
Spock uses a simple syntactic rule to recognize interactions: If an expression is in statement position
and is either a multiplication (``*``) or a left-shift (``>>``, ``>>>``) operation, then it is considered
an interaction and will be parsed accordingly. Such an expression would have little to no value in statement
position, so changing its meaning works out fine. Note how the operations correspond to the syntax for declaring
a cardinality (when mocking) or a response generator (when stubbing). Either of them must always be present;
``foo.bar()`` alone will never be considered an interaction.
.. _DeclaringInteractionsAtMockCreationTime:
Declaring Interactions at Mock Creation Time (New in 0.7)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a mock has a set of "base" interactions that don't vary, they can be declared right at mock creation time::
def subscriber = Mock(Subscriber) {
1 * receive("hello")
1 * receive("goodbye")
}
This feature is particularly attractive for :ref:`stubbing ` and with dedicated `Stubs`_. Note that the
interactions don't (and cannot [#targetContext]_) have a target constraint; it's clear from the context which mock
object they belong to.
Interactions can also be declared when initializing an instance field with a mock::
class MySpec extends Specification {
Subscriber subscriber = Mock {
1 * receive("hello")
1 * receive("goodbye")
}
}
.. _GroupingInteractionsWithSameTarget:
Grouping Interactions with Same Target (New in 0.7)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interactions sharing the same target can be grouped in a ``Specification.with`` block. Similar to
:ref:`declaring interactions at mock creation time `, this makes
it unnecessary to repeat the target constraint::
with(subscriber) {
1 * receive("hello")
1 * receive("goodbye")
}
A ``with`` block can also be used for grouping conditions with the same target.
Mixing Interactions and Conditions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A ``then:`` block may contain both interactions and conditions. Although not strictly required, it is customary
to declare interactions before conditions::
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello")
publisher.messageCount == 1
Read out aloud: "When the publisher sends a 'hello' message, then the subscriber should receive the message exactly
once, and the publisher's message count should be one."
Explicit Interaction Blocks
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Internally, Spock must have full information about expected interactions *before* they take place.
So how is it possible for interactions to be declared in a ``then:`` block?
The answer is that under the hood, Spock moves interactions declared in a ``then:`` block to immediately
before the preceding ``when:`` block. In most cases this works out just fine, but sometimes it can lead to problems::
when:
publisher.send("hello")
then:
def message = "hello"
1 * subscriber.receive(message)
Here we have introduced a variable for the expected argument. (Likewise, we could have introduced a variable
for the cardinality.) However, Spock isn't smart enough (huh?) to tell that the interaction is intrinsically
linked to the variable declaration. Hence it will just move the interaction, which will cause a
``MissingPropertyException`` at runtime.
One way to solve this problem is to move (at least) the variable declaration to before the ``when:``
block. (Fans of :ref:`data-driven testing ` might move the variable into a ``where:`` block.)
In our example, this would have the added benefit that we could use the same variable for sending the message.
Another solution is to be explicit about the fact that variable declaration and interaction belong together::
when:
publisher.send("hello")
then:
interaction {
def message = "hello"
1 * subscriber.receive(message)
}
Since an ``MockingApi.interaction`` block is always moved in its entirety, the code now works as intended.
Scope of Interactions
~~~~~~~~~~~~~~~~~~~~~
Interactions declared in a ``then:`` block are scoped to the preceding ``when:`` block::
when:
publisher.send("message1")
then:
subscriber.receive("message1")
when:
publisher.send("message2")
then:
subscriber.receive("message2")
This makes sure that ``subscriber`` receives ``"message1"`` during execution of the first ``when:`` block,
and ``"message2"`` during execution of the second ``when:`` block.
Interactions declared outside a ``then:`` block are active from their declaration until the end of the
containing feature method.
Interactions are always scoped to a particular feature method. Hence they cannot be declared in a static method,
``setupSpec`` method, or ``cleanupSpec`` method. Likewise, mock objects should not be stored in static or ``@Shared``
fields.
Verification of Interactions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There a two main ways in which a mock-based test can fail: An interaction can match more invocations than
allowed, or it can match fewer invocations than required. The former case is detected right when the invocation
happens, and causes a ``TooManyInvocationsError``::
Too many invocations for:
2 * subscriber.receive(_) (3 invocations)
.. _ShowAllMatchingInvocations:
To make it easier to diagnose why too many invocations matched, Spock will show all invocations matching
the interaction in question (new in Spock 0.7)::
Matching invocations (ordered by last occurrence):
2 * subscriber.receive("hello") <-- this triggered the error
1 * subscriber.receive("goodbye")
According to this output, one of the ``receive("hello")`` calls triggered the ``TooManyInvocationsError``.
Note that because indistinguishable calls like the two invocations of ``subscriber.receive("hello")`` are aggregated
into a single line of output, the first ``receive("hello")`` may well have occurred before the ``receive("goodbye")``.
The second case (fewer invocations than required) can only be detected once execution of the ``when`` block has completed.
(Until then, further invocations may still occur.) It causes a ``TooFewInvocationsError``::
Too few invocations for:
1 * subscriber.receive("hello") (0 invocations)
Note that it doesn't matter whether the method was not called at all, the same method was called with different arguments,
the same method was called on a different mock object, or a different method was called "instead" of this one;
in either case, a ``TooFewInvocationsError`` error will occur.
.. _ShowUnmatchedInvocations:
To make it easier to diagnose what happened "instead" of a missing invocation, Spock will show all
invocations that didn't match any interaction, ordered by their similarity with the interaction in question
(new in Spock 0.7). In particular, invocations that match everything but the interaction's arguments will be shown first::
Unmatched invocations (ordered by similarity):
1 * subscriber.receive("goodbye")
1 * subscriber2.receive("hello")
Invocation Order
~~~~~~~~~~~~~~~~
Often, the exact method invocation order isn't relevant and may change over time. To avoid over-specification,
Spock defaults to allowing any invocation order, provided that the specified interactions are eventually satisfied::
then:
2 * subscriber.receive("hello")
1 * subscriber.receive("goodbye")
Here, any of the invocation sequences ``"hello"`` ``"hello"`` ``"goodbye"``, ``"hello"`` ``"goodbye"`` ``"hello"``, and
``"goodbye"`` ``"hello"`` ``"hello"`` will satisfy the specified interactions.
In those cases where invocation order matters, you can impose an order by splitting up interactions into
multiple ``then:`` blocks::
then:
2 * subscriber.receive("hello")
then:
1 * subscriber.receive("goodbye")
Now Spock will verify that both ``"hello"``'s are received before the ``"goodbye"``.
In other words, invocation order is enforced *between* but not *within* ``then:`` blocks.
.. note:: Splitting up a ``then:`` block with ``and:`` does not impose any ordering, as ``and:``
is only meant for documentation purposes and doesn't carry any semantics.
Mocking Classes
~~~~~~~~~~~~~~~
Besides interfaces, Spock also supports mocking of classes. Mocking classes works
just like mocking interfaces; the only additional requirement is to put ``cglib-nodep-2.2`` or higher
and ``objenesis-1.2`` or higher on the class path. If either of these libraries is missing from
the class path, Spock will gently let you know.
Stubbing
--------
Stubbing is the act of making collaborators respond to method calls in a certain way. When stubbing
a method, you don't care if and how many times the method is going to be called; you just want it to
return some value, or perform some side effect, *whenever* it gets called.
For the sake of the following examples, let's modify the ``Subscriber``'s ``receive`` method
to return a status code that tells if the subscriber was able to process a message::
interface Subscriber {
String receive(String message)
}
Now, let's make the ``receive`` method return ``"ok"`` on every invocation::
subscriber.receive(_) >> "ok"
Read out aloud: "*Whenever* the subscriber receives a message, *make* it respond with 'ok'."
Compared to a mocked interaction, a stubbed interaction has no cardinality on the left end, but adds a
*response generator* on the right end::
subscriber.receive(_) >> "ok"
| | | |
| | | response generator
| | argument constraint
| method constraint
target constraint
A stubbed interaction can be declared in the usual places: either inside a ``then:`` block, or anywhere before a
``when:`` block. (See :ref:`WhereToDeclareInteractions` for the details.) If a mock object is only used for stubbing,
it's common to declare interactions :ref:`at mock creation time ` or in a
``setup:`` block.
Returning Fixed Values
~~~~~~~~~~~~~~~~~~~~~~
We have already seen the use of the right-shift (``>>``) operator to return a fixed value::
subscriber.receive(_) >> "ok"
To return different values for different invocations, use multiple interactions::
subscriber.receive("message1") >> "ok"
subscriber.receive("message2") >> "fail"
This will return ``"ok"`` whenever ``"message1"`` is received, and ``"fail"`` whenever
``"message2"`` is received. There is no limit as to which values can be returned, provided they are
compatible with the method's declared return type.
Returning Sequences of Values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To return different values on successive invocations, use the triple-right-shift (``>>>``) operator::
subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
This will return ``"ok"`` for the first invocation, ``"error"`` for the second and third invocation,
and ``"ok"`` for all remaining invocations. The right-hand side must be a value that Groovy knows how to iterate over;
in this example, we've used a plain list.
Computing Return Values
~~~~~~~~~~~~~~~~~~~~~~~
To compute a return value based on the method's argument, use the the right-shift (``>>``) operator together with a closure.
If the closure declares a single untyped parameter, it gets passed the method's argument list::
subscriber.receive(_) >> { args -> args[0].size() > 3 ? "ok" : "fail" }
Here ``"ok"`` gets returned if the message is more than three characters long, and ``"fail"`` otherwise.
In most cases it would be more convenient to have direct access to the method's arguments. If the closure declares more
than one parameter or a single *typed* parameter, method arguments will be mapped one-by-one to closure
parameters [#closureDestructuring]_::
subscriber.receive(_) >> { String message -> message.size() > 3 ? "ok" : "fail" }
This response generator behaves the same as the previous one, but is arguably more readable.
If you find yourself in need of more information about a method invocation than its arguments, have a look at
``org.spockframework.mock.IMockInvocation``. All methods declared in this interface are available inside the closure,
without a need to prefix them. (In Groovy terminology, the closure *delegates* to an instance of ``IMockInvocation``.)
Performing Side Effects
~~~~~~~~~~~~~~~~~~~~~~~
Sometimes you may want to do more than just computing a return value. A typical example is
throwing an exception. Again, closures come to the rescue::
subscriber.receive(_) >> { throw new InternalError("ouch") }
Of course, the closure can contain more code, for example a ``println`` statement. It
will get executed every time an incoming invocation matches the interaction.
Chaining Method Responses
~~~~~~~~~~~~~~~~~~~~~~~~~
Method responses can be chained::
subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw new InternalError() } >> "ok"
This will return ``"ok", "fail", "ok"`` for the first three invocations, throw ``InternalError``
for the fourth invocations, and return ``ok`` for any further invocation.
Combining Mocking and Stubbing
------------------------------
Mocking and stubbing go hand-in-hand::
1 * subscriber.receive("message1") >> "ok"
1 * subscriber.receive("message2") >> "fail"
When mocking and stubbing the same method call, they have to happen in the same interaction.
In particular, the following Mockito-style splitting of stubbing and mocking into two separate
statements will *not* work::
setup:
subscriber.receive("message1") >> "ok"
when:
publisher.send("message1")
then:
1 * subscriber.receive("message1")
As explained in :ref:`WhereToDeclareInteractions`, 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
get a chance to match.
.. note:: Mocking and stubbing of the same method call has to happen in the same interaction.
.. _OtherKindsOfMockObjects:
Other Kinds of Mock Objects (New in 0.7)
----------------------------------------
So far, we have created mock objects with the ``MockingApi.Mock`` method. Aside from
this method, the ``MockingApi`` class provides a couple of other factory methods for creating
more specialized kinds of mock objects.
.. _Stubs:
Stubs
~~~~~
A *stub* is created with the ``MockingApi.Stub`` factory method::
def subscriber = Stub(Subscriber)
Whereas a mock can be used both for stubbing and mocking, a stub can only be used for stubbing.
Limiting a collaborator to a stub communicates its role to the readers of the specification.
.. note:: If a stub invocation matches a *mandatory* interaction (like ``1 * foo.bar()``),
an ``InvalidSpecException`` is thrown.
Like a mock, a stub allows unexpected invocations. However, the values returned by a stub in such cases are more ambitious:
* For primitive types, the primitive type's default value is returned.
* For non-primitive numerical values (like ``BigDecimal``), zero is returned.
* For non-numerical values, an "empty" or "dummy" object is returned. This could mean an empty String, an empty collection,
an object constructed from its default constructor, or another stub returning default values.
See class ``org.spockframework.mock.EmptyOrDummyResponse`` for the details.
A stub often has a fixed set of interactions, which makes :ref:`declaring interactions at mock creation time
` particularly attractive::
def subscriber = Stub(Subscriber) {
receive("message1") >> "ok"
receive("message2") >> "fail"
}
.. _Spies:
Spies
~~~~~
(Think twice before using this feature. It might be better to change the design of the code under specification.)
A *spy* is created with the ``MockingApi.Spy`` factory method::
def subscriber = Spy(SubscriberImpl, constructorArgs: ["Fred"])
A spy is always based on a real object. Hence you must provide a class type rather
than an interface type, along with any constructor arguments for the type.
If no constructor arguments are provided, the type's default constructor will be used.
Method calls on a spy are automatically delegated to the real object. Likewise, values
returned from the real object's methods are passed back to the caller via the spy.
After creating a spy, you can listen in on the conversation between the caller and the real object underlying the spy::
1 * subscriber.receive(_)
Apart from making sure that ``receive`` gets called exactly once,
the conversation between the publisher and the ``SubscriberImpl`` instance underlying the spy remains unaltered.
When stubbing a method on a spy, the real method no longer gets called::
subscriber.receive(_) >> "ok"
Instead of calling ``SubscriberImpl.receive``, the ``receive`` method will now simply return ``"ok"``.
Sometimes, it is desirable to both execute some code *and* delegate to the real method::
subscriber.receive(_) >> { String message -> callRealMethod(); message.size() > 3 ? "ok" : "fail" }
Here we use ``callRealMethod()`` to delegate the method invocation to the real object.
Note that we don't have to pass the ``message`` argument along; this is taken care of automatically. `callRealMethod()``
returns the real invocation's result, but in this example we opted to return our own result instead.
If we had wanted to pass a different message to the real method, we could have used ``callRealMethodWithArgs("changed message")``.
.. _PartialMocks:
Partial Mocks
~~~~~~~~~~~~~
(Think twice before using this feature. It might be better to change the design of the code under specification.)
Spies can also be used as partial mocks::
// this is now the object under specification, not a collaborator
def persister = Spy(MessagePersister) {
// stub a call on the same object
isPersistable(_) >> true
}
when:
persister.receive("msg")
then:
// demand a call on the same object
1 * persister.persist("msg")
.. _GroovyMocks:
Groovy Mocks (New in 0.7)
-------------------------
So far, all the mocking features we have seen work the same no matter if the calling code is written in Java or Groovy.
By leveraging Groovy's dynamic capabilities, Groovy mocks offer some additional features specifically for testing Groovy code.
They are created with the ``MockingApi.GroovyMock()``, ``MockingApi.GroovyStub()``, and ``MockingApi.GroovySpy()`` factory methods.
.. admonition:: When Should Groovy Mocks be Favored over Regular Mocks?
Groovy mocks should be used when the code under specification is written in Groovy *and* some of the unique Groovy
mock features are needed. When called from Java code, Groovy mocks will behave like regular mocks. Note that it
isn't necessary to use a Groovy mock merely because the code under specification and/or mocked type is written
in Groovy. Unless you have a concrete reason to use a Groovy mock, prefer a regular mock.
Mocking Dynamic Methods
~~~~~~~~~~~~~~~~~~~~~~~
All Groovy mocks implement the ``GroovyObject`` interface. They support the mocking and stubbing of
dynamic methods as if they were physically declared methods::
def subscriber = GroovyMock(Subscriber)
1 * subscriber.someDynamicMethod("hello")
.. _MockingAllInstancesOfAType:
Mocking All Instances of a Type
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(Think twice before using this feature. It might be better to change the design of the code under specification.)
Usually, Groovy mocks need to be injected into the code under specification just like regular mocks.
However, when a Groovy mock is created as *global*, it automagically replaces all real instances
of the mocked type for the duration of the feature method [#automagic]_::
def publisher = new Publisher()
publisher << new RealSubscriber() << new RealSubscriber()
def anySubscriber = GroovyMock(RealSubscriber, global: true)
when:
publisher.publish("message")
then:
2 * anySubscriber.receive("message")
Here, we set up the publisher with two instances of a real subscriber implementation.
Then we create a global mock of the *same* type. This reroutes all method calls on the
real subscribers to the mock object. The mock object's instance isn't ever passed to the publisher;
it is only used to describe the interaction.
.. note:: A global mock can only be created for a class type. It effectively replaces
all instances of that type for the duration of the feature method.
Since global mocks have a somewhat, well, global effect, it's often convenient
to use them together with ``GroovySpy``. This leads to the real code getting
executed *unless* an interaction matches, allowing you to selectively listen
in on objects and change their behavior just where needed.
.. sidebar:: How Are Global Groovy Mocks Implemented?
Global Groovy mocks get their super powers from Groovy meta-programming. To be more precise,
every globally mocked type is assigned a custom meta class for the duration of the feature method.
Since a global Groovy mock is still based on a CGLIB proxy, it will retain its general mocking capabilities
(but not its super powers) when called from Java code.
.. _MockingConstructors:
Mocking Constructors
~~~~~~~~~~~~~~~~~~~~
(Think twice before using this feature. It might be better to change the design of the code under specification.)
Global mocks support mocking of constructors::
def anySubscriber = GroovySpy(RealSubscriber, global: true)
1 * new RealSubscriber("Fred")
Since we are using a spy, the object returned from the constructor call remains unchanged.
To change which object gets constructed, we can stub the constructor::
new RealSubscriber("Fred") >> new RealSubscriber("Barney")
Now, whenever some code tries to construct a subscriber named Fred, we'll construct
a subscriber named Barney instead.
.. _MockingStaticMethods:
Mocking Static Methods
~~~~~~~~~~~~~~~~~~~~~~
(Think twice before using this feature. It might be better to change the design of the code under specification.)
Global mocks support mocking and stubbing of static methods::
def anySubscriber = GroovySpy(RealSubscriber, global: true)
1 * RealSubscriber.someStaticMethod("hello") >> 42
The same works for dynamic static methods.
When a global mock is used solely for mocking constructors and static methods,
the mock's instance isn't really needed. In such a case one can just write::
GroovySpy(RealSubscriber, global: true)
Advanced Features (New in 0.7)
------------------------------
Most of the time you shouldn't need these features. But if you do, you'll be glad to have them.
.. _ALaCarteMocks:
A la Carte Mocks
~~~~~~~~~~~~~~~~
At the end of the day, the ``Mock()``, ``Stub()``, and ``Spy()`` factory methods are just precanned ways to
create mock objects with a certain configuration. If you want more fine-grained control over a mock's configuration,
have a look at the ``org.spockframework.mock.IMockConfiguration`` interface. All properties of this interface
[#mockConfiguration]_ can be passed as named arguments to the ``Mock()`` method. For example::
def person = Mock(name: "Fred", type: Person, defaultResponse: ZeroOrNullResponse, verified: false)
Here, we create a mock whose default return values match those of a ``Mock()``, but whose invocations aren't
verified (as for a ``Stub()``). Instead of passing ``ZeroOrNullResponse``, we could have supplied our own custom
``org.spockframework.mock.IDefaultResponse`` for responding to unexpected method invocations.
.. _DetectingMockObjects:
Detecting Mock Objects
~~~~~~~~~~~~~~~~~~~~~~
To find out whether a particular object is a Spock mock object, use a ``org.spockframework.mock.MockDetector``::
def detector = new MockDetector()
def list1 = []
def list2 = Mock(List)
expect:
!detector.isMock(list1)
detector.isMock(list2)
A detector can also be used to get more information about a mock object::
def mock = detector.asMock(list2)
expect:
mock.name == "list2"
mock.type == List
mock.nature == MockNature.MOCK
Further Reading
---------------
To learn more about interaction-based testing, we recommend the following resources:
* `Endo-Testing: Unit Testing with Mock Objects `_
Paper from the XP2000 conference that introduces the concept of mock objects.
* `Mock Roles, not Objects `_
Paper from the OOPSLA2004 conference that explains how to do mocking *right*.
* `Mocks Aren't Stubs `_
Martin Fowler's take on mocking.
* `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.
.. rubric:: Footnotes
.. [#creating] For additional ways to create mock objects, see :ref:`OtherKindsOfMockObjects`
and :ref:`ALaCarteMocks`.
.. [#targetContext] The ``subscriber`` variable cannot be referenced from the closure because it is being declared as
part of the same statement.
.. [#automagic] You may know this behavior from Groovy's
`MockFor `_ and
`StubFor `_ facilities.
.. [#closureDestructuring] The destructuring semantics for closure arguments come straight from Groovy.
.. [#mockConfiguration] Because mock configurations are immutable, the interface contains just the properties' getters. spock-spock-0.7-groovy-2.0/docs/introduction.rst 0000664 0000000 0000000 00000000650 12034506303 0021634 0 ustar 00root root 0000000 0000000 Introduction
============
Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd
is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most
IDEs, build tools, and continuous integration servers. Spock is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans,
and other fascinating life forms. spock-spock-0.7-groovy-2.0/docs/make.bat 0000664 0000000 0000000 00000010657 12034506303 0017776 0 ustar 00root root 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\SpockFramework.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\SpockFramework.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end
spock-spock-0.7-groovy-2.0/docs/migration_guide.rst 0000664 0000000 0000000 00000006365 12034506303 0022272 0 ustar 00root root 0000000 0000000 Migration Guide
===============
This page explains incompatible changes between successive versions and provides suggestions on how to deal with them.
0.7
---
Client code must be recompiled in order to work with Spock 0.7. This includes third-party Spock extensions and base classes.
No known source incompatible changes.
0.6
---
Class initialization order
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note:: This only affects cases where one specification class inherits from another one.
Given these specifications::
class Base extends Specification {
def base1 = "base1"
def base2
def setup() { base2 = "base2" }
}
class Derived extends Base {
def derived1 = "derived1"
def derived2
def setup() { derived2 = "derived2" }
}
In 0.5, above assignments happened in the order ``base1``, ``base2``, ``derived1``, ``derived2``. In other words, field initializers were executed right before the setup method in the same class. In 0.6, assignments happen in the order ``base1``, ``derived1``, ``base2``, ``derived2``. This is a more conventional order that solves a few problems that users faced with the previous behavior, and also allows us to support JUnit's new ``TestRule``. As a result of this change, the following will no longer work::
class Base extends Specification {
def base
def setup() { base = "base" }
}
class Derived extends Base {
def derived = base + "derived" // base is not yet set
}
To overcome this problem, you can either use a field initializer for ``base``, or move the assignment of ``derived`` into a setup method.
``@Unroll`` naming pattern syntax
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note:: This is not a change from 0.5, but a change compared to 0.6-SNAPSHOT.
.. note:: This only affects the Groovy 1.8 and 2.0 variants.
In 0.5, the naming pattern was string based::
@Unroll("maximum of #a and #b is #c")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 2 | 2
}
In 0.6-SNAPSHOT, this was changed to a closure returning a ``GString``::
@Unroll({"maximum of $a and $b is $c"})
def "maximum of two numbers"() { ... }
For various reasons, the new syntax didn't work out as we had hoped, and eventually we decided to go back to the string based syntax. See :ref:`improved-unroll-0.6` for recent improvements to that syntax.
Hamcrest matcher syntax
~~~~~~~~~~~~~~~~~~~~~~~
.. note:: This only affects users moving from the Groovy 1.7 to the 1.8 or 2.0 variant.
Spock offers a very neat syntax for using `Hamcrest `_ matchers::
import static spock.util.matcher.HamcrestMatchers.closeTo
...
expect:
answer closeTo(42, 0.001)
Due to changes made between Groovy 1.7 and 1.8, this syntax no longer works in as many cases as it did before. For example, the
following will no longer work::
expect:
object.getAnswer() closeTo(42, 0.001)
To avoid such problems, use ``HamcrestSupport.that``::
import static spock.util.matcher.HamcrestSupport.that
...
expect:
that answer, closeTo(42, 0.001)
A future version of Spock will likely remove the former syntax and strengthen the latter one.
spock-spock-0.7-groovy-2.0/docs/new_and_noteworthy.rst 0000664 0000000 0000000 00000035575 12034506303 0023046 0 ustar 00root root 0000000 0000000 New and Noteworthy
==================
0.7
~~~
Snapshot Repository Moved
-------------------------
Spock snapshots are now available from http://oss.sonatype.org/content/repositories/snapshots/.
New Reference Documentation
---------------------------
The new Spock reference documentation is available at http://docs.spockframework.org.
It will gradually replace the documentation at http://wiki.spockframework.org.
Each Spock version is documented separately (e.g. http://docs.spockframework.org/en/spock-0.7-groovy-1.8).
Documentation for the latest Spock snapshot is at http://docs.spockframework.org/en/latest.
As of Spock 0.7, the chapters on :ref:`DataDrivenTesting` and :ref:`InteractionBasedTesting` are complete.
Improved Mocking Failure Message for ``TooManyInvocationsError``
----------------------------------------------------------------
The diagnostic message accompanying a ``TooManyInvocationsError`` has been greatly improved.
Here is an example::
Too many invocations for:
3 * person.sing(_) (4 invocations)
Matching invocations (ordered by last occurrence):
2 * person.sing("do") <-- this triggered the error
1 * person.sing("re")
1 * person.sing("mi")
:ref:`Reference Documentation `.
Improved Mocking Failure Message for ``TooFewInvocationsError``
---------------------------------------------------------------
The diagnostic message accompanying a ``TooFewInvocationsError`` has been greatly improved.
Here is an example::
Too few invocations for:
1 * person.sing("fa") (0 invocations)
Unmatched invocations (ordered by similarity):
1 * person.sing("re")
1 * person.say("fa")
1 * person2.shout("mi")
:ref:`Reference Documentation `.
Stubs
-----
Besides mocks, Spock now has explicit support for stubs::
def person = Stub(Person)
A stub is a restricted form of mock object that responds to invocations without ever demanding them.
Other than not having a cardinality, a stub's interactions look just like a mock's interactions.
Using a stub over a mock is an effective way to communicate its role to readers of the specification.
:ref:`Reference Documentation `.
Spies
-----
Besides mocks, Spock now has support for spies::
def person = Spy(Person, constructorArgs: ["Fred"])
A spy sits atop a real object, in this example an instance of class ``Person``. All invocations on the spy
that don't match an interaction are delegated to that object. This allows to listen in on and selectively
change the behavior of the real object. Furthermore, spies can be used as partial mocks.
:ref:`Reference documentation `.
Declaring Interactions at Mock Creation Time
--------------------------------------------
Interactions can now be declared at mock creation time::
def person = Mock(Person) {
sing() >> "tra-la-la
3 * eat()
}
This feature is particularly attractive for `Stubs`_.
:ref:`Reference Documentation `.
Groovy Mocks
------------
Spock now offers specialized mock objects for spec'ing Groovy code::
def mock = GroovyMock(Person)
def stub = GroovyStub(Person)
def spy = GroovySpy(Person)
A Groovy mock automatically implements ``groovy.lang.GroovyObject``. It allows stubbing and mocking
of dynamic methods just like for statically declared methods. When a Groovy mock is called from Java
rather than Groovy code, it behaves like a regular mock.
:ref:`Reference Documentation `.
Global Mocks
------------
A Groovy mock can be made *global*::
GroovySpy(Person, global: true)
A global mock can only be created for a class type. It effectively replaces all instances of that type and makes them
amenable to stubbing and mocking. (You may know this behavior from Groovy's ``MockFor`` and ``StubFor`` facilities.)
Furthermore, a global mock allows mocking of the type's constructors and static methods.
:ref:`Reference Documentation `.
Grouping Conditions with Same Target Object
-------------------------------------------
Inspired from Groovy's ``Object.with`` method, the ``Specification.with`` method allows to group conditions
involving the same target object::
def person = new Person(name: "Fred", age: 33, sex: "male")
expect:
with(person) {
name == "Fred"
age == 33
sex == "male"
}
Grouping Interactions with Same Target Object
---------------------------------------------
The ``with`` method can also be used for grouping interactions::
def service = Mock(Service)
app.service = service
when:
app.run()
then:
with(service) {
1 * start()
1 * act()
1 * stop()
}
:ref:`Reference Documentation `.
Polling Conditions
------------------
``spock.util.concurrent.PollingConditions`` joins ``AsyncConditions`` and ``BlockingVariable(s)`` as another utility for
testing asynchronous code::
def person = new Person(name: "Fred", age: 22)
def conditions = new PollingConditions(timeout: 10)
when:
Thread.start {
sleep(1000)
person.age == 42
sleep(5000)
person.name == "Barney"
}
then:
conditions.within(2) {
assert person.age == 42
}
conditions.eventually {
assert person.name == "Fred"
}
Experimental DSL Support for Eclipse
------------------------------------
Spock now ships with a DSL descriptor that lets Groovy Eclipse better
understand certain parts of Spock's DSL. The descriptor is automatically
detected and activated by the IDE. Here is an example::
// currently need to type variable for the following to work
Person person = new Person(name: "Fred", age: 42)
expect:
with(person) {
name == "Fred" // editor understands and auto-completes 'name'
age == 42 // editor understands and auto-completes 'age'
}
Another example::
def person = Stub(Person) {
getName() >> "Fred" // editor understands and auto-completes 'getName()'
getAge() >> 42 // editor understands and auto-completes 'getAge()'
}
DSL support is activated for Groovy Eclipse 2.7.1 and higher. If necessary,
it can be deactivated in the Groovy Eclipse preferences.
Experimental DSL Support for IntelliJ IDEA
------------------------------------------
Spock now ships with a DSL descriptor that lets Intellij IDEA better
understand certain parts of Spock's DSL. The descriptor is automatically
detected and activated by the IDE. Here is an example::
def person = new Person(name: "Fred", age: 42)
expect:
with(person) {
name == "Fred" // editor understands and auto-completes 'name'
age == 42 // editor understands and auto-completes 'age'
}
Another example::
def person = Stub(Person) {
getName() >> "Fred" // editor understands and auto-completes 'getName()'
getAge() >> 42 // editor understands and auto-completes 'getAge()'
}
DSL support is activated for IntelliJ IDEA 11.1 and higher.
Splitting up Class Specification
--------------------------------
Parts of class ``spock.lang.Specification`` were pulled up into two new super classes: ``spock.lang.MockingApi``
now contains all mocking-related methods, and ``org.spockframework.lang.SpecInternals`` contains internal methods
which aren't meant to be used directly.
Improved Failure Messages for ``notThrown`` and ``noExceptionThrown``
---------------------------------------------------------------------
Instead of just passing through exceptions, ``Specification.notThrown`` and ``Specification.noExceptionThrown``
now fail with messages like::
Expected no exception to be thrown, but got 'java.io.FileNotFoundException'
Caused by: java.io.FileNotFoundException: ...
``HamcrestSupport.expect``
--------------------------
Class ``spock.util.matcher.HamcrestSupport`` has a new ``expect`` method that makes
[Hamcrest](http://code.google.com/p/hamcrest/) assertions read better in then-blocks::
when:
def x = computeValue()
then:
expect x, closeTo(42, 0.01)
@Beta
-----
Recently introduced classes and methods may be annotated with @Beta, as a sign that they may still undergo incompatible
changes. This gives us a chance to incorporate valuable feedback from our users. (Yes, we need your feedback!) Typically,
a @Beta annotation is removed within one or two releases.
Fixed Issues
------------
See the `issue tracker `_ for a list of fixed issues.
0.6
~~~
Mocking Improvements
--------------------
The mocking framework now provides better diagnostic messages in some cases.
Multiple result declarations can be chained. The following causes method bar to throw an ``IOException`` when first called, return the numbers one, two, and three on the next calls, and throw a ``RuntimeException`` for all subsequent calls::
foo.bar() >> { throw new IOException() } >>> [1, 2, 3] >> { throw new RuntimeException() }
It's now possible to match any argument list (including the empty list) with ``foo.bar(*_)``.
Method arguments can now be constrained with `Hamcrest `_ matchers::
import static spock.util.matcher.HamcrestMatchers.closeTo
...
1 * foo.bar(closeTo(42, 0.001))
Extended JUnit Rules Support
----------------------------
In addition to rules implementing ``org.junit.rules.MethodRule`` (which has been deprecated in JUnit 4.9), Spock now also supports rules implementing the new ``org.junit.rules.TestRule`` interface. Also supported is the new ``@ClassRule`` annotation. Rule declarations are now verified and can leave off the initialization part. I that case Spock will automatically initialize the rule by calling the default constructor.
The ``@TestName`` rule, and rules in general, now honor the ``@Unroll`` annotation and any defined naming pattern.
See `Issue 240 `_ for a known limitation with Spock's TestRule support.
Condition Rendering Improvements
--------------------------------
When two objects are compared with the ``==`` operator, they are unequal, but their string representations are the same, Spock will now print the objects' types::
enteredNumber == 42
| |
| false
42 (java.lang.String)
JUnit Fixture Annotations
-------------------------
Fixture methods can now be declared with JUnit's ``@Before``, ``@After``, ``@BeforeClass``, and ``@AfterClass`` annotations, as an addition or alternative to Spock's own fixture methods. This was particularly needed for Grails 2.0 support.
Tapestry 5.3 Support
--------------------
Thanks to a contribution from `Howard Lewis Ship `_, the Tapestry module is now compatible with Tapestry 5.3. Older 5.x versions are still supported.
IBM JDK Support
---------------
Spock now runs fine on IBM JDKs, working around a bug in the IBM JDK's verifier.
Improved JUnit Compatibility
----------------------------
``org.junit.internal.AssumptionViolatedException`` is now recognized and handled as known from JUnit. ``@Unrolled`` methods no longer cause "yellow" nodes in IDEs.
.. _improved-unroll-0.6:
Improved ``@Unroll``
--------------------
The ``@Unroll`` naming pattern can now be provided in the method name, instead of as an argument to the annotation::
@Unroll
def "maximum of #a and #b is #c"() {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 2 | 2
}
The naming pattern now supports property access and zero-arg method calls::
@Unroll
def "#person.name.toUpperCase() is #person.age years old"() { ... }
The ``@Unroll`` annotation can now be applied to a spec class. In this case, all data-driven feature methods in the class will be unrolled.
Improved ``@Timeout``
---------------------
The ``@Timeout`` annotation can now be applied to a spec class. In this case, the timeout applies to all feature methods (individually) that aren't already annotated with ``@Timeout``.
Timed methods are now executed on the regular test framework thread. This can be important for tests that rely on thread-local state (like Grails integration tests). Also the interruption behavior has been improved, to increase the chance that a timeout can be enforced.
The failure exception that is thrown when a timeout occurs now contains the stacktrace of test execution, allowing you to see where the test was “stuck” or how far it got in the allocated time.
Improved Data Table Syntax
--------------------------
Table cells can now be separated with double pipes. This can be used to visually set apart expected outputs from provided inputs::
...
where:
a | b || sum
1 | 2 || 3
3 | 1 || 4
Groovy 1.8/2.0 Support
----------------------
Spock 0.6 ships in three variants for Groovy 1.7, 1.8, and 2.0. Make sure to pick the right version - for example, for Groovy 1.8 you need to use spock-core-0.6-groovy-1.8 (likewise for all other modules). The Groovy 2.0 variant is based on Groovy 2.0-beta-3-SNAPSHOT and only available from http://m2repo.spockframework.org. The Groovy 1.7 and 1.8 variants are also available from Maven Central. The next version of Spock will no longer support Groovy 1.7.
Grails 2.0 Support
------------------
Spock's Grails plugin was split off into a separate project and now lives at http://github.spockframework.org/spock-grails. The plugin supports both Grails 1.3 and 2.0.
The Spock Grails plugin supports all of the new Grails 2.0 test mixins, effectively deprecating the existing unit testing classes (e.g. UnitSpec). For integration testing, IntegrationSpec must still be used.
IntelliJ IDEA Integration
-------------------------
The folks from `JetBrains `_ have added a few handy features around data tables. Data tables will now be layed out automatically when reformatting code. Data variables are no longer shown as "unknown" and have their types inferred from the values in the table (!).
GitHub Repository
-----------------
All source code has moved to http://github.spockframework.org/. The `Grails Spock plugin `_, `Spock Example `_ project, and `Spock Web Console `_ now have their own GitHub projects. Also available are slides and code for various Spock presentations (like `this one `_).
Gradle Build
------------
Spock is now exclusively built with Gradle. Building Spock yourself is as easy as cloning the `GitHub repo `_ and executing ``gradlew build``. No build tool installation is required; the only prerequisite for building Spock is a JDK installation (1.5 or higher).
Fixed Issues
------------
See the `issue tracker `_ for a list of fixed issues.
spock-spock-0.7-groovy-2.0/gradle/ 0000775 0000000 0000000 00000000000 12034506303 0016666 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/gradle/common.gradle 0000664 0000000 0000000 00000000165 12034506303 0021340 0 ustar 00root root 0000000 0000000 ext {
isSnapshotVersion = project.version.endsWith("-SNAPSHOT")
isRootProject = project == project.rootProject
}
spock-spock-0.7-groovy-2.0/gradle/ide.gradle 0000664 0000000 0000000 00000001410 12034506303 0020603 0 ustar 00root root 0000000 0000000 allprojects {
apply plugin: "idea"
apply plugin: "eclipse"
}
def gitIgnore = file(".gitignore").readLines()
def gitIgnoreDirs = gitIgnore*.trim().findAll { !it.startsWith("#") && it.endsWith("/") }
def (topLevelDirs, allLevelDirs) = gitIgnoreDirs.split { it.startsWith("/") }
topLevelDirs = topLevelDirs.collect { it.substring(1) }
idea {
project {
languageLevel "1.5"
configure(modules) { module ->
def prj = module.project
excludeDirs = prj.files(allLevelDirs) as Set
if (prj == prj.rootProject) excludeDirs += (prj.files(topLevelDirs) as Set)
}
ipr {
withXml { provider ->
def node = provider.asNode()
node.component.find { it.'@name' == 'VcsDirectoryMappings' }?.mapping[0].'@vcs' = 'Git'
}
}
}
} spock-spock-0.7-groovy-2.0/gradle/publishMaven.gradle 0000664 0000000 0000000 00000004540 12034506303 0022506 0 ustar 00root root 0000000 0000000 apply plugin: "maven"
def basePom = {
project {
name project.displayName
description project.description
url "http://spockframework.org"
licenses {
license {
name "The Apache Software License, Version 2.0"
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
}
}
scm {
connection "scm:git:git://github.com/spockframework/spock.git"
developerConnection "scm:git:ssh://git@github.com/spockframework/spock.git"
url "http://github.spockframework.org/spock"
}
developers {
developer {
id "pniederw"
name "Peter Niederwieser"
email "pniederw@gmail.com"
}
developer {
id "ldaley"
name "Luke Daley"
email "ld@ldaley.com"
}
}
}
}
def deployers = []
project.afterEvaluate {
configure(deployers) {
pom basePom
}
}
install {
deployers << repositories.mavenInstaller
}
uploadArchives {
deployers << repositories.mavenDeployer {
if (isSnapshotVersion) {
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
if (project.hasProperty("sonatypeOssUsername")) {
authentication(userName: sonatypeOssUsername, password: sonatypeOssPassword)
}
}
} else {
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
if (project.hasProperty("sonatypeOssUsername")) {
authentication(userName: sonatypeOssUsername, password: sonatypeOssPassword)
}
}
}
}
}
def poms = deployers*.pom
def optionalDeps = []
def providedDeps = []
def internalDeps = []
ext {
modifyPom = { Closure modification ->
poms.each {
it.whenConfigured(modification)
}
}
optional = { optionalDeps << it; it }
provided = { providedDeps << it; it }
internal = { internalDeps << it; it }
}
modifyPom { pom ->
optionalDeps.each { dep ->
pom.dependencies.find { it.artifactId == dep.name }.optional = true
}
providedDeps.each { dep ->
pom.dependencies.find { it.artifactId == dep.name }.scope = "provided"
}
internalDeps.each { dep ->
pom.dependencies.removeAll { it.artifactId == dep.name }
}
// no need to publish test dependencies
pom.dependencies.removeAll { it.scope == "test" }
}
deployers*.beforeDeployment { signing.signPom(it) } spock-spock-0.7-groovy-2.0/settings.gradle 0000775 0000000 0000000 00000000416 12034506303 0020454 0 ustar 00root root 0000000 0000000 include "spock-core"
include "spock-guice"
include "spock-maven"
include "spock-specs"
include "spock-spring"
include "spock-tapestry"
include "spock-unitils"
rootProject.name = "spock"
rootProject.children.each {
it.buildFileName = it.name + ".gradle" - "spock-"
}
spock-spock-0.7-groovy-2.0/spock-core/ 0000775 0000000 0000000 00000000000 12034506303 0017475 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/core.gradle 0000775 0000000 0000000 00000001342 12034506303 0021610 0 ustar 00root root 0000000 0000000 apply from: script("publishMaven")
displayName = "Spock Framework - Core Module"
description = "Spock is a testing and specification framework for Java and Groovy applications. \
What makes it stand out from the crowd is its beautiful and highly expressive specification language. \
Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. \
Spock is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans, and other fascinating life forms."
dependencies {
compile libs.groovy // simplest way to add Groovy dependency to POM
compile libs.junit
compile libs.ant, optional
compile libs.asm, optional
compile libs.cglib, optional
compile libs.objenesis, optional
}
spock-spock-0.7-groovy-2.0/spock-core/src/ 0000775 0000000 0000000 00000000000 12034506303 0020264 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/ 0000775 0000000 0000000 00000000000 12034506303 0021210 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/ 0000775 0000000 0000000 00000000000 12034506303 0022535 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/ 0000775 0000000 0000000 00000000000 12034506303 0023654 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/ 0000775 0000000 0000000 00000000000 12034506303 0024631 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/EmbeddedSpecCompiler.groovy 0000664 0000000 0000000 00000006725 12034506303 0032111 0 ustar 00root root 0000000 0000000 /*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spock.util
import org.codehaus.groovy.control.MultipleCompilationErrorsException
import org.junit.Test
import org.junit.internal.runners.model.MultipleFailureException
import org.junit.runner.RunWith
import org.spockframework.runtime.SpecUtil
import org.spockframework.util.NotThreadSafe
import spock.lang.Specification
/**
* Utility class that allows to compile (fragments of) specs programmatically.
* Mainly intended for spec'ing Spock itself.
*
* @author Peter Niederwieser
*/
@NotThreadSafe
class EmbeddedSpecCompiler {
final GroovyClassLoader loader = new GroovyClassLoader(getClass().classLoader)
boolean unwrapCompileException = true
String imports = ""
void addPackageImport(String pkg) {
imports += "import $pkg.*;"
}
void addPackageImport(Package pkg) {
addPackageImport(pkg.name)
}
void addClassImport(String className) {
imports += "import $className;"
}
void addClassImport(Class> clazz) {
def importName = clazz.name
if (clazz.memberClass) {
importName = importName.reverse().replaceFirst(/\$/, ".").reverse()
}
addClassImport(importName)
}
void addClassMemberImport(String className) {
imports += "import static $className.*;"
}
void addClassMemberImport(Class> clazz) {
addClassMemberImport(clazz.name)
}
/**
* Compiles the given source code, and returns all Spock specifications
* contained therein (but not other classes).
*/
List compile(String source) {
doCompile(imports + source)
}
List compileWithImports(String source) {
addPackageImport(Specification.package )
// one-liner keeps line numbers intact
doCompile "package apackage; $imports ${source.trim()}"
}
Class compileSpecBody(String source) {
// one-liner keeps line numbers intact; newline safeguards against source ending in a line comment
compileWithImports("class ASpec extends Specification { ${source.trim() + '\n'} }")[0]
}
Class compileFeatureBody(String source) {
// one-liner keeps line numbers intact; newline safeguards against source ending in a line comment
compileSpecBody "def 'a feature'() { ${source.trim() + '\n'} }"
}
private List doCompile(String source) {
loader.clearCache()
try {
loader.parseClass(source.trim())
} catch (MultipleCompilationErrorsException e) {
def errors = e.errorCollector.errors
if (unwrapCompileException && errors.every { it.hasProperty("cause") })
if (errors.size() == 1)
throw errors[0].cause
else
throw new MultipleFailureException(errors.cause)
throw e
}
loader.loadedClasses.findAll {
SpecUtil.isSpec(it) || isJUnitTest(it) // need JUnit tests sometimes
} as List
}
private boolean isJUnitTest(Class clazz) {
clazz.isAnnotationPresent(RunWith) || clazz.methods.any { it.getAnnotation(Test) }
}
} spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/EmbeddedSpecRunner.groovy 0000664 0000000 0000000 00000006607 12034506303 0031607 0 ustar 00root root 0000000 0000000 /*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spock.util
import org.junit.runner.notification.RunListener
import org.junit.runner.*
import org.spockframework.util.NotThreadSafe
import org.spockframework.util.IThrowableFunction
import org.spockframework.runtime.RunContext
import org.spockframework.runtime.ConfigurationScriptLoader
import java.lang.reflect.Modifier
/**
* Utility class that allows to run (fragments of) specs programmatically.
* Mainly intended for spec'ing Spock itself.
*
* @author Peter Niederwieser
*/
@NotThreadSafe
class EmbeddedSpecRunner {
private final EmbeddedSpecCompiler compiler = new EmbeddedSpecCompiler(unwrapCompileException: false)
boolean throwFailure = true
List listeners = []
Closure configurationScript = null
List extensionClasses = []
boolean inheritParentExtensions = true
void addPackageImport(String pkg) {
compiler.addPackageImport(pkg)
}
void addPackageImport(Package pkg) {
compiler.addPackageImport(pkg)
}
void addClassImport(String className) {
compiler.addClassImport(className)
}
void addClassImport(Class> clazz) {
compiler.addClassImport(clazz)
}
void addClassMemberImport(String className) {
compiler.addClassMemberImport(className)
}
void addClassMemberImport(Class> clazz) {
compiler.addClassMemberImport(clazz)
}
Result runRequest(Request request) {
withNewContext {
doRunRequest(request)
}
}
Result runClasses(List classes) {
withNewContext {
doRunRequest(Request.classes(classes.findAll { !Modifier.isAbstract(it.modifiers) } as Class[]))
}
}
// it's very important to open a new context BEFORE Request.aClass/classes is invoked
// this is because Sputnik is already constructed by those methods, and has to pop
// the correct context from the stack
Result runClass(Class clazz) {
withNewContext {
doRunRequest(Request.aClass(clazz))
}
}
Result run(String source) {
runClasses(compiler.compile(source))
}
Result runWithImports(String source) {
runClasses(compiler.compileWithImports(source))
}
Result runSpecBody(String source) {
runClass(compiler.compileSpecBody(source))
}
Result runFeatureBody(String source) {
runClass(compiler.compileFeatureBody(source))
}
def withNewContext(Closure block) {
def script = configurationScript ?
new ConfigurationScriptLoader().loadClosureBasedScript(configurationScript) : null
RunContext.withNewContext(script, extensionClasses, inheritParentExtensions, block as IThrowableFunction)
}
private Result doRunRequest(Request request) {
def junitCore = new JUnitCore()
listeners.each { junitCore.addListener(it) }
def result = junitCore.run(request)
if (throwFailure && result.failureCount > 0) throw result.failures[0].exception
result
}
} spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/concurrent/ 0000775 0000000 0000000 00000000000 12034506303 0027013 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/concurrent/BlockingVariables.groovy0000664 0000000 0000000 00000005773 12034506303 0033657 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spock.util.concurrent
import java.util.concurrent.TimeUnit
import org.spockframework.util.ThreadSafe
import org.spockframework.util.TimeUtil
/**
* Provides an unlimited number of dynamic variables. Reading the value of a
* variable will block until some other thread has set the value of the variable,
* or a timeout expires. Useful for verifying state in an expect- or then-block
* that has been captured in some other thread.
*
*
Example:
*
*
* // create object under specification
* def machine = new Machine()
*
* BlockingVariables vars = new BlockingVariables()
*
* // register async callback
* machine.workDone << { result ->
* vars.result = result
* }
*
* when:
* machine.start()
*
* then:
* // blocks until workDone callback has set result, or a timeout expires
* vars.result == WorkResult.OK
*
* cleanup:
* // shut down all threads
* machine?.shutdown()
*
*
* @author Peter Niederwieser
*/
@ThreadSafe
class BlockingVariables {
private final BlockingVariablesImpl impl
/**
* Same as BlockingVariables(1, TimeUnit.SECONDS).
*/
BlockingVariables() {
this(1)
}
/**
* Instantiates a BlockingVariable with the specified timeout (in seconds).
*
* @param timeout the timeout (in seconds) for reading a variable's value.
*/
BlockingVariables(double timeout) {
impl = new BlockingVariablesImpl(timeout)
}
/**
* Instantiates a BlockingVariables instance with the specified
* timeout.
*
* @param timeout timeout for reading a variable's value
* @param unit the timeout's time unit
*
* @deprecated use {@link #BlockingVariables(double)} instead
*/
@Deprecated
BlockingVariables(int timeout, TimeUnit unit) {
this(TimeUtil.toSeconds(timeout, unit))
}
/**
* Sets a variable's value. This method should not be called directly
* but by setting a dynamic variable's value.
*
* @param name the variable's name
* @param value the variable's value
*/
void setProperty(String name, Object value) {
impl.put(name, value)
}
/**
* Gets a variable's value. Blocks until a value has been set for the variable
* or a timeout expires. This method should not be called directly but by
* getting a dynamic variable's value.
*
* @param name the variable's name
*
* @return the variable's value
*/
Object getProperty(String name) {
impl.get(name)
}
} spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/matcher/ 0000775 0000000 0000000 00000000000 12034506303 0026254 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/matcher/HamcrestMatchers.groovy 0000664 0000000 0000000 00000002731 12034506303 0032763 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spock.util.matcher
import org.hamcrest.Matcher
/**
* Factory for Hamcrest matchers that ship with Spock.
*
* @author Peter Niederwieser
*/
class HamcrestMatchers {
/**
* Tells if two numbers are equal within some range of acceptable error.
* In contrast to the equally named matcher in the Hamcrest library, this
* matcher also handles BigDecimals (and any other Numbers),
* which is important for Groovy interoperability.
*
* Example usage:
*
*
* expect:
* myPi closeTo(3.1415, 0.01)
*
*
* @param operand the expected number
* @param error the range of acceptable error
* @return a matcher that tells if two numbers are equal within some range of
* acceptable error
*/
static Matcher closeTo(Number operand, Number error) {
return new IsCloseTo(operand, error)
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/groovy/spock/util/matcher/IsCloseTo.groovy 0000664 0000000 0000000 00000003467 12034506303 0031401 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spock.util.matcher
import org.hamcrest.TypeSafeMatcher
import org.hamcrest.Description
/**
* Generalization of org.hamcrest.number.IsCloseTo to arbitrary
* Numbers (in particular BigDecimals). Otherwise almost
* identical to that class.
*/
public class IsCloseTo extends TypeSafeMatcher {
private final Number value
private final Number epsilon
IsCloseTo(Number value, Number epsilon) {
this.value = value
this.epsilon = epsilon
}
@Override
boolean matchesSafely(Number item) {
delta(item) <= epsilon
}
@Override
void describeMismatchSafely(Number item, Description mismatchDescription) {
mismatchDescription.appendValue(item)
.appendText(" differed by ")
.appendValue(delta(item))
}
void describeTo(Description description) {
description.appendText("a numeric value within ")
.appendValue(epsilon)
.appendText(" of ")
.appendValue(value)
}
private Number delta(Number item) {
// handle special values (infinity, nan)
if (item == value) return 0
(item - value).abs()
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/ 0000775 0000000 0000000 00000000000 12034506303 0022131 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/ 0000775 0000000 0000000 00000000000 12034506303 0022720 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/ 0000775 0000000 0000000 00000000000 12034506303 0025755 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/ 0000775 0000000 0000000 00000000000 12034506303 0027403 5 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/AddSlotFactory.java 0000664 0000000 0000000 00000002231 12034506303 0033126 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
import groovy.lang.MetaMethod;
import org.spockframework.runtime.GroovyRuntimeUtil;
public class AddSlotFactory implements ISlotFactory {
public ISlot create(Object owner, Type ownerType, String name) {
String addMethodName = GroovyRuntimeUtil.propertyToMethodName("add", name);
MetaMethod addMethod = GroovyRuntimeUtil.getMetaClass(owner).pickMethod(addMethodName, new Class[]{Object.class});
return addMethod != null ? new SetterLikeSlot(owner, ownerType, addMethod) : null;
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/BuilderHelper.java 0000664 0000000 0000000 00000003301 12034506303 0032771 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Modifier;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.spockframework.runtime.GroovyRuntimeUtil;
public class BuilderHelper {
public static Object createInstance(Class clazz, Object... args) {
if (args.length == 1) {
Object arg = args[0];
if (MetaClassHelper.isAssignableFrom(clazz, arg.getClass())) return arg;
// IDEA: could do additional coercions here, like Groovy does when setting a property
// (note that we don't know if we are setting a property or invoking a method):
// int -> byte (at least if it fits), etc.
}
// IDEA: could support creation of collection types here
if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
String kind = clazz.isPrimitive() ? "primitive" : clazz.isInterface() ? "interface" : "abstract";
throw new RuntimeException(String.format( "Cannot instantiate %s type %s", kind, clazz.getName()));
}
// TODO: need exception handling for better error messages?
return GroovyRuntimeUtil.invokeConstructor(clazz, args);
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/ClosureBlueprint.java0000664 0000000 0000000 00000002374 12034506303 0033555 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import groovy.lang.Closure;
import org.spockframework.runtime.GroovyRuntimeUtil;
public class ClosureBlueprint implements IBlueprint {
private final Closure closure;
private final Object subject;
public ClosureBlueprint(Closure closure, Object subject) {
this.closure = closure;
this.subject = subject;
closure.setResolveStrategy(Closure.DELEGATE_ONLY);
}
public Object getThisObject() {
return closure.getThisObject();
}
public void setDelegate(Object delegate) {
closure.setDelegate(delegate);
}
public void evaluate() {
GroovyRuntimeUtil.invokeClosure(closure, subject);
}
} spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/CollectionSlot.java 0000664 0000000 0000000 00000005476 12034506303 0033217 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.*;
import java.util.*;
import org.spockframework.gentyref.GenericTypeReflector;
import org.spockframework.util.MopUtil;
import org.spockframework.util.UnreachableCodeError;
import groovy.lang.MetaProperty;
public class CollectionSlot implements ISlot {
private final String name;
private final Object owner;
private final Type ownerType;
private final MetaProperty property;
CollectionSlot(String name, Object owner, Type ownerType, MetaProperty property) {
this.name = name;
this.owner = owner;
this.ownerType = ownerType;
this.property = property;
}
public Type getType() {
Type type = getCollectionType();
if (type instanceof ParameterizedType) return ((ParameterizedType)type).getActualTypeArguments()[0];
if (type instanceof Class) return Object.class;
throw new UnreachableCodeError();
}
private Type getCollectionType() {
Method getter = MopUtil.getterFor(property);
if (getter != null) return GenericTypeReflector.getExactReturnType(getter, ownerType);
Field field = MopUtil.fieldFor(property);
if (field != null) return GenericTypeReflector.getExactFieldType(field, ownerType);
throw new UnreachableCodeError();
}
@SuppressWarnings("unchecked")
public void write(Object value) {
Collection collection = (Collection) property.getProperty(owner);
if (collection == null) {
if (MopUtil.isWriteable(property)) {
collection = createCollection(property.getType());
property.setProperty(owner, collection);
} else {
throw new RuntimeException(String.format(
"Cannot add element to collection property '%s' because it is neither initialized nor does it have a setter",
name));
}
}
collection.add(value);
}
private Collection createCollection(Class clazz) {
if ((clazz.getModifiers() & Modifier.ABSTRACT) == 0) {
return (Collection)BuilderHelper.createInstance(clazz);
}
if (List.class.isAssignableFrom(clazz)) return new ArrayList();
if (Set.class.isAssignableFrom(clazz)) return new HashSet();
throw new RuntimeException(String.format("Don't know how to create a collection of type '%s'", clazz.getName()));
}
}
CollectionSlotFactory.java 0000664 0000000 0000000 00000003245 12034506303 0034460 0 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.regex.Pattern;
import org.spockframework.runtime.GroovyRuntimeUtil;
import org.spockframework.util.MopUtil;
import groovy.lang.MetaProperty;
public class CollectionSlotFactory implements ISlotFactory {
private static final Pattern pluralIESPattern = Pattern.compile(".*[^aeiouy]y", Pattern.CASE_INSENSITIVE);
public ISlot create(Object owner, Type ownerType, String name) {
String plural = toPluralForm(name);
MetaProperty property = GroovyRuntimeUtil.getMetaClass(owner).getMetaProperty(plural);
return property != null && Collection.class.isAssignableFrom(property.getType()) && MopUtil.isReadable(property) ?
new CollectionSlot(plural, owner, ownerType, property) : null;
}
private String toPluralForm(String word) {
if (word.toLowerCase().endsWith("s")) return word + "es";
boolean matchesIESRule = pluralIESPattern.matcher(word).matches();
return matchesIESRule ? word.substring(0, word.length() - 1) + "ies" : word + "s";
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/DelegatingScript.java0000664 0000000 0000000 00000003177 12034506303 0033506 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import groovy.lang.*;
import org.spockframework.runtime.GroovyRuntimeUtil;
public abstract class DelegatingScript extends Script {
private volatile Object $delegate;
public void $setDelegate(Object delegate) {
this.$delegate = delegate;
}
@Override
public Object getProperty(String property) {
try {
return GroovyRuntimeUtil.getProperty($delegate, property);
} catch (MissingPropertyException e) {
return super.getProperty(property);
}
}
@Override
public void setProperty(String property, Object newValue) {
try {
GroovyRuntimeUtil.setProperty($delegate, property, newValue);
} catch (MissingPropertyException e) {
super.setProperty(property, newValue);
}
}
@Override
public Object invokeMethod(String name, Object args) {
try {
return GroovyRuntimeUtil.invokeMethod($delegate, name, GroovyRuntimeUtil.asArgumentArray(args));
} catch (MissingMethodException e) {
return super.invokeMethod(name, args);
}
}
}
DelegatingScriptBlueprint.java 0000664 0000000 0000000 00000002022 12034506303 0035300 0 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
public class DelegatingScriptBlueprint implements IBlueprint {
private final DelegatingScript script;
public DelegatingScriptBlueprint(DelegatingScript script) {
this.script = script;
}
public Object getThisObject() {
return null;
}
public void setDelegate(final Object delegate) {
script.$setDelegate(delegate);
}
public void evaluate() {
script.run();
}
} spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/GestaltBuilder.java 0000664 0000000 0000000 00000001363 12034506303 0033163 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
public class GestaltBuilder {
public void build(IGestalt root) {
new Sculpturer().$form(root);
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/IBlueprint.java 0000664 0000000 0000000 00000001462 12034506303 0032326 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import org.spockframework.util.Nullable;
public interface IBlueprint {
@Nullable
Object getThisObject();
void setDelegate(Object delegate);
void evaluate();
} IConfigurationRegistry.java 0000664 0000000 0000000 00000001333 12034506303 0034640 0 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
public interface IConfigurationRegistry {
Object getConfiguration(String name);
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/IGestalt.java 0000664 0000000 0000000 00000001574 12034506303 0031771 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import org.spockframework.util.Nullable;
public interface IGestalt {
@Nullable IBlueprint getBlueprint();
Object getProperty(String name);
void setProperty(String name, Object value);
Object invokeMethod(String name, Object[] args);
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/ISlot.java 0000664 0000000 0000000 00000001357 12034506303 0031306 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
public interface ISlot {
Type getType();
void write(Object value);
} spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/ISlotFactory.java 0000664 0000000 0000000 00000001467 12034506303 0032640 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
import org.spockframework.util.Nullable;
public interface ISlotFactory {
@Nullable ISlot create(Object owner, Type ownerType, String name);
} spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/PojoBuilder.java 0000664 0000000 0000000 00000003516 12034506303 0032471 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.util.Arrays;
import java.util.List;
import groovy.lang.Closure;
// TODO: test building pojo enriched with expandometaclass/category property
// TODO: test call to void varargs method in expect: block
// (related: find all calls to MetaMethod.invoke and replace with doMethodInvoke)
// IDEA: allow syntax foo = { ... } to make it clear built object should be assigned to a property (can't handle all cases with method syntax)
// IDEA: helpful coercions (esp. for configuration): List -> Set (enables the use of list literals for sets), potentially String -> Enum
// TODO: provide a way to set visibility of methods/properties to look for
public class PojoBuilder {
private final GestaltBuilder gestaltBuilder = new GestaltBuilder();
private final List slotFactories =
Arrays.asList(new SetterSlotFactory(), new AddSlotFactory(), new CollectionSlotFactory());
public Object build(Object pojo, Closure closure) {
return build(pojo, new ClosureBlueprint(closure, pojo));
}
public Object build(Object pojo, IBlueprint blueprint) {
IGestalt gestalt = new PojoGestalt(pojo, pojo.getClass(), blueprint, slotFactories);
gestaltBuilder.build(gestalt);
return pojo;
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/PojoGestalt.java 0000664 0000000 0000000 00000006410 12034506303 0032502 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
import java.util.List;
import org.spockframework.gentyref.GenericTypeReflector;
import org.spockframework.util.CollectionUtil;
import groovy.lang.Closure;
import org.spockframework.runtime.GroovyRuntimeUtil;
public class PojoGestalt implements IGestalt {
private final Object pojo;
private final Type pojoType;
private final IBlueprint blueprint;
private final List slotFactories;
public PojoGestalt(Object pojo, Type pojoType, IBlueprint blueprint, List slotFactories) {
this.pojo = pojo;
this.pojoType = pojoType;
this.blueprint = blueprint;
this.slotFactories = slotFactories;
}
public Object getSubject() {
return pojo;
}
public IBlueprint getBlueprint() {
return blueprint;
}
public Object getProperty(String name) {
return GroovyRuntimeUtil.getProperty(pojo, name);
}
public void setProperty(String name, Object value) {
GroovyRuntimeUtil.setProperty(pojo, name, value);
}
// foo([a:1],b) and foo(a:1,b) are currently not distinguishable in Groovy
// neither are foo([a:1],b) and foo(b,a:1)
// so we should probably add some heuristics to tell them apart (look at subject's method signatures)
// same for telling apart last arg (could be blueprint or last constructor arg)
// current impl is dead stupid:
// - named args not treated specially
// - last arg is closure => treat as blueprint
public Object invokeMethod(String name, Object[] args) {
ISlot slot = findSlot(name, args);
PojoGestalt gestalt = createGestalt(slot.getType(), args);
new Sculpturer().$form(gestalt);
slot.write(gestalt.getSubject());
return gestalt.getSubject();
}
private ISlot findSlot(String name, Object[] args) {
for (ISlotFactory factory : slotFactories) {
ISlot slot = factory.create(pojo, pojoType, name);
if (slot != null) return slot;
}
throw new RuntimeException(String.format("Cannot find a slot named '%s'", name));
}
private PojoGestalt createGestalt(Type newType, Object[] args) {
Closure closure = null;
if (args != null && args.length > 0 && args[args.length - 1] instanceof Closure) {
closure = (Closure)args[args.length - 1];
args = CollectionUtil.copyArray(args, 0, args.length - 1);
}
Class> newClazz = GenericTypeReflector.erase(newType); // TODO: check that this succeeds (Type could be a TypeVariable etc.)
Object newPojo = BuilderHelper.createInstance(newClazz, args);
ClosureBlueprint newBlueprint = closure == null ? null : new ClosureBlueprint(closure, newPojo);
return new PojoGestalt(newPojo, newType, newBlueprint, slotFactories);
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/PropertySlot.java 0000664 0000000 0000000 00000003222 12034506303 0032733 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.*;
import org.spockframework.gentyref.GenericTypeReflector;
import org.spockframework.util.MopUtil;
import org.spockframework.util.UnreachableCodeError;
import groovy.lang.MetaProperty;
public class PropertySlot implements ISlot {
private final Object owner;
private final Type ownerType;
private final MetaProperty property;
PropertySlot(Object owner, Type ownerType, MetaProperty property) {
this.owner = owner;
this.ownerType = ownerType;
this.property = property;
}
public Type getType() {
// could possibly add fast path here, but be careful (inner classes etc.)
Method setter = MopUtil.setterFor(property);
if (setter != null) return GenericTypeReflector.getExactParameterTypes(setter, ownerType)[0];
Field field = MopUtil.fieldFor(property);
if (field != null) return GenericTypeReflector.getExactFieldType(field, ownerType);
throw new UnreachableCodeError();
}
public void write(Object value) {
property.setProperty(owner, value);
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/Sculpturer.java 0000664 0000000 0000000 00000004136 12034506303 0032422 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import groovy.lang.*;
import org.spockframework.runtime.GroovyRuntimeUtil;
/**
* Forms a gestalt from its blueprint.
*/
public class Sculpturer extends GroovyObjectSupport {
private IGestalt $gestalt;
public void $form(IGestalt gestalt) {
IBlueprint blueprint = gestalt.getBlueprint();
if (blueprint == null) return;
$gestalt = gestalt;
blueprint.setDelegate(this);
blueprint.evaluate();
}
public Object getProperty(String name) {
Object thisObject = $gestalt.getBlueprint().getThisObject();
if (thisObject != null) {
try {
return GroovyRuntimeUtil.getProperty(thisObject, name);
} catch (MissingPropertyException ignored) {}
}
return $gestalt.getProperty(name);
}
public void setProperty(String name, Object value) {
Object thisObject = $gestalt.getBlueprint().getThisObject();
if (thisObject != null) {
try {
GroovyRuntimeUtil.setProperty(thisObject, name, value);
return;
} catch (MissingPropertyException ignored) {}
}
$gestalt.setProperty(name, value);
}
public Object invokeMethod(String name, Object args) {
Object thisObject = $gestalt.getBlueprint().getThisObject();
if (thisObject != null) {
try {
return GroovyRuntimeUtil.invokeMethod(thisObject, name, GroovyRuntimeUtil.asArgumentArray(args));
} catch (MissingMethodException ignored) {}
}
return $gestalt.invokeMethod(name, GroovyRuntimeUtil.asArgumentArray(args));
}
}
spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder/SetterLikeSlot.java 0000664 0000000 0000000 00000003072 12034506303 0033165 0 ustar 00root root 0000000 0000000 /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.spockframework.gentyref.GenericTypeReflector;
import org.spockframework.runtime.GroovyRuntimeUtil;
import org.spockframework.util.MopUtil;
import groovy.lang.MetaMethod;
public class SetterLikeSlot implements ISlot {
private final Object owner;
private final Type ownerType;
private final MetaMethod setterLikeMethod;
public SetterLikeSlot(Object owner, Type ownerType, MetaMethod setterLikeMethod) {
this.owner = owner;
this.ownerType = ownerType;
this.setterLikeMethod = setterLikeMethod;
}
public Type getType() {
Method m = MopUtil.methodFor(setterLikeMethod);
return m != null ? GenericTypeReflector.getExactParameterTypes(m, ownerType)[0] :
setterLikeMethod.getNativeParameterTypes()[0];
}
public void write(Object value) {
setterLikeMethod.doMethodInvoke(owner, GroovyRuntimeUtil.asArgumentArray(value));
}
}
SetterSlotFactory.java 0000664 0000000 0000000 00000002166 12034506303 0033634 0 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.lang.reflect.Type;
import org.spockframework.runtime.GroovyRuntimeUtil;
import org.spockframework.util.MopUtil;
import groovy.lang.MetaProperty;
public class SetterSlotFactory implements ISlotFactory {
public ISlot create(Object owner, Type ownerType, String name) {
MetaProperty property = GroovyRuntimeUtil.getMetaClass(owner).getMetaProperty(name);
return property != null && MopUtil.isWriteable(property) ? new PropertySlot(owner, ownerType, property) : null;
}
}
SpockConfigurationGestalt.java 0000664 0000000 0000000 00000004742 12034506303 0035331 0 ustar 00root root 0000000 0000000 spock-spock-0.7-groovy-2.0/spock-core/src/main/java/org/spockframework/builder /*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spockframework.builder;
import java.util.List;
import groovy.lang.*;
public class SpockConfigurationGestalt implements IGestalt {
private final List