Loading...
Loading...
Configures comprehensive testing in Gradle including JUnit 5, TestContainers, test separation (unit vs integration), and code coverage with JaCoCo. Use when asked to "set up JUnit 5", "configure TestContainers", "separate integration tests", or "add code coverage". Works with build.gradle.kts, test source sets, and CI/CD configurations.
npx skill4agent add dawiddutoit/custom-claude gradle-testing-setupbuild.gradle.ktsdependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.testcontainers:testcontainers:1.21.0")
testImplementation("org.testcontainers:junit-jupiter:1.21.0")
testImplementation("org.testcontainers:postgresql:1.21.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
plugins {
id("jacoco")
}
tasks.test {
useJUnitPlatform()
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
finalizedBy(tasks.jacocoTestCoverageVerification)
}
tasks.check {
dependsOn(tasks.jacocoTestReport)
}./gradlew test # Run unit tests
./gradlew test jacocoTestReport # With coverage report
./gradlew integrationTest # Run integration tests (if configured)dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.11.0")
}
tasks.test {
useJUnitPlatform()
}tasks.test {
useJUnitPlatform {
// Include/exclude tags
includeTags("unit", "integration")
excludeTags("slow", "manual")
// Include/exclude by engine
includeEngines("junit-jupiter")
excludeEngines("junit-vintage")
}
// Filter tests by pattern
filter {
includeTestsMatching("*Test")
includeTestsMatching("*Tests")
excludeTestsMatching("*IntegrationTest")
}
// Parallel test execution
maxParallelForks = Runtime.getRuntime().availableProcessors() / 2
// System properties for tests
systemProperty("junit.jupiter.execution.parallel.enabled", "true")
systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent")
// Detailed logging
testLogging {
events("passed", "skipped", "failed", "standardOut")
showExceptions = true
showStackTraces = true
showCauses = true
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}dependencies {
testImplementation("org.testcontainers:testcontainers:1.21.0")
testImplementation("org.testcontainers:junit-jupiter:1.21.0")
testImplementation("org.testcontainers:postgresql:1.21.0")
testImplementation("org.testcontainers:gcloud:1.21.0") // For Pub/Sub emulator
}
tasks.test {
useJUnitPlatform()
// Docker socket configuration
systemProperty("testcontainers.reuse.enable", "true")
}@SpringBootTest
@Testcontainers
class SupplierChargesIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@Container
static GenericContainer<?> pubsub = new GenericContainer<>("google/cloud-sdk:emulators")
.withExposedPorts(8085)
.withCommand("gcloud", "beta", "emulators", "pubsub", "start", "--host-port=0.0.0.0:8085");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
registry.add("spring.cloud.gcp.pubsub.emulator-host",
() -> "localhost:" + pubsub.getMappedPort(8085));
}
@Test
void testDatabaseAndPubSub() {
// Test with real PostgreSQL and Pub/Sub emulator
}
}sourceSets {
create("integrationTest") {
java {
srcDir("src/integrationTest/java")
compileClasspath += sourceSets.main.get().output + sourceSets.test.get().output
runtimeClasspath += sourceSets.main.get().output + sourceSets.test.get().output
}
resources {
srcDir("src/integrationTest/resources")
}
}
}
// Create integration test task
val integrationTest = tasks.register<Test>("integrationTest") {
description = "Run integration tests"
group = "verification"
testClassesDirs = sourceSets["integrationTest"].output.classesDirs
classpath = sourceSets["integrationTest"].runtimeClasspath
useJUnitPlatform()
// Run after unit tests
shouldRunAfter(tasks.test)
// Logging
testLogging {
events("passed", "skipped", "failed")
}
}
// Include integration tests in overall check
tasks.check {
dependsOn(integrationTest)
}src/
├── main/
│ └── java/
├── test/ # Unit tests
│ ├── java/
│ │ └── com/example/
│ │ ├── ServiceTest.java
│ │ └── ControllerTest.java
│ └── resources/
│ └── application-test.yml
└── integrationTest/ # Integration tests
├── java/
│ └── com/example/
│ └── ServiceIntegrationTest.java
└── resources/
└── application-integration.ymlplugins {
id("jacoco")
}
jacoco {
toolVersion = "0.8.12"
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required = true
html.required = true
csv.required = false
xml.outputLocation = layout.buildDirectory.file("reports/jacoco/test/jacocoTestReport.xml")
html.outputLocation = layout.buildDirectory.dir("reports/jacoco/test/html")
}
finalizedBy(tasks.jacocoTestCoverageVerification)
}
// Enforce coverage minimums
tasks.jacocoTestCoverageVerification {
violationRules {
// Overall coverage requirement
rule {
element = "BUNDLE"
limit {
minimum = BigDecimal("0.60") // 60% minimum
}
}
// Class-level requirements
rule {
element = "CLASS"
excludes = listOf("**/config/*", "**/dto/*")
limit {
counter = "LINE"
value = "COVEREDRATIO"
minimum = BigDecimal("0.50") // 50% per class
}
}
// Method-level requirements
rule {
element = "METHOD"
limit {
counter = "LINE"
value = "COVEREDRATIO"
minimum = BigDecimal("0.40") // 40% per method
}
}
}
}
// Generate report after tests
tasks.test {
finalizedBy(tasks.jacocoTestReport)
}
// Include in overall check
tasks.check {
dependsOn(tasks.jacocoTestReport)
}plugins {
id("com.adarshr.test-logger") version "4.0.0"
}
testlogger {
theme = "mocha" // Options: plain, standard, mocha, standard-parallel, mocha-parallel
showExceptions = true
showStackTraces = true
showFullStackTraces = false
showCauses = true
slowThreshold = 2000 // Warn for tests > 2 seconds
showSummary = true
showPassed = true
showSkipped = true
showFailed = true
showStandardStreams = false
}# Verify Docker is running
docker ps
# On macOS with Docker Desktop
export TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock
export DOCKER_HOST=unix://${HOME}/.docker/run/docker.sock
# Run tests
./gradlew testgradle.propertiesorg.gradle.logging.level=info
testcontainers.reuse.enable=true# Unit tests only
./gradlew test
# Integration tests only
./gradlew integrationTest
# All tests
./gradlew check
# With coverage report
./gradlew test jacocoTestReport
# Specific test class
./gradlew test --tests "com.example.ServiceTest"
# Tests matching pattern
./gradlew test --tests "*IntegrationTest"
# Single test method
./gradlew test --tests "com.example.ServiceTest.testMethod"
# Verbose output
./gradlew test --info
# Continuous mode (rerun on changes)
./gradlew test --continuous