Skip to content

Commit

Permalink
Merge 4ca6943 into 77aa841
Browse files Browse the repository at this point in the history
  • Loading branch information
ethankhall committed Sep 9, 2015
2 parents 77aa841 + 4ca6943 commit a51b6c8
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 16 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,29 @@ MultiProjectIntegrationHelper can create sub-projects using our IntegrationSpec.
}
}

Pre Build Hooks
---------------

### PreExecutionAction

PreExecutionActions allows for actions to happen before gradle is executed.

### Usage for PreExecutionAction:

addPreExecute(new PreExecutionAction() {
@Override
void execute(File projectDir, List<String> arguments, List<String> jvmArguments) {
initScript.text = '''
gradle.projectsLoaded {
gradle.rootProject.tasks.create('foo')
}
'''.stripIndent()
}
})

The PreExecutionAction lets you automatically add steps to the test that get executed just before run is called. This is particularly useful when tests change a value that is needed during the execution allowing the action to be defined in a setup, and delayed until the execution.


Caveat
------
* This would have been in nebula-core, but via POMs you can't get dependencies just for tests.
Expand Down
38 changes: 25 additions & 13 deletions src/main/groovy/nebula/test/IntegrationSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import groovy.transform.TypeCheckingMode
import nebula.test.functional.ExecutionResult
import nebula.test.functional.GradleRunner
import nebula.test.functional.GradleRunnerFactory
import nebula.test.functional.PreExecutionAction
import nebula.test.functional.internal.GradleHandle
import nebula.test.multiproject.MultiProjectIntegrationHelper
import org.apache.commons.io.FileUtils
Expand Down Expand Up @@ -52,35 +53,37 @@ abstract class IntegrationSpec extends Specification {
protected List<String> jvmArguments = []
protected MultiProjectIntegrationHelper helper
protected Predicate<URL> classpathFilter
protected List<File> initScripts = []
protected List<PreExecutionAction> preExecutionActions = []

private String findModuleName() {
projectDir.getName().replaceAll(/_\d+/, '')
getProjectDir().getName().replaceAll(/_\d+/, '')
}

def setup() {
moduleName = findModuleName()
if (!settingsFile) {
settingsFile = new File(projectDir, 'settings.gradle')
settingsFile = new File(getProjectDir(), 'settings.gradle')
settingsFile.text = "rootProject.name='${moduleName}'\n"
}

if (!buildFile) {
buildFile = new File(projectDir, 'build.gradle')
buildFile = new File(getProjectDir(), 'build.gradle')
}

println "Running test from ${projectDir}"
println "Running test from ${getProjectDir()}"

buildFile << "// Running test for ${moduleName}\n"

helper = new MultiProjectIntegrationHelper(projectDir, settingsFile)
helper = new MultiProjectIntegrationHelper(getProjectDir(), settingsFile)
}

protected GradleHandle launcher(String... args) {
List<String> arguments = calculateArguments(args)
List<String> jvmArguments = calculateJvmArguments()

GradleRunner runner = GradleRunnerFactory.createTooling(fork, gradleVersion, classpathFilter)
runner.handle(projectDir, arguments, jvmArguments)
runner.handle(getProjectDir(), arguments, jvmArguments, preExecutionActions)
}

private List<String> calculateArguments(String... args) {
Expand All @@ -103,13 +106,22 @@ abstract class IntegrationSpec extends Specification {
}
arguments += '--stacktrace'
arguments.addAll(args)
arguments.addAll(initScripts.collect { file -> '-I' + file.absolutePath })
arguments
}

private List<String> calculateJvmArguments() {
return jvmArguments + (remoteDebug ? [DEFAULT_REMOTE_DEBUG_JVM_ARGUMENTS] : [] as List) as List
}

protected void addInitScript(File initFile) {
initScripts.add(initFile)
}

protected void addPreExecute(PreExecutionAction preExecutionAction) {
preExecutionActions.add(preExecutionAction)
}

/**
* Override to alter its value
* @return
Expand All @@ -119,14 +131,14 @@ abstract class IntegrationSpec extends Specification {
}

/* Setup */
protected File directory(String path, File baseDir = projectDir) {
protected File directory(String path, File baseDir = getProjectDir()) {
new File(baseDir, path).with {
mkdirs()
it
}
}

protected File file(String path, File baseDir = projectDir) {
protected File file(String path, File baseDir = getProjectDir()) {
def splitted = path.split('/')
def directory = splitted.size() > 1 ? directory(splitted[0..-2].join('/'), baseDir) : baseDir
def file = new File(directory, splitted[-1])
Expand All @@ -135,7 +147,7 @@ abstract class IntegrationSpec extends Specification {
}

@CompileStatic(TypeCheckingMode.SKIP)
protected File createFile(String path, File baseDir = projectDir) {
protected File createFile(String path, File baseDir = getProjectDir()) {
File file = file(path, baseDir)
if (!file.exists()) {
assert file.parentFile.mkdirs() || file.parentFile.exists()
Expand All @@ -144,7 +156,7 @@ abstract class IntegrationSpec extends Specification {
file
}

protected void writeHelloWorld(String packageDotted, File baseDir = projectDir) {
protected void writeHelloWorld(String packageDotted, File baseDir = getProjectDir()) {
def path = 'src/main/java/' + packageDotted.replace('.', '/') + '/HelloWorld.java'
def javaFile = createFile(path, baseDir)
javaFile << """package ${packageDotted};
Expand All @@ -162,7 +174,7 @@ abstract class IntegrationSpec extends Specification {
* @param failTest true if you want the test to fail, false if the test should pass
* @param baseDir the directory to begin creation from, defaults to projectDir
*/
protected void writeUnitTest(boolean failTest, File baseDir = projectDir) {
protected void writeUnitTest(boolean failTest, File baseDir = getProjectDir()) {
writeTest('src/test/java/', 'nebula', failTest, baseDir)
}

Expand All @@ -174,7 +186,7 @@ abstract class IntegrationSpec extends Specification {
* @param failTest true if you want the test to fail, false if the test should pass
* @param baseDir the directory to begin creation from, defaults to projectDir
*/
protected void writeTest(String srcDir, String packageDotted, boolean failTest, File baseDir = projectDir) {
protected void writeTest(String srcDir, String packageDotted, boolean failTest, File baseDir = getProjectDir()) {
def path = srcDir + packageDotted.replace('.', '/') + '/HelloWorldTest.java'
def javaFile = createFile(path, baseDir)
javaFile << """package ${packageDotted};
Expand All @@ -195,7 +207,7 @@ abstract class IntegrationSpec extends Specification {
* @param fileName to be used for the file, sans extension. The .properties extension will be added to the name.
* @param baseDir the directory to begin creation from, defaults to projectDir
*/
protected void writeResource(String srcDir, String fileName, File baseDir = projectDir) {
protected void writeResource(String srcDir, String fileName, File baseDir = getProjectDir()) {
def path = "$srcDir/${fileName}.properties"
def resourceFile = createFile(path, baseDir)
resourceFile.text = "firstProperty=foo.bar"
Expand Down
4 changes: 4 additions & 0 deletions src/main/groovy/nebula/test/functional/GradleRunner.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public interface GradleRunner {

ExecutionResult run(File directory, List<String> args, List<String> jvmArgs)

ExecutionResult run(File directory, List<String> args, List<String> jvmArgs, List<PreExecutionAction> preExecutionActions)

/**
* Handle on instance of Gradle that can be run.
* @param directory
Expand All @@ -74,4 +76,6 @@ public interface GradleRunner {
GradleHandle handle(File directory, List<String> args)

GradleHandle handle(File directory, List<String> args, List<String> jvmArgs)

GradleHandle handle(File directory, List<String> args, List<String> jvmArgs, List<PreExecutionAction> preExecutionActions)
}
12 changes: 12 additions & 0 deletions src/main/groovy/nebula/test/functional/PreExecutionAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nebula.test.functional;

import java.io.File;
import java.util.List;


/**
* Executes actions before gradle is called.
*/
public interface PreExecutionAction {
void execute(File projectDir, List<String> arguments, List<String> jvmArguments);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package nebula.test.functional.internal
import groovy.transform.CompileStatic
import nebula.test.functional.ExecutionResult
import nebula.test.functional.GradleRunner
import nebula.test.functional.PreExecutionAction

@CompileStatic
class DefaultGradleRunner implements GradleRunner {
Expand All @@ -29,12 +30,13 @@ class DefaultGradleRunner implements GradleRunner {
}

@Override
public ExecutionResult run(File projectDir, List<String> arguments, List<String> jvmArguments = []) {
return handle(projectDir, arguments, jvmArguments).run();
public ExecutionResult run(File projectDir, List<String> arguments, List<String> jvmArguments = [], List<PreExecutionAction> preExecutionActions = []) {
return handle(projectDir, arguments, jvmArguments, preExecutionActions).run();
}

@Override
public GradleHandle handle(File projectDir, List<String> arguments, List<String> jvmArguments = []) {
public GradleHandle handle(File projectDir, List<String> arguments, List<String> jvmArguments = [], List<PreExecutionAction> preExecutionActions = []) {
preExecutionActions?.each { it.execute(projectDir, arguments, jvmArguments) }
return handleFactory.start(projectDir, arguments, jvmArguments);
}
}
15 changes: 15 additions & 0 deletions src/test/groovy/nebula/test/ChangingTestDirSpec.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package nebula.test


import com.energizedwork.spock.extensions.TempDirectory

class ChangingTestDirSpec extends IntegrationSpec {

@TempDirectory(clean = false, baseDir = 'test/build1') File projectDir

def 'can change name of project dir'() {
expect:
projectDir.absolutePath.contains('test/build1')
}

}
45 changes: 45 additions & 0 deletions src/test/groovy/nebula/test/ConcreteIntegrationSpec.groovy
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nebula.test

import nebula.test.functional.ExecutionResult
import nebula.test.functional.PreExecutionAction
import spock.lang.Unroll

class ConcreteIntegrationSpec extends IntegrationSpec {
Expand Down Expand Up @@ -58,4 +59,48 @@ class ConcreteIntegrationSpec extends IntegrationSpec {
"Tooling" | true
"Launcher" | false
}

def 'init scripts will be appended to arguments provided to gradle'() {
setup:
def initScript = file('foo.gradle')
initScript.text = '''
gradle.projectsLoaded {
gradle.rootProject.tasks.create('foo')
}
'''.stripIndent()
when:
def failure = runTasksWithFailure('foo')

then:
failure.failure != null

when:
addInitScript(initScript)
failure = runTasksSuccessfully('foo')
failure.failure == null

then:
noExceptionThrown()
}

def 'pre execution tasks will run before gradle'() {
def initScript = file('foo.gradle')

when:
addPreExecute(new PreExecutionAction() {
@Override
void execute(File projectDir, List<String> arguments, List<String> jvmArguments) {
initScript.text = '''
gradle.projectsLoaded {
gradle.rootProject.tasks.create('foo')
}
'''.stripIndent()
}
})
addInitScript(initScript)
runTasksSuccessfully('foo')

then:
noExceptionThrown()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package nebula.test.functional.internal


import nebula.test.functional.PreExecutionAction
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import spock.lang.Specification

class DefaultGradleRunnerSpec extends Specification {

@Rule TemporaryFolder temporaryFolder

def 'will execute actions before run is called'() {
setup:
def projectDir = temporaryFolder.newFolder()
def handleFactory = Mock(GradleHandleFactory)
def runner = new DefaultGradleRunner(handleFactory)

when:
runner.handle(projectDir, ['arg'], ['jvm'], [new WriteFileAction(projectDir)])

then:
1 * handleFactory.start(projectDir, ['arg'], ['jvm'])
}

static class WriteFileAction implements PreExecutionAction {
File expectedDir

WriteFileAction(File expectedDir) {
this.expectedDir = expectedDir
}

@Override
void execute(File projectDir, List<String> arguments, List<String> jvmArguments) {
assert expectedDir.absolutePath == projectDir.absolutePath

assert arguments.size() == 1
assert arguments.first() == 'arg'

assert jvmArguments.size() == 1
assert jvmArguments.first() == 'jvm'
}
}
}

0 comments on commit a51b6c8

Please sign in to comment.