Skip to content

Facilitate discovery of test cases for platform clients using sources only #504

@mmerdes

Description

@mmerdes

Motivation

Some clients of the JUnit 5 platform, notably IDEs such as IntellilJ IDEA operate only on sources
for their test detection. Thus, they cannot use the full discovery mechanism of the JUnit platform as the latter relies on compiled classes.

Therefore a mechanism is needed to detect test cases by analyzing the source code only.

In this context, a test case is anything a particular test engine would like to execute as a test. For the JUnit Jupiter Engine this includes test and test factory methods. Knowing about test cases early before compilation is important to interactive platform clients such as IDEs as it can vastly improve the user experience by providing test running means within the source code and in context menus.

Precondition

It is assumed that said interactive platform clients possess a means to find meta-annotations in non-compiled source code. This must obviously include the ability to detect meta-meta-annotations etc.

Proposal

Introduce an annotation such as @Testable that all engines can use to denote which types or methods are "testable". As this notion of being testable solely depends on the interpretation of a (custom) engine the IDE cannot deduce this testability in general for all possible engines.

Such a @Testable annotation will then be used to meta-annotate the engine's 'normal' test annotation(s). Thus this approach does not put an additional burden on test authors as they can still use the familiar test annotations. An IDE however can analyze all meta-annotations of the standard test annotations to find the test cases without being required to have any intimate knowledge of a particular test engine's annotations.

For the JUnit Jupiter engine such normal test annotations making use of @Testable would be @Test, @TestFactory, and the planned @Step.

According to this proposal the @Test annotation, for example, would be meta-annotated in the following way:

@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(Stable)
@Testable
public @interface Test {
}

Note that this approach would also be feasible for inheritance based test engines. These engines could put the @Testable annotation on their respective base classes.

Requirements

  • If a class (including static nested classes or inner classes) is not meta-annotated with @Testable but contains a method that is meta-annotated with @Testable, the class must be considered to be a "testable" class.
  • If annotation hierarchies (containing @Testable) are present in compiled byte code in JARs in the user's classpath, IDEs must also take such annotation hierarchies into consideration when used in conjunction with annotation processing for not-yet-compiled source code.

Limitations

This approach would not work for test engines unwilling or unable to use annotations at all. Examples include non-JVM languages or file formats such as XML or engines relying on naming conventions only, such as the JUnit 3 naming convention.

Restrictions for TestEngine Implementations

A TestEngine must not in any way perform discovery based on the presence of @Testable. In terms of discovery, the presence of @Testable should only be meaningful to clients such as IDEs. TestEngine implementations will therefore be required to discover tests based on information specific to that test engine (e.g., annotations specific to that test engine).

Open Questions

  • If a class is annotated or meta-annotated with @Testable but contains methods that are not annotated or meta-annotated with @Testable but should be considered test methods (e.g. some TestNG-like use cases), will IntelliJ consider the methods to be "testable"?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions