This plugin embraces Contract-Based Testing as a first-class paradigm. The contract defines the expected behavior of your service — and tests should derive from it automatically.
| Contract Type | Status | Description |
|---|---|---|
| OpenAPI / Swagger | ✅ Stable | REST API specifications (YAML/JSON) |
| gRPC Protobuf | 🔜 Planned | Protocol Buffer service definitions |
| Java Interface | 🔜 Planned | Java class/interface contracts |
| GraphQL Schema | 🔜 Future | GraphQL type definitions |
The plugin is architected to be extensible — adding a new contract type requires implementing a new parser and prompt template.
- Contract-First Testing — Tests are generated from the contract, not the implementation
- Multi-Framework Support — JUnit 5 + Rest Assured or Karate DSL
- AI-Powered — Leverages any OpenAI-compatible LLM endpoint
- Comprehensive Coverage — Generates happy path + negative test cases
- IDE Integration — Seamless notification banner on contract files
┌─────────────────────────────────────────────────────────────┐
│ CONTRACT │
│ (OpenAPI / Protobuf / ...) │
│ ⭐ SOURCE OF TRUTH │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AI Test Generator Plugin │
│ (context-aware prompt engineering) │
└─────────────────────┬───────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ TESTS │
│ Rest Assured / Karate / JUnit / Spock ... │
└─────────────────────────────────────────────────────────────┘
The contract is:
- Single source of truth — No duplication between spec and tests
- Version-controlled — Contract changes trigger test regeneration
- Language-agnostic — Works with any test framework
ai-test-plugin/
├── core/ # Contract-agnostic core
│ ├── GenerationRequest.kt
│ ├── PromptBuilder.kt # LLM prompt construction
│ └── Framework.kt # Test framework abstractions
├── llm-client/ # OpenAI-compatible LLM client
│ └── OpenAiCompatibleProvider.kt
└── plugin-idea/ # IntelliJ IDEA plugin
├── GenerateTestsDialog.kt # UI configuration
├── GenerateTestsService.kt # Test generation orchestration
└── contracts/ # Contract type handlers
└── openapi/ # OpenAPI parser & heuristics
- Open IntelliJ IDEA 2025.2+
- Go to Settings → Plugins
- Search for "AI Test Generator"
- Install and restart IDE
Download the latest release from GitHub Releases and install via Settings → Plugins → Install Plugin from Disk.
Create or edit ai-test-config.yaml in your project root:
llm:
endpoint: "https://api.openai.com/v1/chat/completions"
apiKey: "${OPENAI_API_KEY}"
model: "gpt-4o"
generation:
defaultFramework: "restassured"
defaultClassName: "ApiTest"
defaultBaseUrl: "http://localhost:8080"
defaults:
restassured:
packageName: "com.example.tests"
location: "src/test/java"
karate:
location: "src/test/kotlin"OPENAI_API_KEY- Your OpenAI API key (or any OpenAI-compatible provider)- Use
${ENV_VAR}syntax in config for secrets
- Open any contract file (
.yaml,.jsonfor OpenAPI) - A notification banner appears: "Generate Tests?"
- Click to open the generation dialog
- Configure:
- Framework - JUnit 5 + Rest Assured or Karate DSL
- Location - Output directory
- Class Name - Test class/feature name
- Base URL - Optional API base URL hint
- Extra Instructions - Additional context for the LLM
- Click Generate
The plugin analyzes the contract and generates:
- Happy path tests for each operation/endpoint
- Negative tests for missing required fields
- Boundary/type validation tests
package com.example.tests;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.*;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class UserApiTest {
@BeforeAll
public static void setup() {
RestAssured.baseURI = "http://localhost:8080";
}
@Test
void getUser_Success() {
given()
.pathParam("id", 1)
.when()
.get("/users/{id}")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("id", equalTo(1))
.body("name", notNullValue());
}
@Test
void getUser_NotFound() {
given()
.pathParam("id", 99999)
.when()
.get("/users/{id}")
.then()
.statusCode(404);
}
}Feature: User API Contract Tests
Background:
* url baseUrl || 'http://localhost:8080'
Scenario: Get user - success
Given path 'users', 1
When method get
Then status 200
And match response == { id: 1, name: '#notnull', email: '#regex[.*@.*]' }
Scenario: Get user - not found
Given path 'users', 99999
When method get
Then status 404
And match response == { code: '#notnull', message: '#string' }- IntelliJ IDEA 2025.2+ (for development)
- JDK 17+
- Gradle 9.x
# Build the plugin JAR
./gradlew :plugin-idea:buildPlugin
# Build with ZIP distribution
./gradlew :plugin-idea:assemble
# Run in development IDE
./gradlew :plugin-idea:runIdeIf your corporate network only allows access to Maven Central, configure the build like this:
./gradlew :plugin-idea:buildPlugin \
-PrestrictedNetworkMode=true \
-PlocalRepositoryPaths=/opt/build/m2,/opt/build/jetbrains-mirror \
-PintellijPlatformLocalPath=/opt/idea/idea-IU-252.27397.103restrictedNetworkMode=truedisables non-Central remote repositories such as Gradle Plugin Portal, Spring plugin repo, and JetBrains IntelliJ repositories.localRepositoryPathsis a comma-separated list of local Maven repository directories that contain pre-downloaded plugin and JetBrains artifacts.intellijPlatformLocalPathpoints to a local IntelliJ IDEA installation or unpacked distribution sorunIdeandbuildPlugindo not need to download the IDE.
You can also place the same values in gradle.properties or provide them with environment variables:
RESTRICTED_NETWORK_MODELOCAL_REPOSITORY_PATHSINTELLIJ_PLATFORM_LOCAL_PATH
# Publish all configured publications to Maven Local
./gradlew publishToMavenLocal
# Publish all configured publications to Maven Central via Sonatype's
# OSSRH Staging API compatibility service
./gradlew publishAllPublicationsToSonatypeRepository closeAndReleaseSonatypeStagingRepositoryMaven Central publishing now goes through Sonatype Central Portal. Legacy OSSRH was retired on June 30, 2025, but Gradle builds can still publish through Sonatype's OSSRH Staging API compatibility endpoint, which this project already uses.
Before releasing, configure these environment variables:
OSSRH_USERNAMEandOSSRH_PASSWORD: Sonatype Central Portal publishing token credentialsSIGNING_KEY_FILE: path to the ASCII-armored PGP private key used to sign artifactsSIGNING_KEY_PASSWORD: password for the signing key
Recommended release flow:
# 1. Verify all publications locally, including generated artifacts such as sources JARs
./gradlew publishToMavenLocal
# 2. Publish and release to Maven Central
./gradlew publishAllPublicationsToSonatypeRepository closeAndReleaseSonatypeStagingRepositoryRoot module source JAR:
- The root Gradle module publishes under
org.openprojectx.ai.plugin:ai-test-plugin-root. - That root publication includes a custom
sourcesJarartifact that packages all Git-tracked files in the repository. - Run
./gradlew :sourcesJarto build that archive directly. - When you run
publishToMavenLocalorpublishAllPublicationsToSonatypeRepository, thatsourcesJaris included in the root module publication.
Notes:
publishToMavenLocalis the fastest way to verify the generated.pom, signatures, and-sources.jarbefore a Central release.:plugin-idea:publishPluginDistributionPublicationToSonatypeRepositorypublishes only the IntelliJ plugin distribution publication.publishAllPublicationsToSonatypeRepositorypublishes both the root module publication and theplugin-ideapublication.
- gRPC Protobuf support — Generate tests from
.protofiles - Java Interface contracts — Generate tests from annotated interfaces
- Contract diff detection — Alert when contract changes affect existing tests
- Test regeneration — Smart update instead of full overwrite
Contributions are welcome! Key areas:
- New contract type parsers (gRPC, GraphQL, Java)
- Additional test framework generators (Spock, TestNG)
- LLM prompt optimization
Licensed under the Apache License 2.0 - see LICENSE for details.
Built with ❤️ for the contract-driven testing community
