Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting main and test in gradle's eclipse builds

Today I tried to switch an project with integration tests from maven to gradle. All worked fine except I have a serious problem with testng.

The project uses hibernate/JPA2 for database access and has a couple of tests that depend on a persistence unit in the test/resources/META-INF/persistence.xml. When I run the test suite using gradle all works fine. But when I run the xml (or any test class by itself) from eclipse it seems that it tries to use the main/resources/META-INF/persistence.xml.

Because I do most of my work using TDD, I realy need to run/debug tests from eclipse. When I add the persistence unit to the production persistence.xml it works (it even gets some other resources from the "test" dir). It would be a workaround, but I realy don't like the idea of adding test resources to "main/resources"

Same project works fine when I import it using the old pom.xml from maven.

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.7
version = '0.1'
jar {
    manifest {
        attributes 'Implementation-Title': 'md', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.5'
    compile 'com.google.guava:guava:14.0.1'
    compile 'org.hibernate:hibernate-entitymanager:4.2.2.Final'
    compile 'org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final'

    testCompile 'ch.qos.logback:logback-classic:1.0.13'
    testCompile 'org.testng:testng:6.8.5'
    testCompile 'org.dbunit:dbunit:2.4.9'
    testCompile 'org.mockito:mockito-all:1.9.5'
    testCompile 'org.easytesting:fest-assert-core:2.0M10'
    testCompile 'org.hsqldb:hsqldb:2.2.9'

}

test {
    useTestNG(){    
        suites 'src/test/resources/testng.xml' 
    } 
}

Update:

Generated classpath file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src/main/java"/>
    <classpathentry kind="src" path="src/main/resources"/>
    <classpathentry kind="src" path="src/test/java"/>
    <classpathentry kind="src" path="src/test/resources"/>
    <classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry exported="true" kind="con" path="org.springsource.ide.eclipse.gradle.classpathcontainer"/>
    <classpathentry kind="output" path="bin"/>
</classpath>

It seems it merges all into the bin folder and doesn't differentiate between main and test like the .classpath file generated by maven.

like image 317
ssindelar Avatar asked Jul 03 '13 15:07

ssindelar


People also ask

How do I skip a test in Gradle build?

To skip any task from the Gradle build, we can use the -x or –exclude-task option. In this case, we'll use “-x test” to skip tests from the build. As a result, the test sources aren't compiled, and therefore, aren't executed.

How much time Gradle build takes?

In your build. gradle, if you have minifyEnabled for debug, remove it. I had it in my project and it took ~2-3 minutes to build.


2 Answers

Problem was that gradle's eclipse plugin merges the test and main folder by default. Therefore the persistence.xml from main did override the test version.

Adding the following code will resolve the problem by changing the output directories of the generated classpathentries and removing the entry with the default output.

import org.gradle.plugins.ide.eclipse.model.SourceFolder 
eclipse.classpath.file {
    beforeMerged { classpath -> 
        classpath.entries.clear()
    }
    whenMerged {  cp -> 
        cp.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/main/") }*.output = "bin/main" 
        cp.entries.findAll { it instanceof SourceFolder && it.path.startsWith("src/test/") }*.output = "bin/test" 
        cp.entries.removeAll { it.kind == "output" }
    }
}

Update: Relevant classpath entries after the change.

<classpathentry output="bin/main" kind="src" path="src/main/java"/>
<classpathentry output="bin/main" kind="src" path="src/main/resources"/>
<classpathentry output="bin/test" kind="src" path="src/test/java"/>
<classpathentry output="bin/test" kind="src" path="src/test/resources"/>
like image 109
ssindelar Avatar answered Sep 20 '22 20:09

ssindelar


Setting default output folder to 'build' and test output folder to 'build-test' (tested with Gradle 2.7):

eclipse.classpath {
    defaultOutputDir = file('build')
    file.withXml { n ->
        n.asNode().classpathentry.findAll { [email protected]('src/test') }
                .each { it.@output = 'build-test' }
    }
}

Resulting .classpath file entries:

<classpathentry kind="output" path="build"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/test/java" output="build-test"/>
<classpathentry kind="src" path="src/test/resources" output="build-test"/>
like image 22
Ogmios Avatar answered Sep 20 '22 20:09

Ogmios