From 1290553bff577358e28f555d6b11c118d92d0a99 Mon Sep 17 00:00:00 2001 From: Rob Spieldenner Date: Wed, 1 Mar 2017 15:23:35 -0800 Subject: [PATCH] GradleTestKit Helper --- CHANGELOG.md | 5 + CONTRIBUTING.md | 2 +- README.md | 2 +- build.gradle | 5 +- .../spock/extensions/TempDirectory.groovy | 16 --- .../extensions/TempDirectoryExtension.groovy | 122 ----------------- .../nebula/test/AbstractProjectSpec.groovy | 8 +- .../nebula/test/BaseIntegrationSpec.groovy | 125 ++++++++++++++++++ .../groovy/nebula/test/IntegrationSpec.groovy | 95 +------------ .../nebula/test/IntegrationTestKitSpec.groovy | 75 +++++++++++ .../nebula/test/ChangingTestDirSpec.groovy | 29 ---- .../ConcreteIntegrationTestKitSpec.groovy | 40 ++++++ .../MultiProjectHelperSpec.groovy | 2 +- 13 files changed, 259 insertions(+), 267 deletions(-) delete mode 100644 src/main/groovy/com/energizedwork/spock/extensions/TempDirectory.groovy delete mode 100644 src/main/groovy/com/energizedwork/spock/extensions/TempDirectoryExtension.groovy create mode 100644 src/main/groovy/nebula/test/BaseIntegrationSpec.groovy create mode 100644 src/main/groovy/nebula/test/IntegrationTestKitSpec.groovy delete mode 100644 src/test/groovy/nebula/test/ChangingTestDirSpec.groovy create mode 100644 src/test/groovy/nebula/test/ConcreteIntegrationTestKitSpec.groovy diff --git a/CHANGELOG.md b/CHANGELOG.md index 725a872..811ea80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +5.1.0 / 2017-03-01 +================== + +* Add IntegrationTestKitSpec -- helper for Gradle TestKit + 5.0.1 / 2017-02-14 ================== diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 158ed0a..6cd6a86 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ By contributing your code, you agree to license your contribution under the term ``` /** - * Copyright 2015 the original author or authors. + * Copyright 2017 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 7af9b78..6aabafe 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Gradle Compatibility Tested LICENSE ======= -Copyright 2014-2016 Netflix, Inc. +Copyright 2014-2017 Netflix, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/build.gradle b/build.gradle index ed00e71..8fde9f8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 Netflix, Inc. + * Copyright 2014-2017 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ plugins { - id 'nebula.plugin-plugin' version '5.1.0' + id 'nebula.plugin-plugin' version '5.1.1' id 'org.ysb33r.gradletest' version '0.5.4' } @@ -34,6 +34,7 @@ contacts { } dependencies { + compile gradleTestKit() compile 'com.google.guava:guava:19.0' compile 'commons-io:commons-io:2.5' compile ('org.spockframework:spock-core:1.0-groovy-2.4') { diff --git a/src/main/groovy/com/energizedwork/spock/extensions/TempDirectory.groovy b/src/main/groovy/com/energizedwork/spock/extensions/TempDirectory.groovy deleted file mode 100644 index d73709d..0000000 --- a/src/main/groovy/com/energizedwork/spock/extensions/TempDirectory.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package com.energizedwork.spock.extensions - -import org.spockframework.runtime.extension.ExtensionAnnotation - -import java.lang.annotation.ElementType -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy -import java.lang.annotation.Target - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@ExtensionAnnotation(TempDirectoryExtension) -@interface TempDirectory { - String baseDir() default 'build/test' - boolean clean() default false -} \ No newline at end of file diff --git a/src/main/groovy/com/energizedwork/spock/extensions/TempDirectoryExtension.groovy b/src/main/groovy/com/energizedwork/spock/extensions/TempDirectoryExtension.groovy deleted file mode 100644 index 04cd8bd..0000000 --- a/src/main/groovy/com/energizedwork/spock/extensions/TempDirectoryExtension.groovy +++ /dev/null @@ -1,122 +0,0 @@ -package com.energizedwork.spock.extensions - -import groovy.transform.InheritConstructors -import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension -import org.spockframework.runtime.extension.AbstractMethodInterceptor -import org.spockframework.runtime.extension.IMethodInvocation -import org.spockframework.runtime.model.FieldInfo -import org.spockframework.runtime.model.SpecInfo -import spock.lang.Specification - -class TempDirectoryExtension extends AbstractAnnotationDrivenExtension { - - @Override - void visitFieldAnnotation(TempDirectory annotation, FieldInfo field) { - def interceptor - if (field.isShared()) { - interceptor = new SharedTempDirectoryInterceptor(annotation.baseDir(), annotation.clean(), field.name) - } else { - interceptor = new TempDirectoryInterceptor(annotation.baseDir(), annotation.clean(), field.name) - } - interceptor.install(field.parent.getTopSpec()) - } -} - -abstract class DirectoryManagingInterceptor extends AbstractMethodInterceptor { - - protected final String baseDir - protected final boolean clean - protected final String fieldName - - DirectoryManagingInterceptor(String baseDir, boolean clean, String fieldName) { - this.baseDir = baseDir - this.clean = clean - this.fieldName = fieldName - } - - protected final Specification getSpec( IMethodInvocation invocation ) - { - invocation.instance?:invocation.sharedInstance - } - - protected void setupDirectory(IMethodInvocation invocation) { - final specInstance = getSpec(invocation) - final testName = invocation.feature?invocation.feature.name.replaceAll(/\W+/, '-'):fieldName - final testDirName = "${ specInstance.class.name }/${testName}" - File testDir = new File(baseDir, testDirName).canonicalFile - - if (testDir.isDirectory() ) { - // Creating new directory next to existing one - for (int counter = 1; testDir.directory; counter++) { - testDir = new File(baseDir, testDirName + "_$counter").canonicalFile - } - } - assert testDir.with { (!directory) && mkdirs() }, "Failed to create test directory [$testDir]" - specInstance."$fieldName" = testDir - assert specInstance."$fieldName" == testDir - } - - protected void destroyDirectory(invocation) { - final specInstance = getSpec(invocation) - File directory = specInstance."$fieldName" - - if (clean) { - assert (directory.deleteDir() && !directory.isDirectory()) - } - } - - abstract void install(SpecInfo spec) - -} - -@InheritConstructors -class TempDirectoryInterceptor extends DirectoryManagingInterceptor { - - @Override - void interceptSetupMethod(IMethodInvocation invocation) { - setupDirectory(invocation) - invocation.proceed() - } - - @Override - void interceptCleanupMethod(IMethodInvocation invocation) { - try { - invocation.proceed() - } finally { - destroyDirectory(invocation) - } - } - - @Override - void install(SpecInfo spec) { - spec.setupMethods.each { it.addInterceptor this } - spec.cleanupMethods.each { it.addInterceptor this } - } - -} - -@InheritConstructors -class SharedTempDirectoryInterceptor extends DirectoryManagingInterceptor { - - @Override - void interceptSetupSpecMethod(IMethodInvocation invocation) { - setupDirectory(invocation) - invocation.proceed() - } - - @Override - void interceptCleanupSpecMethod(IMethodInvocation invocation) { - try { - invocation.proceed() - } finally { - destroyDirectory(invocation) - } - } - - @Override - void install(SpecInfo spec) { - spec.setupSpecMethods.each { it.addInterceptor this } - spec.cleanupSpecMethods.each { it.addInterceptor this } - } - -} diff --git a/src/main/groovy/nebula/test/AbstractProjectSpec.groovy b/src/main/groovy/nebula/test/AbstractProjectSpec.groovy index e0dc15d..1da19f8 100644 --- a/src/main/groovy/nebula/test/AbstractProjectSpec.groovy +++ b/src/main/groovy/nebula/test/AbstractProjectSpec.groovy @@ -1,6 +1,5 @@ package nebula.test -import com.energizedwork.spock.extensions.TempDirectory import groovy.transform.CompileStatic import nebula.test.multiproject.MultiProjectHelper import org.gradle.api.Project @@ -21,7 +20,7 @@ import spock.lang.Specification @CompileStatic public abstract class AbstractProjectSpec extends Specification { static final String CLEAN_PROJECT_DIR_SYS_PROP = 'cleanProjectDir' - @TempDirectory File ourProjectDir + File ourProjectDir @Rule TestName testName = new TestName() String canonicalName @@ -29,6 +28,11 @@ public abstract class AbstractProjectSpec extends Specification { MultiProjectHelper helper def setup() { + ourProjectDir = new File("build/nebulatest/${this.class.canonicalName}/${testName.methodName.replaceAll(/\W+/, '-')}") + if (ourProjectDir.exists()) { + ourProjectDir.deleteDir() + } + ourProjectDir.mkdirs() canonicalName = testName.getMethodName().replaceAll(' ', '-') project = ProjectBuilder.builder().withName(canonicalName).withProjectDir(ourProjectDir).build() helper = new MultiProjectHelper(project) diff --git a/src/main/groovy/nebula/test/BaseIntegrationSpec.groovy b/src/main/groovy/nebula/test/BaseIntegrationSpec.groovy new file mode 100644 index 0000000..2ed424e --- /dev/null +++ b/src/main/groovy/nebula/test/BaseIntegrationSpec.groovy @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2017 Netflix, Inc. + * + * 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 nebula.test + +import groovy.transform.CompileStatic +import groovy.transform.TypeCheckingMode +import org.junit.Rule +import org.junit.rules.TestName +import spock.lang.Specification + +abstract class BaseIntegrationSpec extends Specification { + @Rule TestName testName = new TestName() + File projectDir + + def setup() { + projectDir = new File("build/nebulatest/${this.class.canonicalName}/${testName.methodName.replaceAll(/\W+/, '-')}") + if (projectDir.exists()) { + projectDir.deleteDir() + } + projectDir.mkdirs() + } + + /* Setup */ + protected File directory(String path, File baseDir = getProjectDir()) { + new File(baseDir, path).with { + mkdirs() + it + } + } + + 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]) + file.createNewFile() + file + } + + @CompileStatic(TypeCheckingMode.SKIP) + protected File createFile(String path, File baseDir = getProjectDir()) { + File file = file(path, baseDir) + if (!file.exists()) { + assert file.parentFile.mkdirs() || file.parentFile.exists() + file.createNewFile() + } + file + } + + 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}; + + public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello Integration Test"); + } + } + """.stripIndent() + } + + /** + * Creates a unit test for testing your plugin. + * @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 = getProjectDir()) { + writeTest('src/test/java/', 'nebula', failTest, baseDir) + } + + /** + * + * Creates a unit test for testing your plugin. + * @param srcDir the directory in the project where the source file should be created. + * @param packageDotted the package for the unit test class, written in dot notation (ex. - nebula.integration) + * @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 = getProjectDir()) { + def path = srcDir + packageDotted.replace('.', '/') + '/HelloWorldTest.java' + def javaFile = createFile(path, baseDir) + javaFile << """\ + package ${packageDotted}; + import org.junit.Test; + import static org.junit.Assert.assertFalse; + + public class HelloWorldTest { + @Test public void doesSomething() { + assertFalse( $failTest ); + } + } + """.stripIndent() + } + + /** + * Creates a properties file to included as project resource. + * @param srcDir the directory in the project where the source file should be created. + * @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 = getProjectDir()) { + def path = "$srcDir/${fileName}.properties" + def resourceFile = createFile(path, baseDir) + resourceFile.text = "firstProperty=foo.bar" + } + + protected void addResource(String srcDir, String filename, String contents, File baseDir = getProjectDir()) { + def resourceFile = createFile("${srcDir}/${filename}", baseDir) + resourceFile.text = contents + } + } \ No newline at end of file diff --git a/src/main/groovy/nebula/test/IntegrationSpec.groovy b/src/main/groovy/nebula/test/IntegrationSpec.groovy index c21abcc..2037c2f 100644 --- a/src/main/groovy/nebula/test/IntegrationSpec.groovy +++ b/src/main/groovy/nebula/test/IntegrationSpec.groovy @@ -15,7 +15,6 @@ */ package nebula.test -import com.energizedwork.spock.extensions.TempDirectory import com.google.common.base.Predicate import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode @@ -27,19 +26,16 @@ import nebula.test.functional.internal.GradleHandle import nebula.test.multiproject.MultiProjectIntegrationHelper import org.apache.commons.io.FileUtils import org.gradle.api.logging.LogLevel -import spock.lang.Specification /** * @author Justin Ryan * @author Marcin Erdmann */ @CompileStatic -abstract class IntegrationSpec extends Specification { +abstract class IntegrationSpec extends BaseIntegrationSpec { private static final String DEFAULT_REMOTE_DEBUG_JVM_ARGUMENTS = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" private static final Integer DEFAULT_DAEMON_MAX_IDLE_TIME_IN_SECONDS_IN_MEMORY_SAFE_MODE = 15; - @TempDirectory(clean=false) protected File projectDir - // Holds State of last run private ExecutionResult result @@ -61,7 +57,7 @@ abstract class IntegrationSpec extends Specification { protected Integer daemonMaxIdleTimeInSecondsInMemorySafeMode = DEFAULT_DAEMON_MAX_IDLE_TIME_IN_SECONDS_IN_MEMORY_SAFE_MODE private String findModuleName() { - getProjectDir().getName().replaceAll(/_\d+/, '') + getProjectDir().getName().replaceAll(/_\d+/, '') } def setup() { @@ -139,89 +135,6 @@ abstract class IntegrationSpec extends Specification { return logLevel } - /* Setup */ - protected File directory(String path, File baseDir = getProjectDir()) { - new File(baseDir, path).with { - mkdirs() - it - } - } - - 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]) - file.createNewFile() - file - } - - @CompileStatic(TypeCheckingMode.SKIP) - protected File createFile(String path, File baseDir = getProjectDir()) { - File file = file(path, baseDir) - if (!file.exists()) { - assert file.parentFile.mkdirs() || file.parentFile.exists() - file.createNewFile() - } - file - } - - 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}; - - public class HelloWorld { - public static void main(String[] args) { - System.out.println("Hello Integration Test"); - } - } - """.stripIndent() - } - - /** - * Creates a unit test for testing your plugin. - * @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 = getProjectDir()) { - writeTest('src/test/java/', 'nebula', failTest, baseDir) - } - - /** - * - * Creates a unit test for testing your plugin. - * @param srcDir the directory in the project where the source file should be created. - * @param packageDotted the package for the unit test class, written in dot notation (ex. - nebula.integration) - * @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 = getProjectDir()) { - def path = srcDir + packageDotted.replace('.', '/') + '/HelloWorldTest.java' - def javaFile = createFile(path, baseDir) - javaFile << """package ${packageDotted}; - import org.junit.Test; - import static org.junit.Assert.assertFalse; - - public class HelloWorldTest { - @Test public void doesSomething() { - assertFalse( $failTest ); - } - } - """.stripIndent() - } - - /** - * Creates a properties file to included as project resource. - * @param srcDir the directory in the project where the source file should be created. - * @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 = getProjectDir()) { - def path = "$srcDir/${fileName}.properties" - def resourceFile = createFile(path, baseDir) - resourceFile.text = "firstProperty=foo.bar" - } - protected void copyResources(String srcDir, String destination) { ClassLoader classLoader = getClass().getClassLoader(); URL resource = classLoader.getResource(srcDir); @@ -297,10 +210,6 @@ abstract class IntegrationSpec extends Specification { helper.addSubproject(subprojectName, subBuildGradleText) } - File getProjectDir() { - return projectDir - } - File getSettingsFile() { return settingsFile } diff --git a/src/main/groovy/nebula/test/IntegrationTestKitSpec.groovy b/src/main/groovy/nebula/test/IntegrationTestKitSpec.groovy new file mode 100644 index 0000000..65a2d04 --- /dev/null +++ b/src/main/groovy/nebula/test/IntegrationTestKitSpec.groovy @@ -0,0 +1,75 @@ +/* + * Copyright 2016-2017 Netflix, Inc. + * + * 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 nebula.test + +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import org.junit.Rule +import org.junit.rules.TestName + +abstract class IntegrationTestKitSpec extends BaseIntegrationSpec { + boolean keepFiles = false + File buildFile + File settingsFile + + def setup() { + settingsFile = new File(projectDir, "settings.gradle") + buildFile = new File(projectDir, "build.gradle") + + configurePluginClasspath() + } + + def configurePluginClasspath() { + def pluginClasspathResource = this.class.classLoader.findResource("plugin-classpath.txt") + if (pluginClasspathResource == null) { + throw new IllegalStateException("Did not find plugin classpath resource, run `testClasses` build task.") + } + def pluginClasspath = pluginClasspathResource.readLines() + .collect { it.replace("\\", "\\\\") } // escape backslashes in Windows paths + .collect { "'$it'" } + .join(", ") + buildFile << """\ + buildscript { + dependencies { + classpath files($pluginClasspath) + } + } + """.stripIndent() + } + + def cleanup() { + if (!keepFiles) { + projectDir.deleteDir() + } + } + + void addSubproject(String name, String buildGradle) { + def subdir = new File(projectDir, name) + subdir.mkdirs() + + settingsFile << "include \"${name}\"" + + new File(subdir, "build.gradle").text = buildGradle + } + + BuildResult runTasks(String... tasks) { + GradleRunner.create() + .withProjectDir(projectDir) + .withArguments(*tasks.plus("-i")) + .forwardOutput() + .build() + } +} diff --git a/src/test/groovy/nebula/test/ChangingTestDirSpec.groovy b/src/test/groovy/nebula/test/ChangingTestDirSpec.groovy deleted file mode 100644 index 1935a23..0000000 --- a/src/test/groovy/nebula/test/ChangingTestDirSpec.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2017 Netflix, Inc. - * - * 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 nebula.test - -import com.energizedwork.spock.extensions.TempDirectory - -class ChangingTestDirSpec extends IntegrationSpec { - - @TempDirectory(clean = false, baseDir = 'build/test/build1') File projectDir - - def 'can change name of project dir'() { - expect: - projectDir.toURI().toString().contains('build/test/build1') - } - -} diff --git a/src/test/groovy/nebula/test/ConcreteIntegrationTestKitSpec.groovy b/src/test/groovy/nebula/test/ConcreteIntegrationTestKitSpec.groovy new file mode 100644 index 0000000..f180273 --- /dev/null +++ b/src/test/groovy/nebula/test/ConcreteIntegrationTestKitSpec.groovy @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Netflix, Inc. + * + * 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 nebula.test + +import org.gradle.testkit.runner.TaskOutcome + +class ConcreteIntegrationTestKitSpec extends IntegrationTestKitSpec { + @Override + def configurePluginClasspath() { + // intentionally empty to test basics of runner, as this is not a plugin it doesn't have a plugin classpath + } + + def "can run build"() { + given: + buildFile << """\ + apply plugin: "java" + """.stripIndent() + + writeHelloWorld("test.nebula") + + when: + def buildResult = runTasks("assemble") + + then: + buildResult.task(":compileJava").outcome == TaskOutcome.SUCCESS + } +} diff --git a/src/test/groovy/nebula/test/multiproject/MultiProjectHelperSpec.groovy b/src/test/groovy/nebula/test/multiproject/MultiProjectHelperSpec.groovy index 3ad05a6..7832883 100644 --- a/src/test/groovy/nebula/test/multiproject/MultiProjectHelperSpec.groovy +++ b/src/test/groovy/nebula/test/multiproject/MultiProjectHelperSpec.groovy @@ -51,6 +51,6 @@ class MultiProjectHelperSpec extends ProjectSpec { then: sub.parent == project project.subprojects.find { it == sub } != null - sub.projectDir == new File(projectDir, 'sub') + sub.projectDir.toURI().toURL() == new File(projectDir, 'sub').toURI().toURL() } }