Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testcontainers for Java: Add showcase examples for different scenarios #54

Merged
merged 7 commits into from
Apr 14, 2023
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
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ updates:
package-ecosystem: "bundler"
schedule:
interval: "monthly"

- directory: "/testing/testcontainers/java"
package-ecosystem: "gradle"
schedule:
interval: "monthly"
47 changes: 47 additions & 0 deletions .github/workflows/testcontainers-java.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Testcontainers for Java
on:

pull_request:
branches: [ main ]
paths:
- '.github/workflows/testcontainers-java.yml'
- 'testing/testcontainers/java/**'
push:
branches: [ main ]
paths:
- '.github/workflows/testcontainers-java.yml'
- 'testing/testcontainers/java/**'

# Allow job to be triggered manually.
workflow_dispatch:

# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}

jobs:
test:
name: "CrateDB: ${{ matrix.cratedb-version }}
on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ "ubuntu-latest" ]

steps:

- name: Acquire sources
uses: actions/checkout@v3

- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: "17"
cache: "gradle"

- name: Run software tests
run: |
cd testing/testcontainers/java
./gradlew check
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ Layout
CrateDB is part of a larger software stack. Those resources may also be used
within "reference architecture" types of documentation.

- The ``testing`` folder contains reference implementations about how to use
different kinds of test layers for testing your applications with CrateDB.


.. _CrateDB: https://github.com/crate/crate
8 changes: 8 additions & 0 deletions testing/testcontainers/java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.gradle/
.idea
*.iws
*.iml
*.ipr
build/
out/
target/
1 change: 1 addition & 0 deletions testing/testcontainers/java/.java-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17
89 changes: 89 additions & 0 deletions testing/testcontainers/java/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#######################
Testcontainers for Java
#######################

*How to run integration tests of Java applications with CrateDB.*


*****
About
*****

Introduction
============

`Testcontainers for Java`_ is a Java library that supports JUnit tests,
providing lightweight, throwaway instances of common databases suitable
for integration testing scenarios.

The `Testcontainers CrateDB Module`_ will provide your application test
framework with a single-node `CrateDB`_ instance. You will be able to choose
the `CrateDB OCI image`_ variant by version, or by selecting the ``nightly``
release.

What's inside
=============

This directory includes different canonical examples how to use those
components within test harnesses of custom applications using `CrateDB`_.
Currently, all test cases are based on JUnit 4. This is an enumeration
of examples you can explore here:

- ``TestClassScope``: Class-scoped testcontainer instance with JUnit 4 @Rule/@ClassRule integration.
- ``TestFunctionScope``: Function-scoped testcontainer instance with JUnit 4 @Rule/@ClassRule integration.
- ``TestJdbcUrlScheme``: Database containers launched via Testcontainers "TC" JDBC URL scheme.
- ``TestManual``: Function-scoped testcontainer instance with manual setup/teardown.
- ``TestManualWithLegacyCrateJdbcDriver``:
Function-scoped testcontainer instance with manual setup/teardown, using a custom
``CrateDBContainer``, which uses the `legacy CrateDB JDBC driver`_.
- ``TestSharedSingleton`` [1]:
Testcontainer instance shared across multiple test classes, implemented using the Singleton pattern.
- ``TestSharedSingletonEnvironmentVersion``:
Testcontainer instance honoring the ``CRATEDB_VERSION`` environment variable, suitable
for running a test matrix on different versions of CrateDB, shared across multiple test
classes.

[1]: Sometimes, it might be useful to define a container that is only started once for
several test classes. There is no special support for this use case provided by
the Testcontainers extension. Instead, this can be implemented using the Singleton
pattern. See also `Testcontainers » Manual container lifecycle control » Singleton
containers`_.


*****
Usage
*****

1. Make sure Java 17 is installed.
amotl marked this conversation as resolved.
Show resolved Hide resolved
2. Invoke software tests, using `Testcontainers for Java`_. It should work out
of the box::

