Tom Eyckmans wrote:
Just some info on TestNG integration changes:

I'm rather sure that there are no breaking changes to the current way build scripts are organized in the test block.

We now have an abstraction of a test framework and the Test task only deals with a test framework (except for the backwards compatible getOptions function). The JUnit options and the Ant task that were on test are now managed by the JUnitTestFramework implemenation.

Selecting a test framework:
- useJUnit / useTestNG / useTestFramework(<your own exotic test framework>) (all are available with/without closure that delegates to the options of the test framework)
- add a test.framework.default property to gradle.properties (possible values: junit, testng or <youw own exotic test framework class>) if no default is specified or the property value is empty JUnit is the absolute default. Then you can just do testFramework() {} in your build

TestReport:

This can now be enable/ disable ( as you migth have seen in GRADLE-182) with
test {
    enableTestReport() / disableTestReport() / testReport = false / testReport = true ( whatever you like best )
}

Includes / excludes:
When no includes excludes are specified the following includes/excludes are use:
   include("**/*Tests.class", "**/*Test.class")
   exclude("**/Abstract*.class")

This is used by JUnit and TestNG.

Both jk14/jdk15 style of indicating TestNG tests is supported. I think I've made all ant task options available expect those that gradle uses/depends on for correct operation.

Examples:

TestNG:

test {
    useTestNG() {
         javadocAnnotations() / jdkAnnotations()  // default is determined based on sourceCompatibilty.
         includeGroups 'fast', 'unit'
         excludeGroups 'slow', 'integration'
    }
}

// when peoply use the TestNG suite XML stuff
test {
    useTestNG() {
         suites 'src/test/resources/testng-suite1.xml'
         suites new File(rootDir, 'src/test/resources/testng-suite2.xml')
    }
}

// when people hate XML they can use the Groovy XMLBuilder to script a TestNG suite xml.
test {
    useTestNG() {
        suiteXmlBuilder().suite(name: 'testing-testng') {
            test (name : 'testing-testng', annotations : 'JDK', verbose:'1') {
                classes {
                    'class' (name: 'org.gradle.testng.UserImplTest')
                }
            }
        }
    }
}

JUnit:

test {
    useJUnit() {
        fork(forkMode: ForkMode.ONCE, jvmArgs: ["-ea", "-Dgradle.home=roadToNowhere", '-Xms128m', '-Xmx1g'])
    }
}

test {
    testFramework() { // no default set
        fork(forkMode: org.gradle.api.tasks.testing.ForkMode.ONCE)
    }
    include '**/*Test.class'
    exclude '**/Abstract*'
}

Looking at this code block I'm having some doubts:
- Currently I've left the include/exclude functions on the Test task, but I find it odd to put it outside the testFramework closure, perhaps this needs to move to the options, what do you think?

I think we should end up with framework-dependent and -independent configuration options in the same location. As a user of the test task, I only use 1 framework at a time, so all options are logically the same to me.

Splitting the options based on whether they are common to the currently supported frameworks is also problematic if we later add a third framework which does not support some of these common options.

I wonder if calling useNN() should simply set the associated Options object as a convention object on the task, and nothing more - no nested config. Then the properties and methods of the Options object become properties and methods of the task itself, and you can configure the common and framework-dependent options the same way:

test {
    useTestNg()
    includeGroups 'fast', 'unit'
    excludeGroups 'slow', 'integration'
    include '**/*UnitTest'
}

or

test {
    useJunit()
    fork(jvmArgs: ['-ea'])
    exclude '**/integTest/**'
}

- Also I'm not 100% happy with the naming:
    testFramework() -> runner() // Interface TestFramework -> TestRunner, but just runner in the test block
    useTestFramework(<your testframework impl instance>) -> runner(<your testtunner impl>)
    useTestNG() -> testng() // remove use adds nothing of interest
    useJUnit() -> junit()

Userfriendly

If peoply mixup the options

test {
    useTestNG() {
        fork(forkMode: ForkMode.ONCE, jvmArgs: ["-ea", "-Dgradle.home=roadToNowhere", '-Xms128m', '-Xmx1g'])
    }
}

A user friendly message is shown pointing them in the right direction

Method fork could not be found in the options of the TestNG test framework.

            Make sure the correct TestFramework is in use.
            - Call useJUnit(), useTestNG() or useTestFramework(<your own TestFramework implementation class>) as first statement in the test { } block.
            - Set the test.framework.default property in a gradle.properties file

The only way this doesn't work is when the TestNGOptions.suiteXmlBuilder is used, all missing methods/properties are routed to the suiteXmlBuilder (Groovy XML builder). We could somehow check if it is a valid xml element/ attribute but I haven't added that for the moment (could do this based on the dtd that is available in the testng jars but I haven't added that yet).

Tom
--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email

Reply via email to