Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions .agents/skills/writing-tests/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
---
name: writing-tests
description: >
Testing patterns for Vert.x SQL Client: test frameworks, async testing,
test locations, and how to run tests.
---

# Writing Tests

Vert.x SQL Client uses JUnit 4 with Vert.x-specific test utilities. Tests and documentation are mandatory for contributions.

## Test Framework

- **JUnit 4** (version 4.13.1) - Standard test framework
- **VertxUnitRunner** - JUnit 4 runner for async tests
- **TestContext** - Async test utility for handling asynchronous operations
- **Docker** - Required for integration tests (database containers)

## Test Annotations and Extensions

### Standard Test Patterns

#### Pattern 1: Using Async with Simple Callback

```java
@RunWith(VertxUnitRunner.class)
public class MyTest {

@Test
public void testWithAsync(TestContext ctx) {
Async async = ctx.async();
Comment thread
tsegismont marked this conversation as resolved.
vertx.runOnContext(v -> async.complete());
}
}
```

#### Pattern 2: Using asyncAssertSuccess Directly

When using `asyncAssertSuccess`, do not call `async.complete()` as it creates an async internally:

```java
@RunWith(VertxUnitRunner.class)
public class MyTest {

@Test
public void testAsyncAssertSuccess(TestContext ctx) {
client.query("SELECT 1")
.execute()
.onComplete(ctx.asyncAssertSuccess(result -> {
ctx.assertEquals(1, result.size());
}));
}
}
```

#### Pattern 3: Using asyncAssertSuccess from runOnContext

When calling `asyncAssertSuccess` from `runOnContext`, you need an explicit async:

```java
@RunWith(VertxUnitRunner.class)
public class MyTest {

@Test
public void testAsyncAssertSuccessFromRunOnContext(TestContext ctx) {
Async async = ctx.async();
vertx.runOnContext(v -> {
client.query("SELECT 1")
.execute()
.onComplete(ctx.asyncAssertSuccess(result -> {
ctx.assertEquals(1, result.size());
async.complete();
}));
});
}
}
```

## Test Location

- **Unit tests**: Same module as code under test, in `src/test/java/`
- **Integration tests**: May be in separate test modules or `src/test/java/`
- **Database-specific tests**: In respective client module
- PostgreSQL: `vertx-pg-client/src/test/`
- MySQL: `vertx-mysql-client/src/test/`
- MSSQL: `vertx-mssql-client/src/test/`
- DB2: `vertx-db2-client/src/test/`
- Oracle: `vertx-oracle-client/src/test/`

## Test Data Setup

### Using SQL Scripts

Place initialization scripts in `src/test/resources/`:

```sql
-- init.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);

INSERT INTO users (name) VALUES ('Alice'), ('Bob');
```

### Programmatic Setup

```java
@Before
public void setUp(TestContext ctx) {
Async async = ctx.async();
client.query("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name VARCHAR(100))")
.execute()
.compose(v -> client.query("INSERT INTO users (name) VALUES ('Alice'), ('Bob')").execute())
.onComplete(ctx.asyncAssertSuccess(v -> async.complete()));
}

@After
public void tearDown(TestContext ctx) {
Async async = ctx.async();
client.query("DROP TABLE IF EXISTS users")
.execute()
.onComplete(ctx.asyncAssertSuccess(v -> async.complete()));
}
```

Prefer temporary tables when testing databases that support it (automatically dropped when the connection is closed).

## Test Requirements

- **All new features must include tests**
- **Integration tests must clean up resources** (connections, containers)

## Assertions

### TestContext Assertions (JUnit 4 style)

```java
ctx.assertEquals(expected, actual);
ctx.assertTrue(condition);
ctx.assertFalse(condition);
ctx.assertNull(value);
ctx.assertNotNull(value);
```

## Common Pitfalls

1. **Forgetting to complete async tests** - Always call `async.complete()`
194 changes: 194 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Agent Guidelines - vertx-sql-client

Instructions for AI coding agents working in this repository.
Checkout relevant `.agents/skills/` to accomplish specific tasks.

## Build & Verify Commands

```bash
mvn test-compile # compile code and tests
mvn test # run all tests (requires Docker for database interactions)
mvn spotless:check # verify formatting
mvn spotless:apply # auto-fix formatting
```

## Project Structure

This is a multi-module Maven project with the following key modules:

- **vertx-sql-client**: Core SQL client API and base implementations
- **vertx-sql-client-codec**: Shared codec utilities for data type encoding/decoding
- **vertx-sql-client-templates**: SQL template support for type-safe queries
- **vertx-pg-client**: PostgreSQL-specific client implementation
- **vertx-mysql-client**: MySQL/MariaDB-specific client implementation
- **vertx-mssql-client**: Microsoft SQL Server client implementation
- **vertx-db2-client**: IBM DB2 client implementation
- **vertx-oracle-client**: Oracle Database client implementation