# Run all tests.
./gradlew test

# Run individual tests.
./gradlew test --tests TestFunctionScope

# Run test case showing how to select CrateDB version per environment variable.
export CRATEDB_VERSION=5.2.3
export CRATEDB_VERSION=nightly
./gradlew test --tests TestSharedSingletonMatrix

3. Invoke example application::

# Start CrateDB.
docker run -it --rm --publish=4200:4200 --publish=5432:5432 \
crate:latest -Cdiscovery.type=single-node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did I miss something or the discovery-type option is not passed to the JdbcDatabaseContainer ?

Copy link
Member Author

@amotl amotl Apr 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bringing this up.

In this particular case, outlining basic examples only, CrateDB will also happily start without any options, right? So it would be acceptable to omit the -Cdiscovery.type=single-node option?

However, propagating command-line options to CrateDB will become important when aiming to use this in a multi-node scenario like what crate-java-testing provides per CrateTestCluster 1, right? Did you already take this into account, @matriv, or would this be up to a second iteration?

Footnotes

  1. See also https://github.com/crate/crate-jdbc/issues/377.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I haven't tried testcontainers in multi-node setup, don't even know if that's supported by their existing infrastructure.
  2. This test, doesn't have to do with testcontainers, the script starts a docker container manually and then runs the tests, connecting to the bound port of the container.

Copy link
Contributor

@hlcianfagna hlcianfagna Apr 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CrateDB will also happily start without any options, right?

That is correct, it goes ahead with a "best-effort cluster bootstrapping" and it works.


# Run example program, using both the CrateDB legacy
# JDBC driver, and the vanilla PostgreSQL JDBC driver.
./gradlew run --args="jdbc:crate://localhost:5432/"
./gradlew run --args="jdbc:postgresql://localhost:5432/"


.. _CrateDB: https://github.com/crate/crate
.. _CrateDB OCI image: https://hub.docker.com/_/crate
.. _legacy CrateDB JDBC driver: https://crate.io/docs/jdbc/
.. _Testcontainers for Java: https://github.com/testcontainers/testcontainers-java
.. _Testcontainers CrateDB Module: https://www.testcontainers.org/modules/databases/cratedb/
.. _Testcontainers » Manual container lifecycle control » Singleton containers: https://www.testcontainers.org/test_framework_integration/manual_lifecycle_control/#singleton-containers
67 changes: 67 additions & 0 deletions testing/testcontainers/java/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* An example application for demonstrating "Testcontainers for Java" with CrateDB and the PostgreSQL JDBC driver.
*/

buildscript {
repositories {
mavenCentral()
}
}

plugins {
id 'application'
amotl marked this conversation as resolved.
Show resolved Hide resolved
id 'idea'
id 'java'
amotl marked this conversation as resolved.
Show resolved Hide resolved
}

repositories {
mavenCentral()
mavenLocal()
}

dependencies {
implementation 'org.postgresql:postgresql:42.6.0'
implementation 'io.crate:crate-jdbc:2.6.0'
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation 'org.slf4j:slf4j-simple:2.0.7'
testImplementation 'junit:junit:4.13.2'
testImplementation "org.assertj:assertj-core:3.23.1"
testImplementation 'org.testcontainers:testcontainers:1.18.0'
testImplementation 'org.testcontainers:cratedb:1.18.0'
testImplementation 'org.testcontainers:postgresql:1.18.0'
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

jar {
archiveBaseName = 'cratedb-example-testcontainers-java'
archiveVersion = '0.0.1-SNAPSHOT'
}

sourceSets {
main {
java.srcDirs += [
"src/generated/java",
"src/main/java",
]
}
}

test {
dependsOn 'cleanTest'
}

application {
mainClass = 'io.crate.example.testing.Application'
}

ext.javaMainClass = "io.crate.example.testing.Application"


idea.module.inheritOutputDirs = true
processResources.destinationDir = compileJava.destinationDir
compileJava.dependsOn processResources
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading