gradle-testing-setup

📁 dawiddutoit/custom-claude 📅 Jan 26, 2026
4
总安装量
4
周安装量
#50032
全站排名
安装命令
npx skills add https://github.com/dawiddutoit/custom-claude --skill gradle-testing-setup

Agent 安装分布

mcpjam 4
neovate 4
gemini-cli 4
antigravity 4
windsurf 4
zencoder 4

Skill 文档

Gradle Testing Setup

Table of Contents

When to Use This Skill

Use this skill when you need to:

  • Set up JUnit 5 (Jupiter) testing framework
  • Configure TestContainers for integration tests with real databases
  • Separate unit tests from integration tests
  • Measure code coverage with JaCoCo
  • Enforce minimum code coverage thresholds
  • Configure parallel test execution for faster test runs
  • Set up test logging and reporting in CI/CD
  • Create separate source sets for integration tests

Quick Start

Add to build.gradle.kts:

dependencies {
    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)
}

Run tests:

./gradlew test                    # Run unit tests
./gradlew test jacocoTestReport   # With coverage report
./gradlew integrationTest         # Run integration tests (if configured)

Instructions

Step 1: Configure JUnit 5 (Jupiter)

Add JUnit 5 dependencies:

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()
}

Advanced JUnit 5 configuration:

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
    }
}

Step 2: Set Up TestContainers for Integration Tests

Add TestContainers dependencies:

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")
}

Example integration test with TestContainers:

@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
    }
}

Step 3: Separate Unit and Integration Tests

Create separate source sets and tasks:

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)
}

Directory structure:

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.yml

Step 4: Configure Code Coverage with JaCoCo

Add JaCoCo plugin and configuration:

plugins {
    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)
}

Step 5: Configure Test Logging

Use prettier test output with test-logger plugin:

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
}

Step 6: Configure Docker for TestContainers

Ensure Docker is properly configured:

# 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 test

In gradle.properties for CI/CD:

org.gradle.logging.level=info
testcontainers.reuse.enable=true

Examples

Example: Running Different Test Suites

# 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

For advanced examples including TestContainers integration, GitHub Actions with coverage reports, and CI coverage verification, see references/advanced-examples.md.

Commands Reference

See references/commands-and-troubleshooting.md for complete command reference and troubleshooting guide.

See Also