Chapter 1: Gradle Build Integration
Welcome to the jdoc-test
tutorial! Ever wished you could write simple tests directly inside your Java code comments (Javadocs) and have them run automatically when you build your project? That’s exactly what jdoc-test
helps you do!
This first chapter introduces the magic behind making this automation happen: Gradle Build Integration.
The Problem: Manual Test Running is Tedious
Imagine you’ve written some neat examples or test cases right in your Javadoc comments. How would you actually run them?
- You’d need to somehow read those comments from your Java files.
- Then, you’d need to convert those comments into actual test files that a testing tool (like Spock or Cucumber) can understand (e.g.,
.groovy
or.feature
files). - If needed (like for Spock), you’d have to compile these generated test files.
- Finally, you’d need to run these tests using the appropriate testing tool.
Doing this manually for every change would be repetitive and error-prone. We need a way to automate this whole process!
The Solution: Gradle Plugins as Your Build Foreman
This is where Gradle and the jdoc-test
Gradle plugins come in. Think of Gradle as a powerful tool that builds your software project, like a recipe for making your application. Gradle plugins are like adding extra steps or specialized tools to that recipe.
The jdoc-test
project provides two specific Gradle plugins:
jdoc-spock-gradle-plugin
: For tests written in a Spock-like syntax within Javadocs.jdoc-cucumber-gradle-plugin
: For tests written in a Gherkin/Cucumber-like syntax within Javadocs.
These plugins act like a construction foreman for your Javadoc tests. The foreman (the Gradle plugin) knows exactly how to manage the process:
- It reads the plans (your Java source files with Javadoc tests).
- It coordinates workers (Gradle tasks) to prepare the materials (generate
.groovy
or.feature
test files). - It ensures the final structure is built and checked (compiles and runs the tests).
- It even brings the necessary tools and materials (manages dependencies for Spock or Cucumber).
By using these plugins, the entire process of parsing, generating, compiling (if needed), and running your Javadoc tests becomes a seamless part of your regular Gradle build.
How to Use It: Applying the Plugin
Let’s see how simple it is to add this automation using the Cucumber plugin as an example. You just need to tell Gradle to use the plugin in your build.gradle
(if using Groovy DSL) or build.gradle.kts
(if using Kotlin DSL) file.
Example: Applying the Cucumber Plugin (build.gradle - Groovy DSL)
plugins {
id 'java' // Your project needs the Java plugin
id 'io.github.boolivar.jdoctest.jdoc-cucumber' // Apply the jdoc-test Cucumber plugin
}
// Optional: Configure the plugin if defaults aren't right
// jdocCucumber {
// cucumberVersion = "7.15.0" // Specify Cucumber version if needed
// // Other configurations possible, but defaults often work!
// }
repositories {
mavenCentral() // Needed to download the plugin and dependencies
}
// The plugin automatically adds dependencies like cucumber-java
// You might need glue packages for Cucumber step definitions
// dependencies {
// testImplementation 'io.cucumber:cucumber-java:...' // Managed by plugin
// testImplementation 'your.glue.code.package:...'
// }
Explanation:
plugins { ... }
: This block tells Gradle which plugins to activate for your project.id 'java'
: We assume you have a standard Java project.id 'io.github.boolivar.jdoctest.jdoc-cucumber'
: This is the key line! It applies thejdoc-test
Cucumber plugin.repositories { ... }
: Tells Gradle where to find the plugin code.jdocCucumber { ... }
(Optional): Allows you to customize plugin settings, but often the defaults are fine to start. The plugin automatically figures out where your Java source code is and where to put generated files. It also adds the necessary Cucumber dependency for you!
That’s it! By adding that one line (id '...'
), you’ve enabled the magic.
What Happens Now? New Gradle Tasks!
Once you apply the plugin, it automatically adds new tasks to your Gradle project. For the Cucumber plugin, the main tasks are:
generateCucumberFeatures
: This task reads your Javadocs and generates the.feature
files.jdocCucumberTest
: This task runs the generated.feature
files using Cucumber. It automatically depends ongenerateCucumberFeatures
, so you usually just run this one.
You can run these tasks from your command line:
# Generate the .feature files only
./gradlew generateCucumberFeatures
# Generate the .feature files AND run them
./gradlew jdocCucumberTest
# Often, running the standard 'check' or 'test' task will also trigger jdocCucumberTest
./gradlew check
Similarly, the Spock plugin (id 'io.github.boolivar.jdoctest.jdoc-spock'
) adds tasks like generateSpockSpecs
, compileJdocSpockGroovy
, and jdocSpockTest
.
How It Works Under the Hood: The Foreman and the Workers
Let’s peek behind the curtain. How does applying the plugin actually set everything up?
- Configuration Phase: When Gradle starts and reads your
build.gradle
file, it sees thejdoc-test
plugin ID.- The plugin code (like
JdocCucumberPlugin.java
orJdocSpockPlugin.java
) runs. - It tells Gradle about the new tasks (
generate...
,test...
). - It configures these tasks:
- Where to find your Java source code (
sources
). - Where to put the generated test files (
outputDir
). - What dependencies are needed (like
cucumber-java
orspock-core
). - Task dependencies (e.g.,
jdocCucumberTest
must run aftergenerateCucumberFeatures
).
- Where to find your Java source code (
- The plugin code (like
- Execution Phase: When you run a task like
./gradlew jdocCucumberTest
:- Gradle figures out the task dependencies. It sees
jdocCucumberTest
depends ongenerateCucumberFeatures
, so it runsgenerateCucumberFeatures
first. generateCucumberFeatures
Task Runs:- This task (defined in
JdocCucumberTask.java
) gets the list of Java source files. - Internally, it uses the Javadoc Test Parser to read and understand the special Javadoc comments.
- It then uses the BDD Spec Generator to create the actual
.feature
files in the specified output directory (usually somewhere inbuild/generated/sources/...
).
- This task (defined in
- (For Spock only)
compileJdocSpockGroovy
Task Runs: If you were using the Spock plugin, a task would run here to compile the generated.groovy
spec files into Java bytecode. jdocCucumberTest
Task Runs:- This task (configured in
JdocCucumberPlugin.java
to be aJavaExec
task for Cucumber, or aTest
task for Spock) executes the testing framework. - For Cucumber, it runs the Cucumber CLI, pointing it to the generated
.feature
files and your step definition code (“glue”). - For Spock, it runs the JUnit Platform test runner, telling it to look for tests in the compiled output of the generated specs.
- The test results are reported just like any other tests in your build.
- This task (configured in
- Gradle figures out the task dependencies. It sees
Here’s a simplified diagram showing the flow when you run the test task:
sequenceDiagram
participant User
participant Gradle
participant JdocPlugin as Jdoc Plugin (Foreman)
participant GenerateTask as generate... Task (Worker 1)
participant TestTask as test... Task (Worker 2)
User->>Gradle: ./gradlew jdocCucumberTest
Gradle->>JdocPlugin: Load build.gradle & configure tasks
Gradle->>GenerateTask: Execute (because TestTask depends on it)
GenerateTask->>GenerateTask: Find Java sources
GenerateTask->>GenerateTask: Parse Javadocs (using Javadoc Test Parser)
GenerateTask->>GenerateTask: Generate .feature files (using BDD Spec Generator)
Gradle->>TestTask: Execute
TestTask->>TestTask: Run Cucumber/Spock against generated files
TestTask-->>Gradle: Report test results
Gradle-->>User: Show results
A Glimpse at the Plugin Code
You don’t need to understand the plugin’s internal code to use it, but seeing a small piece can help clarify what’s happening.
Example: Part of JdocCucumberPlugin.java
// Inside the JdocCucumberPlugin class...
@Override
public void apply(Project project) {
// Create extension for configuration (like setting cucumberVersion)
JdocCucumberExtension extension = project.getExtensions()
.create("jdocCucumber", JdocCucumberExtension.class);
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
// Configure defaults (source dirs, output dir, etc.)
configureExtension(project, extension);
// Add Cucumber dependency automatically
project.getDependencies().addProvider(/* ... */);
// IMPORTANT: Register the task that generates .feature files
project.getTasks().register(GENERATE_FEATURES_TASK_NAME, JdocCucumberTask.class,
task -> configureCucumberTask(task, extension)); // Sets input/output dirs
// IMPORTANT: Register the task that runs the tests
project.getTasks().register(TEST_TASK_NAME, JavaExec.class,
task -> configureTestTask(task, extension)); // Sets up Cucumber CLI run
});
}
// Helper method to configure the generation task
private void configureCucumberTask(JdocCucumberTask task, JdocCucumberExtension extension) {
task.setGroup(TASK_GROUP); // Group task in ./gradlew tasks output
task.dependsOn(/* compileJava task */); // Ensure code is compiled first
task.getOutputDir().set(extension.getOutputDir()); // Tell task where to write files
task.getSources().set(extension.getSources()); // Tell task where to find Java files
// ... other settings ...
}
Explanation:
- The
apply
method is called by Gradle when the plugin is activated. - It uses
project.getTasks().register(...)
to tell Gradle about the new tasks (generateCucumberFeatures
,jdocCucumberTest
). - It links these tasks to specific Java classes (
JdocCucumberTask.java
,JavaExec
) that contain the logic for what the task does. - Helper methods like
configureCucumberTask
set up the task’s inputs (like source files) and outputs (like the generated features directory) and dependencies (dependsOn
).
This registration and configuration are how the plugin integrates the Javadoc testing process seamlessly into the Gradle build lifecycle.
Conclusion
You’ve now seen how jdoc-test
uses Gradle plugins (jdoc-spock-gradle-plugin
and jdoc-cucumber-gradle-plugin
) to act as a “foreman,” automating the entire process of turning your Javadoc tests into runnable specifications. By simply applying the plugin in your build.gradle
file, you get:
- Automatic discovery of Javadoc tests.
- Generation of
.groovy
(Spock) or.feature
(Cucumber) files. - Compilation of generated tests (for Spock).
- Integration with standard Gradle test execution tasks.
- Management of necessary testing framework dependencies.
This automation makes writing and running tests directly in your Javadocs incredibly convenient.
But how does jdoc-test
actually understand the tests written inside the /** ... */
comments? That’s the job of the parser. In the next chapter, we’ll dive into the details of the Javadoc Test Parser.
Generated by AI Codebase Knowledge Builder