This is an automated email from the ASF dual-hosted git repository. benweidig pushed a commit to branch javax in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
commit 96cf167a50994377cf2b905080f854fae7148687 Author: Ben Weidig <[email protected]> AuthorDate: Sun Apr 19 11:59:23 2026 +0200 TAP5-2809: run TestNG unit tests via Jupiter, integration tests native, more cleanup As using both JUnit and TestNG in the same project can be troublesome, we now created a deliberate split at integration testing level. Unit tests are run via the Jupiter testng-runner, whereas integration tests are still run with "native" TestNG, as SeleniumTestCase uses TestNG-only feature for its lifecycles. Furthermore, the Gradle files have been cleaned up and added some documentation to improve maintainability. --- .../tapestry.junit4-legacy-convention.gradle | 16 ++- .../main/groovy/tapestry.junit5-convention.gradle | 14 +- .../groovy/tapestry.junit5-spock-convention.gradle | 4 + .../groovy/tapestry.testing-base-convention.gradle | 39 +++-- .../main/groovy/tapestry.testng-convention.gradle | 35 +++-- gradle/libs.versions.toml | 9 +- tapestry-beanvalidator/build.gradle | 17 ++- tapestry-core/build.gradle | 158 ++++++++++++--------- tapestry-core/src/test/resources/testng.xml | 44 ------ tapestry-hibernate-core/build.gradle | 2 +- tapestry-hibernate/build.gradle | 17 ++- tapestry-hibernate/src/test/resources/testng.xml | 5 - tapestry-http/build.gradle | 17 ++- tapestry-http/src/test/resources/testng.xml | 11 ++ tapestry-ioc/build.gradle | 2 +- tapestry-jmx/build.gradle | 15 ++ tapestry-jpa/build.gradle | 15 ++ .../jpa/JpaTransactionAdvisorImplTest.java | 27 ++-- .../org/apache/tapestry5/jpa/test/JpaTest.java | 17 ++- tapestry-kaptcha/build.gradle | 15 ++ .../kaptcha/components/KaptchaUnitTest.java | 3 +- tapestry-spring/build.gradle | 17 ++- tapestry-spring/src/test/resources/testng.xml | 6 - tapestry-test/build.gradle | 15 ++ tapestry-upload/build.gradle | 15 ++ tapestry-upload/src/test/resources/testng.xml | 2 - tapestry-webresources/build.gradle | 18 ++- .../services/web/WebResourcesTest.java | 5 + 28 files changed, 363 insertions(+), 197 deletions(-) diff --git a/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle index 54b2d6577..fc7e39272 100644 --- a/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle +++ b/buildSrc/src/main/groovy/tapestry.junit4-legacy-convention.gradle @@ -1,11 +1,15 @@ +// Use ONLY for existing modules still using JUnit 4 test sources (@RunWith, @Rule, etc.). +// +// Adds the JUnit Vintage engine so those tests run on the JUnit Platform alongside +// any Jupiter tests in the same module. +// No test source changes required. +// +// Prefer migrating tests to JUnit 5 over adding this convention to new modules. + plugins { - id 'tapestry.testing-base-convention' + id 'tapestry.junit5-convention' } dependencies { - testImplementation libs.junit4 -} - -tasks.withType(Test).configureEach { - useJUnit() + testRuntimeOnly libs.junit.vintage.engine } diff --git a/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle index 59c163eb6..ee2ecdaea 100644 --- a/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle +++ b/buildSrc/src/main/groovy/tapestry.junit5-convention.gradle @@ -1,14 +1,16 @@ +// Use for modules whose test sources use JUnit 5 (Jupiter) annotations (@Test, @ExtendWith, …). +// +// Convention hierarchy: +// tapestry.testing-base-convention platform runner, BOM, logging +// └─ tapestry.junit5-convention + Jupiter API + engine (this file) +// ├─ tapestry.junit5-spock-convention + Spock +// └─ tapestry.junit4-legacy-convention + Vintage engine for JUnit 4 + plugins { id 'tapestry.testing-base-convention' } dependencies { - testImplementation platform(libs.junit.bom) testImplementation libs.bundles.junit.jupiter.essentials testRuntimeOnly libs.junit.jupiter.engine - testRuntimeOnly libs.junit.platform.launcher -} - -tasks.withType(Test).configureEach { - useJUnitPlatform() } diff --git a/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle b/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle index 1570598ef..3c35d1a43 100644 --- a/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle +++ b/buildSrc/src/main/groovy/tapestry.junit5-spock-convention.gradle @@ -1,3 +1,7 @@ +// Use for modules that write tests in Spock (Groovy-based BDD framework). +// Extends tapestry.junit5-convention with the Spock BOM and spock-core. +// Spock runs on the JUnit Platform, so no additional runner config is needed. + plugins { id 'tapestry.junit5-convention' id 'groovy' diff --git a/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle b/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle index 35dd0f937..c4f1a1f06 100644 --- a/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle +++ b/buildSrc/src/main/groovy/tapestry.testing-base-convention.gradle @@ -1,12 +1,32 @@ +// Shared test infrastructure for all testing conventions. +// Applied indirectly via tapestry.junit5-convention and tapestry.testng-convention. +// +// DO NOT USE DIRECTLY! +// +// Configures every Test task in the project (via tasks.withType(Test)): +// - JUnit Platform as the test runner (required by both Jupiter and testng-engine) +// - junit-platform-launcher + JUnit BOM on the runtime classpath +// - Standard system properties: encoding, locale, CI flag, Selenium timeout +// - Consistent test logging (full exception format, pass/skip/fail events, progress counter) +// +// The JUnit BOM ensures all JUnit Platform artifacts (launcher, engines) use the same version, +// even in modules that only use TestNG and never write a single @Test(jupiter) method. + +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.TestResult.ResultType + plugins { id 'java-library' } dependencies { + testImplementation platform(libs.junit.bom) testRuntimeOnly libs.slf4j.simple + testRuntimeOnly libs.junit.platform.launcher } tasks.withType(Test).configureEach { testTask -> + useJUnitPlatform() maxHeapSize = '600M' systemProperties( @@ -21,22 +41,24 @@ tasks.withType(Test).configureEach { testTask -> environment.LANG = 'en_US.UTF-8' testLogging { - exceptionFormat 'full' + exceptionFormat = TestExceptionFormat.FULL events 'passed', 'skipped', 'failed' showStandardStreams = true } + // The code below is a helper to output test progress during testing + def total = 0, passed = 0, failed = 0, skipped = 0 afterTest { descriptor, result -> switch (result.resultType) { - case org.gradle.api.tasks.testing.TestResult.ResultType.SUCCESS: + case ResultType.SUCCESS: passed++ break - case org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE: + case ResultType.FAILURE: failed++ break - case org.gradle.api.tasks.testing.TestResult.ResultType.SKIPPED: + case ResultType.SKIPPED: skipped++ break } @@ -50,17 +72,16 @@ tasks.withType(Test).configureEach { testTask -> // The root suite has a null parent. We only want to log the final summary. if (descriptor.parent == null) { total = passed + failed + skipped - // Using project.path gives a clear identifier like ":tapestry-core" - def projectName = project.path - // Don't log if no tests were run + // Only log if we actually have tested something if (total > 0) { + // Using project.path plus task gives a clear identifier like ":tapestry-core:test" + def taskIdentifier = "${project.path}:${name}" logger.lifecycle "------------------------------------------------------------------------" - logger.lifecycle "Test Results for ${projectName}" + logger.lifecycle "Test Results for ${taskIdentifier}" logger.lifecycle " Tests run: ${total}, Passed: ${passed}, Failed: ${failed}, Skipped: ${skipped}" logger.lifecycle "------------------------------------------------------------------------" } } } } - diff --git a/buildSrc/src/main/groovy/tapestry.testng-convention.gradle b/buildSrc/src/main/groovy/tapestry.testng-convention.gradle index da6dc9d17..083069931 100644 --- a/buildSrc/src/main/groovy/tapestry.testng-convention.gradle +++ b/buildSrc/src/main/groovy/tapestry.testng-convention.gradle @@ -1,3 +1,19 @@ +// Use for modules whose test sources use TestNG annotations (@Test, @BeforeMethod, ...). +// +// Adds TestNG + EasyMock to the test compile classpath, and testng-engine at runtime +// so the standard 'test' task (JUnit Platform) discovers and runs TestNG unit tests +// without any configuration change. +// +// Modules that ALSO have Selenium integration tests must additionally declare: +// - A 'testNG' task using useTestNG { suiteXmlFiles << ... } for native TestNG execution +// (needed for correct @BeforeTest / ITestContext scoping across multiple test apps) +// - An exclusion on the 'test' task to skip integration classes +// - tasks.named('check') { dependsOn 'testNG' } +// +// Convention hierarchy: +// tapestry.testing-base-convention platform runner, BOM, logging +// └─ tapestry.testng-convention + TestNG + EasyMock + testng-engine (this file) + plugins { id 'tapestry.testing-base-convention' } @@ -5,22 +21,5 @@ plugins { dependencies { testImplementation libs.testng testImplementation libs.easymock -} - -tasks.withType(Test).configureEach { testTask -> - - def suiteFile = [ - 'src/test/resources/testng.xml', - 'src/test/conf/testng.xml' - ].find { path -> - project.file(path).exists() - } - - if (suiteFile) { - testTask.useTestNG { - suites suiteFile - } - } else { - testTask.useTestNG() - } + testRuntimeOnly libs.testng.engine } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 98f100db6..cbaeb2a94 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -72,8 +72,7 @@ rhino = "1.7.7.2" # TESTING -junit5 = "5.14.2" -junit4 = "4.13.2" +junit5 = "5.14.3" testng = "7.5.1" easymock = "5.4.0" @@ -197,11 +196,11 @@ junit-jupiter = { module = "org.junit.jupiter:junit-jupiter"} junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api" } junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params" } junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" } +junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine" } junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } -junit4 = { module = "junit:junit", version.ref = "junit4" } - -testng = { module = "org.testng:testng", version.ref = "testng" } +testng = { module = "org.testng:testng", version.ref = "testng" } +testng-engine = { module = "org.junit.support:testng-engine", version = "1.1.0" } easymock = { module = "org.easymock:easymock", version.ref = "easymock" } diff --git a/tapestry-beanvalidator/build.gradle b/tapestry-beanvalidator/build.gradle index b11ffabcd..611391011 100644 --- a/tapestry-beanvalidator/build.gradle +++ b/tapestry-beanvalidator/build.gradle @@ -2,8 +2,6 @@ plugins { id 'tapestry.testng-convention' } -import t5build.* - description = 'Support for JSR-303 Bean Validation via the Hibernate validator implementation' dependencies { @@ -27,6 +25,21 @@ tasks.register('runTestApp303', JavaExec) { classpath += project.sourceSets.test.runtimeClasspath } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.beanvalidator.modules.BeanValidatorModule' diff --git a/tapestry-core/build.gradle b/tapestry-core/build.gradle index 9f4b55af0..133bef559 100644 --- a/tapestry-core/build.gradle +++ b/tapestry-core/build.gradle @@ -1,16 +1,12 @@ +import t5build.NpmTask + plugins { id 'tapestry.junit5-convention' id 'tapestry.testng-convention' } -import t5build.TapestryBuildLogic -import org.apache.tools.ant.filters.ReplaceTokens - description = 'Central module for Tapestry, containing all core services and components' -def npmWorkingDir = 'src/main/typescript/' -def npmExec = TapestryBuildLogic.isWindows() ? 'npm.cmd' : 'npm' - dependencies { api project(':tapestry-ioc') api project(':tapestry-json') @@ -29,41 +25,39 @@ dependencies { provided libs.javax.servlet.api testImplementation libs.commons.httpclient - testImplementation project(":tapestry-spock") + testImplementation project(':tapestry-spock') - testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.hsqldb } -tasks.register('npmInstall', Exec) { - group = 'TypeScript' - description = 'Runs npm install' - - workingDir = npmWorkingDir - commandLine npmExec, 'install' +tasks.register('npmInstall', NpmTask) { + group = 'typescript' + description = 'Runs npm ci' + + npmArgs = ['ci'] } -tasks.register('compileTypeScriptToAmd', Exec) { - group = 'TypeScript' +tasks.register('compileTypeScriptToAmd', NpmTask) { + group = 'typescript' description = 'Compiles TypeScript to AMD modules' - dependsOn npmInstall - workingDir = npmWorkingDir - commandLine npmExec, 'run', 'build-amd' + npmArgs = ['run', 'build-amd'] } -tasks.register('compileTypeScriptToEsModule', Exec) { - group = 'TypeScript' +tasks.register('compileTypeScriptToEsModule', NpmTask) { + group = 'typescript' description = 'Compiles TypeScript to ES modules' - dependsOn npmInstall - - workingDir = npmWorkingDir - commandLine npmExec, 'run', 'build-es-module' + + npmArgs = ['run', 'build-es-module'] } +// Lifecycle task that triggers both TypeScript compilations. +// Typed as Delete only because Gradle requires a concrete type +// and this task performs no actions of its own. tasks.register('compileTypeScript', Delete) { - group = 'TypeScript' + group = 'typescript' description = 'Compiles all TypeScript variants' dependsOn compileTypeScriptToAmd, compileTypeScriptToEsModule @@ -73,18 +67,16 @@ tasks.named('sourcesJar') { dependsOn compileTypeScript } -tasks.register('generateTypeScriptDocs', Exec) { - group = 'TypeScript' +tasks.register('generateTypeScriptDocs', NpmTask) { + group = 'typescript' description = 'Generates TypeScript documentation' - dependsOn npmInstall - workingDir = npmWorkingDir - commandLine npmExec, 'run', 'docs' + npmArgs = ['run', 'docs'] } tasks.register('cleanTypeScriptFiles', Delete) { - group = 'TypeScript' + group = 'typescript' description = 'Cleans generated TypeScript files' delete fileTree('src/main/resources/META-INF/assets/es-modules/t5/core') { @@ -105,12 +97,18 @@ tasks.named('clean') { } -// Not sure why this is necessary: +// Groovy test classes extend Java test base classes, so Java must be compiled first. +// Gradle does not infer this ordering automatically in mixed-language source sets. tasks.named('compileTestGroovy') { dependsOn compileTestJava } test { + useJUnitPlatform() + + // Don't run integration tests via Jupiter testng-runner + exclude '**/integration/**' + // Needed to have XMLTokenStreamTests.testStreamEncoding() passing on Java 9+ if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_1_9)) { jvmArgs('--add-opens=java.base/java.nio.charset=ALL-UNNAMED') @@ -120,6 +118,23 @@ test { systemProperty 'user.language', 'en' } +// This task runs the default integration tests that are defined in the testng.xml +tasks.register('testNG', Test) { + group = 'verification' + classpath = sourceSets.test.runtimeClasspath + + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } + + // TAP5-2722 + systemProperty 'user.language', 'en' +} + +tasks.named('check') { + dependsOn 'testNG' +} + [ 'app1', 'app2', @@ -130,7 +145,7 @@ test { 'appfolder' ].each { appName -> tasks.register("runTest${appName.capitalize()}", JavaExec) { - group = 'Application' + group = 'application' description = "Starts the ${appName} integration test app, useful when debugging." mainClass = 'org.apache.tapestry5.test.JettyRunner' @@ -139,41 +154,48 @@ test { } } -// Default is jQuery and Require.js enabled, so here are the tests for the -// other combinations - -tasks.register('testWithJqueryAndRequireJsDisabled', Test) { - group = 'Verification' - description = 'Runs tests with jQuery and Require.js disabled' +// The default testNG run uses jQuery + Require.js (the most common production config). +// These three tasks exercise the other combinations. They are NOT wired into 'check' +// and run only via the 'continuousIntegration' task in the root build. - systemProperties( - 'tapestry.javascript-infrastructure-provider': 'jquery', - 'tapestry.require-js-enabled': 'false', - 'tapestry.port': '9091', - 'tapestry.ssl-port': '8444' - ) -} - -tasks.register('testWithPrototypeAndRequireJsEnabled', Test) { - group = 'Verification' - description = 'Runs tests with Prototype and Require.js enabled' - - systemProperties( - 'tapestry.javascript-infrastructure-provider': 'prototype', - 'tapestry.require-js-enabled': 'true', - 'tapestry.port': '9092', - 'tapestry.ssl-port': '8445' - ) -} +[ + [ + name: 'testWithJqueryAndRequireJsDisabled', + provider: 'jquery', + requireJs: 'false', + port: '9091', + sslPort: '8444' + ], + [ + name: 'testWithPrototypeAndRequireJsEnabled', + provider: 'prototype', + requireJs: 'true', + port: '9092', + sslPort: + '8445' + ], + [ + name: 'testWithPrototypeAndRequireJsDisabled', + provider: 'prototype', + requireJs: 'false', + port: '9093', + sslPort: '8446' + ] +].each { cfg -> + tasks.register(cfg.name, Test) { + group = 'verification' + description = "Runs integration tests with ${cfg.provider} and RequireJS ${cfg.requireJs == 'true' ? 'enabled' : 'disabled'}" + classpath = sourceSets.test.runtimeClasspath -tasks.register('testWithPrototypeAndRequireJsDisabled', Test) { - group = 'Verification' - description = 'Runs tests with Prototype and Require.js disabled' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } - systemProperties( - 'tapestry.javascript-infrastructure-provider': 'prototype', - 'tapestry.require-js-enabled': 'false', - 'tapestry.port': '9093', - 'tapestry.ssl-port': '8446' - ) + systemProperties( + 'tapestry.javascript-infrastructure-provider': cfg.provider, + 'tapestry.require-js-enabled': cfg.requireJs, + 'tapestry.port': cfg.port, + 'tapestry.ssl-port': cfg.sslPort + ) + } } diff --git a/tapestry-core/src/test/resources/testng.xml b/tapestry-core/src/test/resources/testng.xml index e7ffac3f7..b46d6f256 100644 --- a/tapestry-core/src/test/resources/testng.xml +++ b/tapestry-core/src/test/resources/testng.xml @@ -11,50 +11,6 @@ name="Tapestry Core" annotations="1.5" verbose="2"> - <test - name="Component Unit Tests" - enabled="true"> - <packages> - <package name="org.apache.tapestry5.pagetester" /> - <package name="org.apache.tapestry5.integration.pagelevel" /> - <package name="org.apache.tapestry5.corelib.base" /> - <package name="org.apache.tapestry5.corelib.components" /> - <package name="org.apache.tapestry5.corelib.mixins" /> - <package name="org.apache.tapestry5.corelib.internal" /> - </packages> - </test> - - <test - name="Service Unit Tests" - enabled="true"> - <packages> - <package name="org.apache.tapestry5.root" /> - <package name="org.apache.tapestry5.dom" /> - <package name="org.apache.tapestry5.runtime" /> - <package name="org.apache.tapestry5.services" /> - <package name="org.apache.tapestry5.services.javascript" /> - <package name="org.apache.tapestry5.util" /> - <package name="org.apache.tapestry5.validator" /> - <package name="org.apache.tapestry5.internal" /> - <package name="org.apache.tapestry5.internal.beaneditor" /> - <package name="org.apache.tapestry5.internal.bindings" /> - <package name="org.apache.tapestry5.internal.grid" /> - <package name="org.apache.tapestry5.internal.model" /> - <package name="org.apache.tapestry5.internal.pageload" /> - <package name="org.apache.tapestry5.internal.services" /> - <package name="org.apache.tapestry5.internal.services.assets" /> - <package name="org.apache.tapestry5.internal.services.messages" /> - <package name="org.apache.tapestry5.internal.services.meta" /> - <package name="org.apache.tapestry5.internal.services.templates" /> - <package name="org.apache.tapestry5.internal.structure" /> - <package name="org.apache.tapestry5.internal.test" /> - <package name="org.apache.tapestry5.internal.transform" /> - <package name="org.apache.tapestry5.internal.translator" /> - <package name="org.apache.tapestry5.internal.util" /> - <package name="org.apache.tapestry5.internal.services.ajax" /> - </packages> - </test> - <!-- We break these out by which of the test applications they apply to. We have a bunch. --> <test name="Core Integration Tests" diff --git a/tapestry-hibernate-core/build.gradle b/tapestry-hibernate-core/build.gradle index 48aa01612..60ef293d3 100644 --- a/tapestry-hibernate-core/build.gradle +++ b/tapestry-hibernate-core/build.gradle @@ -12,7 +12,7 @@ dependencies { implementation libs.jaxb.runtime testImplementation project(':tapestry-test') - testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.hsqldb } jar { diff --git a/tapestry-hibernate/build.gradle b/tapestry-hibernate/build.gradle index f6e08dd8b..a2a9d32d7 100644 --- a/tapestry-hibernate/build.gradle +++ b/tapestry-hibernate/build.gradle @@ -11,7 +11,7 @@ dependencies { implementation libs.jboss.logging testImplementation project(':tapestry-test') - testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.hsqldb } tasks.register('runTestApp0', JavaExec) { @@ -22,6 +22,21 @@ tasks.register('runTestApp0', JavaExec) { classpath += project.sourceSets.test.runtimeClasspath } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.hibernate.web.modules.HibernateModule' diff --git a/tapestry-hibernate/src/test/resources/testng.xml b/tapestry-hibernate/src/test/resources/testng.xml index ae459a0ca..764776869 100644 --- a/tapestry-hibernate/src/test/resources/testng.xml +++ b/tapestry-hibernate/src/test/resources/testng.xml @@ -17,11 +17,6 @@ <suite name="Tapestry Hibernate" parallel="false" thread-count="10" annotations="1.5" verbose="2"> <parameter name="tapestry.integration-webapp" value="src/test/webapp"/> - <test name="Tapestry Hibernate Internal APIs"> - <packages> - <package name="org.apache.tapestry5.internal.hibernate"/> - </packages> - </test> <test name="Tapestry Hibernate Integration Tests"> <packages> <package name="org.apache.tapestry5.hibernate.integration"/> diff --git a/tapestry-http/build.gradle b/tapestry-http/build.gradle index 49c4bea43..1cbc9ec3e 100644 --- a/tapestry-http/build.gradle +++ b/tapestry-http/build.gradle @@ -19,7 +19,7 @@ dependencies { testImplementation project(':tapestry-test') testImplementation project(':tapestry-test-constants') - testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly libs.hsqldb testRuntimeOnly libs.slf4j.simple } @@ -33,3 +33,18 @@ tasks.named('jar', Jar) { filter(ReplaceTokens, tokens: [version: project.parent.version]) } } + +tasks.named('test') { + exclude '**/TapestryHttpIntegrationTests*' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} diff --git a/tapestry-http/src/test/resources/testng.xml b/tapestry-http/src/test/resources/testng.xml new file mode 100644 index 000000000..edd62c552 --- /dev/null +++ b/tapestry-http/src/test/resources/testng.xml @@ -0,0 +1,11 @@ +<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> + +<suite name="Tapestry HTTP" annotations="1.5" verbose="2"> + + <test name="Tapestry HTTP Integration Tests" enabled="true"> + <packages> + <package name="org.apache.tapestry5.http.test" /> + </packages> + </test> + +</suite> diff --git a/tapestry-ioc/build.gradle b/tapestry-ioc/build.gradle index 75879fb7b..ce2e31c76 100644 --- a/tapestry-ioc/build.gradle +++ b/tapestry-ioc/build.gradle @@ -18,8 +18,8 @@ dependencies { testImplementation libs.commons.lang3 testImplementation libs.hibernate.core - testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") + testRuntimeOnly("${libs.hsqldb.get().module.group}:${libs.hsqldb.get().module.name}:${libs.hsqldb.get().version}:jdk8") } tasks.named('test', Test) { diff --git a/tapestry-jmx/build.gradle b/tapestry-jmx/build.gradle index 00694090c..b4d80f37e 100644 --- a/tapestry-jmx/build.gradle +++ b/tapestry-jmx/build.gradle @@ -10,6 +10,21 @@ dependencies { testImplementation project(':tapestry-test') } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + jar { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jmx.modules.JmxModule' diff --git a/tapestry-jpa/build.gradle b/tapestry-jpa/build.gradle index 2bb87cb1d..da097ab4d 100644 --- a/tapestry-jpa/build.gradle +++ b/tapestry-jpa/build.gradle @@ -27,6 +27,21 @@ dependencies { } } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.jpa.modules.JpaModule' diff --git a/tapestry-jpa/src/test/java/org/apache/tapestry5/internal/jpa/JpaTransactionAdvisorImplTest.java b/tapestry-jpa/src/test/java/org/apache/tapestry5/internal/jpa/JpaTransactionAdvisorImplTest.java index 5789ad684..e5591b68c 100644 --- a/tapestry-jpa/src/test/java/org/apache/tapestry5/internal/jpa/JpaTransactionAdvisorImplTest.java +++ b/tapestry-jpa/src/test/java/org/apache/tapestry5/internal/jpa/JpaTransactionAdvisorImplTest.java @@ -37,6 +37,9 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +// Disabled as JUnit would pick it up, but TestNG ignored it due to missing in testng.xml +// https://github.com/apache/tapestry-5/commit/246e677097f249ad2352ddc595ef43cc257f8e27 +@Test(enabled = false) public class JpaTransactionAdvisorImplTest extends IOCTestCase { private static final String UNIT_NAME = "FooUnit"; @@ -62,7 +65,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase registry = null; } - @Test + @Test(enabled = false) public void undecorated() { final VoidService delegate = newMock(VoidService.class); @@ -84,7 +87,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void persistence_unit_name_missing() { final VoidService delegate = newMock(VoidService.class); @@ -118,7 +121,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void persistence_unit_name_missing_single_unit_configured() { final VoidService delegate = newMock(VoidService.class); @@ -147,7 +150,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void persistence_unit_missing() { final VoidService delegate = newMock(VoidService.class); @@ -181,7 +184,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void persistence_unit_missing_single_unit_configured() { final VoidService delegate = newMock(VoidService.class); @@ -210,7 +213,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void transaction_inactive() { final VoidService delegate = newMock(VoidService.class); @@ -238,7 +241,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void void_method() { final VoidService delegate = newMock(VoidService.class); @@ -266,7 +269,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void void_method_with_param() { final VoidService delegate = newMock(VoidService.class); @@ -292,7 +295,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void runtime_exception_will_abort_transaction() throws Exception { final Performer delegate = newMock(Performer.class); @@ -328,7 +331,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void checked_exception_will_commit_transaction() throws Exception { final Performer delegate = newMock(Performer.class); @@ -369,7 +372,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void return_type_method() { final ReturnTypeService delegate = newTestService(); @@ -395,7 +398,7 @@ public class JpaTransactionAdvisorImplTest extends IOCTestCase verify(); } - @Test + @Test(enabled = false) public void return_type_method_with_param() { final ReturnTypeService delegate = newTestService(); diff --git a/tapestry-jpa/src/test/java/org/apache/tapestry5/jpa/test/JpaTest.java b/tapestry-jpa/src/test/java/org/apache/tapestry5/jpa/test/JpaTest.java index 267b07617..2671c4fbf 100644 --- a/tapestry-jpa/src/test/java/org/apache/tapestry5/jpa/test/JpaTest.java +++ b/tapestry-jpa/src/test/java/org/apache/tapestry5/jpa/test/JpaTest.java @@ -47,6 +47,9 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +// Disabled as JUnit would pick it up, but TestNG ignored it due to missing in testng.xml +// https://github.com/apache/tapestry-5/commit/246e677097f249ad2352ddc595ef43cc257f8e27 +@Test(enabled = false) public class JpaTest { @@ -149,7 +152,7 @@ public class JpaTest return em.createQuery(query).getResultList(); } - @Test + @Test(enabled = false) public void commitBothInNestedTransaction() { topLevelService.createThingOneAndTwo("one", "two"); @@ -158,19 +161,19 @@ public class JpaTest assertTrue(getEntityManager().find(VersionedThing.class, 1).getVersion() > 0); } - @Test(expectedExceptions = RollbackException.class) + @Test(expectedExceptions = RollbackException.class, enabled = false) public void rollbackNestedFails() { topLevelService.createThingOneAndTwo("one", null); } - @Test(expectedExceptions = RollbackException.class) + @Test(expectedExceptions = RollbackException.class, enabled = false) public void rollbackTopFails() { topLevelService.createThingOneAndTwo(null, "two"); } - @Test + @Test(enabled = false) public void sequentialCommitUsingInvokeAfterCommit() { topLevelService.createThingOneThenTwo("one", "two"); @@ -179,7 +182,7 @@ public class JpaTest assertTrue(getEntityManager().find(VersionedThing.class, 1).getVersion() > 1); } - @Test + @Test(enabled = false) public void sequentialCommitUsingInvokeAfterCommitAndCommitAfterAnnotation() { topLevelService.createThingOneThenTwoWithNestedCommitAfter("one", "two"); @@ -188,7 +191,7 @@ public class JpaTest assertTrue(getEntityManager().find(VersionedThing.class, 1).getVersion() > 1); } - @Test + @Test(enabled = false) public void sequentialRollbackAndAbortUsingInvokeAfterCommit() { try @@ -203,7 +206,7 @@ public class JpaTest assertEquals(0, getInstances(ThingTwo.class).size()); } - @Test + @Test(enabled = false) public void trySomething() { ThingOne thingOne = new ThingOne(); diff --git a/tapestry-kaptcha/build.gradle b/tapestry-kaptcha/build.gradle index bb011c385..f08d8bcc1 100644 --- a/tapestry-kaptcha/build.gradle +++ b/tapestry-kaptcha/build.gradle @@ -14,6 +14,21 @@ dependencies { testImplementation project(':tapestry-test') } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.kaptcha.modules.KaptchaModule' diff --git a/tapestry-kaptcha/src/test/java/org/apache/tapestry5/kaptcha/components/KaptchaUnitTest.java b/tapestry-kaptcha/src/test/java/org/apache/tapestry5/kaptcha/components/KaptchaUnitTest.java index 849bf0056..3ea5d713f 100644 --- a/tapestry-kaptcha/src/test/java/org/apache/tapestry5/kaptcha/components/KaptchaUnitTest.java +++ b/tapestry-kaptcha/src/test/java/org/apache/tapestry5/kaptcha/components/KaptchaUnitTest.java @@ -19,11 +19,12 @@ import org.apache.tapestry5.internal.test.TestableResponse; import org.apache.tapestry5.test.PageTester; import org.junit.Test; +@Test(enabled = false) public class KaptchaUnitTest { @SuppressWarnings("unchecked") - @Test + @Test(enabled = false) public void cache_control_header() { PageTester tester = new PageTester("kaptcha.demo", "app"); diff --git a/tapestry-spring/build.gradle b/tapestry-spring/build.gradle index 248e3d049..9782baf62 100644 --- a/tapestry-spring/build.gradle +++ b/tapestry-spring/build.gradle @@ -16,7 +16,7 @@ dependencies { ['', '1'].each { suffix -> tasks.register("runTestApp${suffix}", JavaExec) { - group = 'Application' + group = 'application' description = "Start tapestry-spring integration test app${suffix}, useful when debugging failing integration tests" mainClass = 'org.apache.tapestry5.test.JettyRunner' args '-d', "src/test/webapp${suffix}", '-p', '8080' @@ -24,6 +24,21 @@ dependencies { } } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.spring.modules.SpringModule' diff --git a/tapestry-spring/src/test/resources/testng.xml b/tapestry-spring/src/test/resources/testng.xml index 076743557..d40d02bf2 100644 --- a/tapestry-spring/src/test/resources/testng.xml +++ b/tapestry-spring/src/test/resources/testng.xml @@ -16,12 +16,6 @@ --> <suite name="Tapesty Spring Integration" parallel="false" thread-count="10" annotations="1.5" verbose="2"> - <test name="Tapestry Spring Unit Tests"> - <packages> - <package name="org.apache.tapestry5.spring"/> - <package name="org.apache.tapestry5.internal.spring"/> - </packages> - </test> <test name="Tapestry Spring Integration - Standard"> <packages> <package name="org.apache.tapestry5.spring.integration.standard"/> diff --git a/tapestry-test/build.gradle b/tapestry-test/build.gradle index 70b34c377..281b3f9c0 100644 --- a/tapestry-test/build.gradle +++ b/tapestry-test/build.gradle @@ -25,3 +25,18 @@ dependencies { api libs.testng api libs.easymock } + +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} diff --git a/tapestry-upload/build.gradle b/tapestry-upload/build.gradle index 6873b19c6..d55fcbbb4 100644 --- a/tapestry-upload/build.gradle +++ b/tapestry-upload/build.gradle @@ -16,6 +16,21 @@ dependencies { testImplementation project(':tapestry-test') } +tasks.named('test') { + exclude '**/integration/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + useTestNG { + suiteXmlFiles << project.file('src/test/resources/testng.xml') + } +} + +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.upload.modules.UploadModule' diff --git a/tapestry-upload/src/test/resources/testng.xml b/tapestry-upload/src/test/resources/testng.xml index a6ed19248..d6d82a9ec 100755 --- a/tapestry-upload/src/test/resources/testng.xml +++ b/tapestry-upload/src/test/resources/testng.xml @@ -19,8 +19,6 @@ <test name="Tapesty Upload Component"> <parameter name="tapestry.web-app-folder" value="src/test/webapp"/> <packages> - <package name="org.apache.tapestry5.upload.components"/> - <package name="org.apache.tapestry5.upload.internal.services"/> <package name="org.apache.tapestry5.upload.integration"/> </packages> </test> diff --git a/tapestry-webresources/build.gradle b/tapestry-webresources/build.gradle index fcca7534f..ff8d65a26 100644 --- a/tapestry-webresources/build.gradle +++ b/tapestry-webresources/build.gradle @@ -31,7 +31,19 @@ dependencies { } -test { +tasks.named('test') { + useJUnitPlatform() + exclude '**/services/web/**' +} + +tasks.register('testNG', Test) { + group = 'verification' + description = 'Runs Selenium integration tests via native TestNG' + + useTestNG() + + include '**/services/web/**' + systemProperties( 'tapestry.page-load-timeout': '60', 'tapestry.compiled-asset-cache-dir': "$buildDir/compiled-asset-cache", @@ -41,6 +53,10 @@ test { ) } +tasks.named('check') { + dependsOn 'testNG' +} + tasks.named('jar', Jar) { manifest { attributes 'Tapestry-Module-Classes': 'org.apache.tapestry5.webresources.modules.WebResourcesModule' diff --git a/tapestry-webresources/src/test/java/t5/webresources/services/web/WebResourcesTest.java b/tapestry-webresources/src/test/java/t5/webresources/services/web/WebResourcesTest.java index c4b932c81..d4d5bb7f5 100644 --- a/tapestry-webresources/src/test/java/t5/webresources/services/web/WebResourcesTest.java +++ b/tapestry-webresources/src/test/java/t5/webresources/services/web/WebResourcesTest.java @@ -26,6 +26,11 @@ public class WebResourcesTest extends SeleniumTestCase { @Test public void test_CoffeeScript_compilation() { + // It appears that the initial CoffeeScriptCompiler/Rhino initialization might + // take too long on Apache CI, so we allow Selenium some more time to wait + // after initiating the request. + setTimeout("90000"); // 90s + open("/"); waitForInitializedPage(); assertEquals(getText("banner"), "Index module loaded, bare!");
