Meta-annotations

The final part of this section is about the definition of meta-annotations. The JUnit Jupiter annotations can be used in the definition of other annotations (that is, can be used as meta-annotations). That means that we can define our own composed annotation that will automatically inherit the semantics of its meta-annotations. This feature is very convenient to create our custom test taxonomy by reusing the JUnit 5 annotation @Tag.

Let's see an example. Consider the following classification for test cases, in which we classify all tests as functional and non-functional, and then we make another level under the non-functional tests:

Example taxonomy for tests (functional and non-functional)

With that scheme in mind, we are going to create our custom meta-annotations for leaves of that tree structure: @Functional, @Security, @Usability, @Accessiblity, @Load, and @Stress. Notice that in each annotation we are using one or more @Tag annotations, depending on the structure previously defined. First, we can see the declaration of @Functional:

package io.github.bonigarcia;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("functional")
public @interface Functional {
}

Then, we define the annotation @Security with tags non-functional and security:

package io.github.bonigarcia;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("non-functional")
@Tag("security")
public @interface Security {
}

Similarly, we define the annotation @Load, but this time tagging with non-functional, performance, and load:

package io.github.bonigarcia;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("non-functional")
@Tag("performance")
@Tag("load")
public @interface Load {
}

Finally we create the annotation @Stress (with tags non-functional, performance, and stress):

package io.github.bonigarcia;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("non-functional")
@Tag("performance")
@Tag("stress")
public @interface Stress {
}

Now, we can use our annotations to tag (and later filter) tests. For instance, in the following example we are using the annotation @Functional at class level:

package io.github.bonigarcia;

import org.junit.jupiter.api.Test;

@Functional
class FunctionalTest {

@Test
void testOne() {
System.out.println("Test 1");
}

@Test
void testTwo() {
System.out.println("Test 2");
}

}

We can also out annotations at method level. In the following test, we annotate the different tests (methods) with different annotations (@Load, @Stress, @Security, and @Accessibility):

package io.github.bonigarcia;

import org.junit.jupiter.api.Test;

class NonFunctionalTest {

@Test
@Load
void testOne() {
System.out.println("Test 1");
}

@Test
@Stress
void testTwo() {
System.out.println("Test 2");
}

@Test
@Security
void testThree() {
System.out.println("Test 3");
}

@Test
@Usability
void testFour() {
System.out.println("Test 4");
}

}

All in all, we can filter the test by simply changing the included tags. On the one hand, we can filter by the tag functional. Notice that in this case, only two tests are executed. The following snippet shows the output of this kind of filtering using Maven:

Filtering test by tags (functional) using Maven and the command line

On the other hand, we can also filter with different tags, such as non-functional. The following picture shows an example of this type of filtering, this time using Gradle. As usual, we can play with these examples by forking the GitHub repository (https://github.com/bonigarcia/mastering-junit5):

>
Filtering test by tags (non-functional) using Gradle and the command line
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.162.49