### Module Layout Pattern

Each database-specific client follows this structure:
- `src/main/java/`: Public API interfaces and implementation classes
- Top package (e.g., `io.vertx.pgclient`): Public API interfaces
- `impl/` subpackage: Implementation classes (not exported)
- `src/main/asciidoc/`: Module-specific documentation
- `src/test/java/`: Unit and integration tests
- `module-info.java`: Defines module exports and dependencies

## General Coding Rules

These rules apply when **writing or modifying code**. Code review is the checkpoint where compliance is verified.

### Logging

In production code, use the Vert.x internal logger, never SLF4J, Log4j, or `java.util.logging` directly.

```java
import io.vertx.core.internal.logging.Logger;
import io.vertx.core.internal.logging.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
```

Vert.x internal logging API doesn't support parameters placeholders.
Check the active level before debug or trace logging.

```java
if (logger.isDebugEnabled()) {
logger.debug("Prepared parameters: " + paramDesc);
}
```

### Async Patterns

Use Vert.x `Future<T>` and `Promise<T>` throughout. Do not use raw callbacks or `CompletableFuture` in production code.

### API Design

- Public contracts are interfaces in the top package (`io.vertx.sqlclient`, `io.vertx.pgclient`, …)
- Implementations go in `impl/` subpackages
- Annotate public API interfaces and methods with `@VertxGen` for code-generation support
- Expose construction via static factory methods, not constructors

### Module Boundaries

`module-info.java` governs exports.
Internal packages are exported only to their corresponding test modules, do not widen exports without discussion.
Test module descriptors (`src/test/java/module-info.java`) can be modified freely, e.g. to add a `requires` for a new dependency used in tests.

### Copyright Header

New Java files must include the dual-license header matching existing files:

```java
/*
* Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
```

The range is always `2011-[current year]`.

## Testing Guidelines

For comprehensive testing patterns and examples, see `.agents/skills/writing-tests/SKILL.md`.

### Test Framework

- Use **JUnit 4** (version 4.13.1) for all tests
- Async tests use **VertxUnitRunner** (JUnit 4 runner) and **TestContext**
- Integration tests require **Docker** for database containers

### Test Patterns

```java
@RunWith(VertxUnitRunner.class)
public class MyTest {

@Test
public void testAsyncOperation(TestContext ctx) {
Async async = ctx.async();
client.query("SELECT 1")
.execute()
.onComplete(ctx.asyncAssertSuccess(result -> {
ctx.assertEquals(1, result.size());
async.complete();
}));
}
}
```

### Test Location

- **Unit tests**: Same module as code under test, in `src/test/java/`
- **Integration tests**: May be in separate test modules or `src/test/java/`
- **Database-specific tests**: In respective client module (e.g., `vertx-pg-client/src/test/`)

### Running Tests

```bash
mvn test # Run all tests (requires Docker)
mvn test -Dtest=MyTest # Run specific test class
mvn test -Dtest=MyTest#testMethod # Run specific test method

# When your change spans modules (e.g. modifying vertx-sql-client-codec and
# testing in vertx-pg-client), use -am to rebuild dependencies:
mvn test -pl vertx-pg-client -am -Dtest=MyTest
```

### Test Requirements

- All new features must include tests
- Database tests must clean up resources (connections, containers)

## Development Workflow

### Incremental Development

When making changes:
1. Compile frequently: `mvn compile -pl <module>`
2. Run affected tests: `mvn test -pl <module>`
3. Verify formatting: `mvn spotless:check`
4. Run full build before PR: `mvn clean install`

### Build Optimization

```bash
# Skip tests during development
mvn compile -DskipTests

# Build specific module and dependencies
mvn install -pl vertx-pg-client -am
```

## Specialized Skills

When performing specific tasks, read the relevant skill file for detailed guidance:

- **Writing tests** - Read `.agents/skills/writing-tests/SKILL.md` when creating or modifying tests

## Contribution Process

- All commits must be signed off: `git commit -s` (DCO)
- Commit messages should end with: `Assisted-by: [Provider] [Model-Family] ([Version/ID])` (replace placeholders)
- Contributors must have signed the [Eclipse Contributor Agreement (ECA)](https://www.eclipse.org/legal/ECA.php)

See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contribution workflow.

## Code Review Guidelines

### Verify

- General coding rules above are followed
- Test coverage is present; async tests use `VertxUnitRunner` and `TestContext`
- No breaking changes to public interfaces without prior discussion

### Do Not Comment On

- Patterns already used consistently throughout the codebase
9 changes: 9 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@AGENTS.md

# Agent Guidelines - vertx-sql-client

## Specialized Skills

When performing specific tasks, read the relevant skill file for detailed guidance:

- **Writing tests** - Read `.agents/skills/writing-tests/SKILL.md` when creating or modifying tests