apache/seatunnel

[Improve][E2E] Make SeaTunnelContainer reusable across test classes to speed up E2E tests

Open

#10784 opened on Apr 17, 2026

View on GitHub
 (2 comments) (0 reactions) (1 assignee)Java (6,897 stars) (1,432 forks)batch import
Testhelp wantedimprove

Description

Search before asking

  • I had searched in the issues and found no similar feature requirement.

Background

E2E tests in SeaTunnel are slow. A significant portion of the overhead comes from the fact that each test class creates and destroys its own SeaTunnelContainer via ContainerTestingExtension.beforeAll/afterAll.

The full startup sequence runs for every single test class:

ContainerTestingExtension.beforeAll()
  → SeaTunnelContainer.startUp()
    → new GenericContainer(...).start()          // Docker cold start: 30–60s
    → waitForLogMessage("received new worker register")  // Hazelcast cluster ready
    → copyAllConnectorJarToContainer(...)         // copy connector JARs into container

On teardown:

ContainerTestingExtension.afterAll()
  → SeaTunnelContainer.tearDown()
    → server.close()                             // container destroyed

This means a test suite with 20 test classes pays the 30–60s Docker startup cost 20 times.

Proposed Solution

Introduce a singleton/reusable SeaTunnelContainer that is started once per JVM and shared across all test classes, similar to the Testcontainers Singleton Pattern.

Key changes required:

1. Singleton container lifecycle

Move SeaTunnelContainer to a static singleton with a JVM shutdown hook instead of per-class beforeAll/afterAll:

class SharedSeaTunnelContainer {
    static final SeaTunnelContainer INSTANCE;
    static {
        INSTANCE = new SeaTunnelContainer();
        INSTANCE.startUp();
        Runtime.getRuntime().addShutdownHook(new Thread(() -> INSTANCE.tearDown()));
    }
}

2. Connector JAR pre-loading

Currently each test class copies only the connector JARs it needs. With a shared container, all required connectors must be copied once at startup (or support hot-copy to the container's connectors directory without restart, since Zeta supports dynamic connector loading).

3. Cleanup between test classes

tearDown currently deletes the volume and destroys the container. For a shared container, cleanup should only remove per-job artifacts (e.g., volume files written by a specific job), not destroy the container itself.

4. Adapt ContainerTestingExtension

Change the extension to inject the shared container instance instead of creating a new one in beforeAll.

Key Files

File Change needed
SeaTunnelContainer.java Add singleton pattern, fix tearDown to not destroy container
ContainerTestingExtension.java Inject shared container instead of creating per-class
TestSuiteBase.java No change expected

Expected Impact

  • Before: N test classes × ~45s Docker startup = N × 45s overhead
  • After: 1 startup × ~45s + N × ~0s (container already running)
  • For a module with 20 test classes: ~15 minutes saved per CI run

Non-goals

  • This issue does not cover Embedded Zeta or in-process execution
  • Streaming/checkpoint E2E tests are still expected to run against the shared container (no scope reduction)
  • This does not affect connector-specific external system containers (MySQL, Kafka, etc.), which remain per-class

Acceptance Criteria

  • SeaTunnelContainer can be started once and reused across multiple test classes
  • Connector JARs are loaded at container startup (not per test class)
  • Per-job artifacts are cleaned up between test classes without container restart
  • Existing E2E tests pass without modification to individual test classes
  • CI wall-clock time for at least one E2E module is measurably reduced

Are you willing to submit a PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Contributor guide