Spock Extensions
From Evgeny Goldin
Contents |
Details
| Provided By | ||
|---|---|---|
| Source Code | GitHub | |
| GroovyDoc | <groovydoc>
| |
| Issue Tracker | YouTrack | |
| Build Server | Gradle TeamCity | |
| Coordinates |
Maven: <dependency> <groupId>com.github.goldin</groupId> <artifactId>spock-extensions</artifactId> <version>0.1.4</version> </dependency> Gradle: testCompile 'com.github.goldin:spock-extensions:0.1.4' | |
| Maven Repository | Artifactory Online |
ProfilerExtension
This global extensions provides a basic profiling of your tests by generating the following report of test name and its execution time, sorted in decreasing order:
DatabaseDriven.maximum of two numbers : 28 ms HamcrestMatchers.comparing two decimal numbers : 21 ms OrderedInteractions.collaborators must be invoked in order : 15 ms PublisherSpec.can cope with misbehaving subscribers : 12 ms PublisherSpec.delivers events to all subscribers : 10 ms EmptyStack.push : 5 ms ...
To activate it add the following file to "src/test/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension":
com.github.goldin.spock.extensions.profiler.ProfilerExtension
When your tests have finished running you'll find a "profiler.txt" file in project's root directory. To display it with Gradle use
test.afterSuite { final file = new File( 'profiler.txt' ) if (( ! it.parent ) && ( file.file )){ println( file.text )} }
@With
@With extension can be applied per-Specification (globally) or per-feature (locally). It behaves as if it wraps the entire spec
or certain feature with a with{ .. } block using objects specified as delegates. As is the case with with
it saves on referencing the same object over and over or creating temporal variables "just to hold this result for a second".
It accepts a Closure expression returning either a single object or List of objects:
@With({ true }) @With({ 'string' }) @With({ 'http://gradle.org/'.toURL() }) @With({ [ 'string', [ 1 : 3 ], [ true ] ] }) @With({ [ 'http://gradle.org/'.toURL(), 'http://groovy.codehaus.org/' ] })
All non-null objects returned by the Closure become with{ .. }-like delegates for execution of all Specification features
(if @With is applied globally) or execution of a certain feature (if applied locally). If extension is applied both globally
and locally then two sets of objects are combined, giving priority to those specified locally for the test method.
Internally, @With is not implemented using with{ .. } but MOP's methodMissing and propertyMissing
which means it works equally well for methods and properties.
Test Specifications
Examples (taken from those two files)
@With({ [ 'string', [ 1 : 2 ], [ true ] ] }) def 'regular test method' () { expect: bytes // 'string'.bytes chars // 'string'.chars size() == 6 // 'string'.size() containsKey( 1 ) // [ 1 : 2 ].containsKey( 1 ) first() // [ true ].first() } @With({ 'http://gradle.org/'.toURL() }) def 'URL test method' () { when: // 'http://gradle.org/'.toURL().text new File( testDir, 'data.txt' ).write( text ) then: new File( testDir, 'data.txt' ).text.size() > ( 9 * 1024 ) } @With({ GCommons.file() }) class FileBeanSpec extends Specification { def 'check relative path'( String dir, String file, String path ) { expect: // GCommons.file().relativePath() relativePath( new File( dir ), new File( file )) == path where: dir | file | path 'C:/111/' | 'C:/111/222/sss/3.txt' | '/222/sss/3.txt' 'C:/' | 'C:/111/222/oiu/3.txt' | ( windows ? '' : '/' ) + '111/222/oiu/3.txt' 'C:/' | 'C:/111/222/oiu/3.txt' | ( windows ? '' : '/' ) + '111/222/oiu/3.txt' 'C:/1/2/' | 'C:/1/2/' | '/' } } class GeneralBeanSpec extends Specification { @With({ GCommons.general() }) def 'check match()'() { expect: // GCommons.general().match() match( '/a/b/c/d', '**' ) match( '/a/b/c/d/1.txt', '''*/''.*' ) ! match( '/a/b/c/d', '''*/''.*' ) ! match( '/a/b/c/d/1.txt', '''*/''.xml' ) } }
@Time
@Time extension can be applied per-Specification (globally) or per-feature (locally). It allows to time-limit execution of the whole spec or specific test method with two attributes:
-
min(int) -0by default, minimal execution time in milliseconds, should be zero or more. -
max(int) -Integer.MAX_VALUEby default, maximal execution time in milliseconds, should be more thanmin.
Note, that both attributes are int (covering 24-days execution) and not long although they deal with milliseconds. This is to avoid warnings around 0L constants and avoid appending L to numbers as well.
Default values allow to display an execution time without applying any limits:
Test Specifications
Example (taken from this file)
@Time( min = 500, max = 2000 ) class GeneralBeanSpec extends Specification { @Time( min = 500, max = 2000 ) def 'gc-87: GeneralBean.executeWithResult()'() { ... } @Time( min = 0, max = 100 ) def 'check match()'() { ... } }
@TestDir
@TestDir extension can only be applied to Specification instance field. It creates empty test directory for each Spock feature (test method) and assigns
its value to the field, assuming it is of File type.
It has two attributes
-
baseDir(String) -"build/test"by default.
Directory where all test directories are created. -
clean(boolean) -trueby default.
If test directory already exists whether it should be cleaned up (truevalue) or another one should be created next to it (falsevalue).
For each feature test directory created at "<baseDir>/<spec FQCN>/<feature name>" where all non-alphabetic characters in feature name are replaced by "-".
For example for feature 'Check pack() and unpack() operations' in FileBeanSpec it will be build/test/com.github.goldin.gcommons.specs.FileBeanSpec/Check-pack-and-unpack-operations.
Test Specifications
Example (taken from this file)
class FileBeanSpec extends Specification { @TestDir File testDir def 'Check pack() and unpack() operations' () { // build/test/com.github.goldin.gcommons.specs.FileBeanSpec/Check-pack-and-unpack-operations/ assert testDir.directory && ( ! testDir.listFiles()) given: def zipUnpack1 = new File( testDir, 'zip-1' ) def zipUnpack2 = new File( testDir, 'zip-2' ) } def 'Check "fullpath" and "prefix" pack() options'() { // build/test/com.github.goldin.gcommons.specs.FileBeanSpec/Check-fullpath-and-prefix-pack-options/ assert testDir.directory && ( ! testDir.listFiles()) given: def zipFile = testResource( "${testArchive.key}.zip" ) def zipUnpack = new File( testDir, 'zip' ) def extFile1 = new File( testDir, "${testArchive.key}-1.$extension" ) def extFile2 = new File( testDir, "${testArchive.key}-2.$extension" ) } }
@TempDir
Originally forked from http://github.com/robfletcher/spock-extensions.
Used on a File property of a spec class this annotation will cause
a temporary directory to be created and injected before each feature
method is run and destroyed afterwards. If the field is @Shared the
directory is only destroyed after all feature methods have run. You
can have as many such fields as you like in a single spec, each will
be generated with a unique name.
Temporary directories are created inside java.io.tmpdir.
This is useful when testing a class that reads from or writes to a location on disk.
Test Specifications
Example
class MySpec extends Specification { @TempDir File myTempDir def diskStore = new DiskStore() def "disk store writes bytes to a file"() { given: diskStore.baseDir = myTempDir diskStore.targetFilename = "foo" when: diskStore << "some text" then: new File(myTempDir, "foo").text == "some text" } }

