[[test-engines]]
=== Test Engines

A `TestEngine` facilitates _discovery_ and _execution_ of tests for a particular
programming model.

For example, JUnit provides a `TestEngine` that discovers and executes tests written using
the JUnit Jupiter programming model (see <<writing-tests>> and <<extensions>>).

[[test-engines-junit]]
==== JUnit Test Engines

JUnit provides three `TestEngine` implementations.

* `{junit-jupiter-engine}`: The core of JUnit Jupiter.
* `{junit-vintage-engine}`: A thin layer on top of JUnit 4 to allow running _vintage_
  tests (based on JUnit 3.8 and JUnit 4) with the JUnit Platform launcher infrastructure.
* `{junit-platform-suite-engine}`: Executes declarative suites of tests with the JUnit
  Platform launcher infrastructure.

[[test-engines-custom]]
==== Custom Test Engines

You can contribute your own custom `{TestEngine}` by implementing the interfaces in the
{junit-platform-engine} module and _registering_ your engine.

Every `TestEngine` must provide its own _unique ID_, _discover_ tests from an
`EngineDiscoveryRequest`, and _execute_ those tests according to an `ExecutionRequest`.

[WARNING]
.The `junit-` unique ID prefix is reserved for TestEngines from the JUnit Team
====
The JUnit Platform `Launcher` enforces that only `TestEngine` implementations published
by the JUnit Team may use the `junit-` prefix for their `TestEngine` IDs.

* If any third-party `TestEngine` claims to be `junit-jupiter` or `junit-vintage`, an
  exception will be thrown, immediately halting execution of the JUnit Platform.
* If any third-party `TestEngine` uses the `junit-` prefix for its ID, a warning message
  will be logged. Later releases of the JUnit Platform will throw an exception for such
  violations.
====

In order to facilitate test discovery within IDEs and tools prior to launching the JUnit
Platform, `TestEngine` implementations are encouraged to make use of the `@Testable`
annotation. For example, the `@Test` and `@TestFactory` annotations in JUnit Jupiter are
meta-annotated with `@Testable`. Consult the Javadoc for `{Testable}` for further details.

If your custom `TestEngine` needs to be configured, consider allowing users to supply
configuration via <<running-tests-config-params,configuration parameters>>. Please note,
however, that you are strongly encouraged to use a unique prefix for all configuration
parameters supported by your test engine. Doing so will ensure that there are no conflicts
between the names of your configuration parameters and those from other test engines. In
addition, since configuration parameters may be supplied as JVM system properties, it is
wise to avoid conflicts with the names of other system properties. For example, JUnit
Jupiter uses `junit.jupiter.` as a prefix of all of its supported configuration
parameters. Furthermore, as with the warning above regarding the `junit-` prefix for
`TestEngine` IDs, you should not use `junit.` as a prefix for the names of your own
configuration parameters.

Although there is currently no official guide on how to implement a custom `TestEngine`,
you can consult the implementation of <<test-engines-junit>> or the implementation of
third-party test engines listed in the
https://github.com/junit-team/junit5/wiki/Third-party-Extensions#junit-platform-test-engines[JUnit 5 wiki].
You will also find various tutorials and blogs on the Internet that demonstrate how to
write a custom `TestEngine`.

NOTE: `{HierarchicalTestEngine}` is a convenient abstract base implementation of the
`TestEngine` SPI (used by the `{junit-jupiter-engine}`) that only requires implementors to
provide the logic for test discovery. It implements execution of `TestDescriptors` that
implement the `Node` interface, including support for parallel execution.

[[test-engines-registration]]
==== Registering a TestEngine

`TestEngine` registration is supported via Java's `{ServiceLoader}` mechanism.

For example, the `junit-jupiter-engine` module registers its
`org.junit.jupiter.engine.JupiterTestEngine` in a file named
`org.junit.platform.engine.TestEngine` within the `/META-INF/services` folder in the
`junit-jupiter-engine` JAR.
