Search code examples
javagradlecode-generationopenapi

Gradle: compile and run a single test


I have a separate task to run the test that generates open-api.yml specification for my application. Here is the Gradle configuration below:

task generateOpenApiYml(type: Test) {
    group = 'verification'
    useJUnitPlatform {
        includeTags 'openApi'
    }
    testLogging {
        showExceptions true
        showStandardStreams = false
        showCauses true
        showStackTraces true
        exceptionFormat "full"
        events("skipped", "failed", "passed")
    }
}

So, I have one test with openApi JUnit tag. It works very well, but there is a slight thing I want to approve.

The whole idea of this test is that the result open-api.yml file is used to generate Java client to invoke REST endpoints. This client is used in other tests in the project.

I want to put those generated Java classes to .gitgnore because they are generated anyway and there is no need to index those files. The problem is that the generateOpenApiYml task compiles all the tests in src/test/java directory. Therefore, some of them use generated classes. Which leads to compiling errors.

Is it possible to tune the generateOpenApiYml task to make it compile and run only the single test with openApi JUnit tag? Then I could easily put generated Java classes to .gitignore and don't bother about their temporary absence, because other tests won't be compiled.


Solution

  • I figured out the solution. Firstly, I installed the gradle-testsets-plugin.

    Then I configured a separate source set like this:

    testSets {
        generateOpenApiYml
    }
    

    So, generateOpenApiYml is the new Gradle task that looks for sources in src/generatedOpenApiYml/java directory.

    Afterwards, we need to tune all tasks of test type to bind them with JUnit 5 platform.

    tasks.withType(Test) {
        group = 'verification'
        useJUnitPlatform()
        testLogging {
            showExceptions true
            showStandardStreams = false
            showCauses true
            showStackTraces true
            exceptionFormat "full"
            events("skipped", "failed", "passed")
        }
    }
    
    generateOpenApiYml.outputs.upToDateWhen { false }
    

    I put the upToDateWhen option for convenience to make sure the generateOpenApiYml task is always run on demand and never cached.

    Then I have the open-api-generator.

    openApiGenerate {
        inputSpec = "$buildDir/classes/java/generateOpenApiYml/open-api.json".toString()
        outputDir = "$buildDir/generated/openapi".toString()
        apiPackage = "..."
        invokerPackage = "..."
        modelPackage = "..."
        configOptions = [
                dateLibrary    : "java8",
                openApiNullable: "false",
        ]
        generatorName = 'java'
        groupId = "..."
        globalProperties = [
                modelDocs: "false"
        ]
        additionalProperties = [
                hideGenerationTimestamp: true
        ]
    }
    
    tasks.named('openApiGenerate') {
        dependsOn generateOpenApiYml
    }
    

    Finally, I just need to run two commands to build and run tests for my whole project.

    ./gradlew openApiGenerate
    ./gradlew build
    

    The first one creates the open-api.yml file and generates Java client according to the provided specification. The second one runs tests and build the project normally. The tests running during the build phase uses classes generated by openApiGenerate task. Therefore, I can put them to .gitignore safely.

    Hope this will be helpful.