1. Fixt
Fixt helps organize fixtures for your fixtures in a directories with the same name as your test class.
Given a test residing in src/test/java
or src/test/groovy
with name org.example.MyTest
then
the fixtures' location will src/test/resources/org/example/MyTest
keeping all the files for given test in a single folder.
If you generate the fixture files from your tests it is always better to specify the path to the test resources folder
using test.resources.folder
system property or TEST_RESOURCES_FOLDER
environment variable.
In Gradle, you can easily achive this by using following snippet:
test {
environment 'TEST_RESOURCES_FOLDER', new File(project.projectDir, 'src/test/resources').canonicalPath
}
Fixt guarantee that the directories are created before the test run so adding new fixture files will be easier.
1.1. Installation
repositories {
jcenter()
}
dependencies {
testCompile 'com.agorapulse.testing:fixt:0.2.3'
}
<dependency>
<groupId>com.agorapulse.testing</groupId>
<artifactId>fixt</artifactId>
<version>0.2.3</version>
<scope>test</scope>
</dependency>
1.2. Usage
package com.agorapulse.testing.fixt
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import spock.lang.Specification
import spock.util.environment.RestoreSystemProperties
@RestoreSystemProperties
class FixtSpec extends Specification {
public static final String TEXT_FILE = 'text.txt'
public static final String TEXT_CONTENT = 'Hello Text\n'
public static final String STREAM_FILE = 'stream.txt'
public static final String STREAM_CONTENT = 'Hello Stream\n'
public static final String EMPTY_FILE = 'empty.txt'
public static final String EMPTY_CONTENT = ''
@Rule
TemporaryFolder tmp = new TemporaryFolder()
Fixt fixt = Fixt.create(this) (1)
void 'reading existing files'() {
expect:
fixt.readStream(STREAM_FILE).text == STREAM_CONTENT (2)
fixt.readText(TEXT_FILE) == TEXT_CONTENT (3)
fixt.readText(EMPTY_FILE) == EMPTY_CONTENT
}
void 'writing files'() {
when:
Fixt fixt = Fixt.create(ReferenceClass) (4)
File testResources = tmp.newFolder()
System.setProperty('test.resources.folder', testResources.canonicalPath)
fixt.mkdirs() (5)
then:
Fixt.testResourcesLocation == testResources.canonicalPath
when:
ByteArrayInputStream stream = new ByteArrayInputStream(STREAM_CONTENT.bytes)
fixt.writeStream(STREAM_FILE, stream) (6)
fixt.writeText(TEXT_FILE, TEXT_CONTENT) (7)
File contextTestFolder = new File(testResources, 'com/agorapulse/testing/fixt/ReferenceClass')
then:
contextTestFolder.exists()
new File(contextTestFolder, STREAM_FILE).text == STREAM_CONTENT
new File(contextTestFolder, TEXT_FILE).text == TEXT_CONTENT
}
void 'copy directory'() {
given:
Fixt fixt = Fixt.create(this)
File destinationDir = tmp.newFolder()
when:
fixt.copyTo('testdir', destinationDir) (8)
then:
new File(destinationDir, 'root.txt').exists() (9)
new File(destinationDir, 'firstLevel/firstLevel.txt').exists()
new File(destinationDir, 'firstLevel/secondLevel/secondLevel.txt').exists()
}
}
1 | Declare Fixt for the specification |
2 | Read the content of the file as stream |
3 | Read the content of the file as text |
4 | Create Fixt for the specific class (ReferenceClass ) |
5 | Create all necessary directories if they do not exist yet |
6 | Write the content of the stream into a file |
7 | Write the text into a file |
8 | Copy whole directory from the test resources |
9 | All thehe files from the fixture directory are available in the new destination |
2. Grails Job Testing Support
Grails Job Testing Support brings the same trait-based tesing support to jobs created by the Quartz plugin as the original
https://testing.grails.org/]Grails Testing Support]. It provides JobUnitTest<J>
trait which your specification can implement
in order to test the job more easily.
2.1. Installation
repositories {
jcenter()
}
dependencies {
testCompile 'com.agorapulse.testing:grails-job-testing-support:0.2.3'
}
2.2. Usage
package com.agorapulse.testing.grails.job.test
import groovy.transform.CompileDynamic
@CompileDynamic
@SuppressWarnings([
'FieldTypeRequired',
'NoDef',
])
class TestJob {
static triggers = {
simple name: 'mySimpleTrigger', startDelay: 60000, repeatInterval: 1000
}
static sessionRequired = true
static concurrent = true
static group = 'MyGroup'
static description = 'Example job with Simple Trigger'
Runnable runnable
void execute() {
runnable.run()
}
}
package com.agorapulse.testing.grails.job.test
import com.agorapulse.testing.grails.job.JobUnitTest
import org.quartz.SimpleTrigger
import spock.lang.Specification
@SuppressWarnings('ClassStartsWithBlankLine')
class TestJobSpec extends Specification implements JobUnitTest<TestJob> { (1)
Runnable mock = Mock(Runnable)
void setup() {
job.runnable = mock (2)
}
void 'test trigger job'() {
when:
trigger job (3)
then:
noExceptionThrown()
1 * mock.run()
}
void 'check cofiguration'() {
expect:
triggers.any { (4)
it instanceof SimpleTrigger && it.repeatInterval == 1000
}
jobClass.concurrent (5)
jobClass.sessionRequired
jobClass.description == 'Example job with Simple Trigger'
jobClass.group == 'MyGroup'
}
}
1 | Implement JobUnitTest with the particular job under test |
2 | You can inject any mocks into the job instance |
3 | Trigger the job |
4 | Access the list of configured triggers |
5 | Access the job metadata |
3. Office Unit
Office Unit is trivial tool for matching Microsoft Office documents. It leverage their nature of being archive files with XML content. It compares the content of the files using XmlUnit but it by default ignores date created and last updated timestamps. The typical usecase is to compare the reference file against the newly generated to keep the status quo of the exports.
For Excel documents, you should consider using SpreadsheetQuery instead.
3.1. Installation
repositories {
jcenter()
}
dependencies {
testCompile 'com.agorapulse.testing:office-unit:0.2.3'
}
<dependency>
<groupId>com.agorapulse.testing</groupId>
<artifactId>office-unit</artifactId>
<version>0.2.3</version>
<scope>test</scope>
</dependency>
3.2. Usage
void 'no differences: #control with #test'() {
expect:
new OfficeUnit().compare( (1)
loadFile(control),
loadFile(test)
).empty
where:
control | test
'test1.pptx' | 'test2.pptx'
'test1.xlsx' | 'test2.xlsx'
}
void '#differencesCount difference(s): #control with #test'() {
given:
OfficeUnit officeUnit = new OfficeUnit()
expect:
officeUnit.compare( (2)
loadFile(control),
loadFile(test)
).size() == differencesCount
where:
control | test | differencesCount
'test1.xlsx' | 'test3.xlsx' | 1
'test1.xlsx' | 'test4.xlsx' | 8
'test1.xlsx' | 'test5.xlsx' | 159
'test1.pptx' | 'test3.pptx' | 2469
}
void 'ignore some other part'() {
given:
OfficeUnit officeUnit = new OfficeUnit()
.ignore('/sst[1]/si[3]/t[1]/text()[1]') (3)
expect:
officeUnit.compare(
loadFile('test1.xlsx'),
loadFile('test3.xlsx')
).empty
}
1 | Compare two Microsoft Office files and expect no difference |
2 | Expect some differences |
3 | Ignore some differences by XPath expression |
4. Spock
Set of useful Spock Framework extensions.
-
@Detached
will automatically attach mock created byDetachedMockFactory
-
@OverrideParentFeatures
will override any parent features of the same name
4.1. Installation
repositories {
jcenter()
}
dependencies {
testCompile 'com.agorapulse.testing:spock:0.2.3'
}
<dependency>
<groupId>com.agorapulse.testing</groupId>
<artifactId>spock</artifactId>
<version>0.2.3</version>
<scope>test</scope>
</dependency>
4.2. Usage
package com.agorapulse.testing.spock
import spock.lang.Specification
class DetachedSpec extends Specification {
@Detached Runnable runnable = MyMockFactory.mockRunnable() (1)
void 'mock is attached'() {
when:
runnable.run()
then:
1 * runnable.run()
}
}
1 | You can attach mock which has been created out of the scope of current specification |
package com.agorapulse.testing.spock
import spock.lang.Specification
class ParentSpec extends Specification {
void 'ignore me in child'() { (1)
expect:
this.getClass() == ParentSpec || this.getClass() == GrandChildSpec
}
void 'ignore me in grandchild'() {
expect:
this.getClass() == ParentSpec || this.getClass() == ChildSpec
}
}
1 | Feature methods declared in parent specification cannot be normally overriden |
package com.agorapulse.testing.spock
class ChildSpec extends ParentSpec {
@OverrideParentFeatures (1)
void 'ignore me in child'() {
expect:
this.getClass() == ChildSpec || this.getClass() == GrandChildSpec
}
}
1 | Using OverrideParentFeatures any method with the same name in any parent is skipped |