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

Provided ability to handle package annotations (labels, links etc.) #1125

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@Repeatable(Epics.class)
@LabelAnnotation(name = EPIC_LABEL_NAME)
public @interface Epic {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Epics {

Epic[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@Repeatable(Features.class)
@LabelAnnotation(name = FEATURE_LABEL_NAME)
public @interface Feature {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Features {

Feature[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Flaky {
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@LinkAnnotation(type = ISSUE_LINK_TYPE)
@Repeatable(Issues.class)
public @interface Issue {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Issues {

Issue[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@LinkAnnotation
@Repeatable(Links.class)
public @interface Link {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Links {

Link[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Muted {
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@LabelAnnotation(name = OWNER_LABEL_NAME)
public @interface Owner {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Severity {

SeverityLevel value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface Stories {

Story[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@Repeatable(Stories.class)
@LabelAnnotation(name = STORY_LABEL_NAME)
public @interface Story {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
@LinkAnnotation(type = TMS_LINK_TYPE)
@Repeatable(TmsLinks.class)
public @interface TmsLink {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
public @interface TmsLinks {

TmsLink[] value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
Expand All @@ -39,7 +41,11 @@

import static io.qameta.allure.util.ResultsUtils.createLabel;
import static io.qameta.allure.util.ResultsUtils.createLink;
import static java.lang.String.join;
import static java.util.Arrays.asList;
import static java.util.Arrays.copyOfRange;
import static java.util.Arrays.stream;
import static java.util.Optional.ofNullable;

/**
* Collection of utils used by Allure integration to extract meta information from
Expand All @@ -64,7 +70,7 @@ private AnnotationUtils() {
* @return true if {@link io.qameta.allure.Flaky} annotation is present, false otherwise.
*/
public static boolean isFlaky(final AnnotatedElement annotatedElement) {
return annotatedElement.isAnnotationPresent(Flaky.class);
return isAnnotationPresent(annotatedElement, Flaky.class);
}

/**
Expand All @@ -74,7 +80,7 @@ public static boolean isFlaky(final AnnotatedElement annotatedElement) {
* @return true if {@link io.qameta.allure.Muted} annotation is present, false otherwise.
*/
public static boolean isMuted(final AnnotatedElement annotatedElement) {
return annotatedElement.isAnnotationPresent(Muted.class);
return isAnnotationPresent(annotatedElement, Muted.class);
}

/**
Expand All @@ -84,7 +90,7 @@ public static boolean isMuted(final AnnotatedElement annotatedElement) {
* @return discovered links.
*/
public static Set<Link> getLinks(final AnnotatedElement annotatedElement) {
return getLinks(annotatedElement.getAnnotations());
return getLinks(getAnnotationsFrom(annotatedElement));
}

/**
Expand Down Expand Up @@ -116,7 +122,7 @@ public static Set<Link> getLinks(final Collection<Annotation> annotations) {
* @return discovered labels.
*/
public static Set<Label> getLabels(final AnnotatedElement annotatedElement) {
return getLabels(annotatedElement.getAnnotations());
return getLabels(getAnnotationsFrom(annotatedElement));
}

/**
Expand All @@ -140,6 +146,29 @@ public static Set<Label> getLabels(final Collection<Annotation> annotations) {
.collect(Collectors.toSet());
}

private static <T extends Annotation> boolean isAnnotationPresent(final AnnotatedElement annotatedElement, Class<T> annotationClass) {
boolean isPresent = annotatedElement.isAnnotationPresent(annotationClass);
if (!isPresent && annotatedElement instanceof Class<?>) {
Annotation[] packageAnnotations = PackageUtil.getPackageAnnotations((Class<?>) annotatedElement);
return stream(packageAnnotations).anyMatch(a -> a.annotationType().equals(annotationClass));
}

return isPresent;
}

private static Annotation[] getAnnotationsFrom(AnnotatedElement annotatedElement) {
Annotation[] result = annotatedElement.getAnnotations();
if (annotatedElement instanceof Class<?>) {
Annotation[] packageAnnotations = PackageUtil.getPackageAnnotations((Class<?>) annotatedElement);
List<Annotation> annotationList = new ArrayList<>(asList(result));
List<Annotation> packageAnnotationList = new ArrayList<>(asList(packageAnnotations));
annotationList.addAll(packageAnnotationList);
result = annotationList.toArray(new Annotation[]{});
}

return result;
}

private static <T, U extends Annotation> Stream<T> extractMetaAnnotations(
final Class<U> annotationType,
final BiFunction<U, Annotation, Stream<T>> mapper,
Expand Down Expand Up @@ -262,4 +291,41 @@ private static boolean isInJavaLangAnnotationPackage(final Class<? extends Annot
return annotationType != null && annotationType.getName().startsWith("java.lang.annotation");
}

/**
* Extracts annotations from packages hierarchically by given classes
*
* @author TikhomirovSergey (Sergey Tikhomirov).
*/
static class PackageUtil {

static Annotation[] getPackageAnnotations(Class<?> clz) {
Objects.requireNonNull(clz, "Class should not be a null value");
return getPackageAnnotations(clz.getPackage().getName());
}

static Annotation[] getPackageAnnotations(String packageName) {
Objects.requireNonNull(packageName, "Package name should not be a null value");

//the code below would look better if allure supported Java from 9 and higher versions
Class<?> packInfo;
try {
packInfo = Class.forName(packageName + ".package-info", false, PackageUtil.class.getClassLoader());
} catch (ClassNotFoundException e) {
packInfo = null;
}

Annotation[] annotations = ofNullable(packInfo).map(clazz -> clazz.getPackage().getAnnotations()).orElse(new Annotation[]{});
String[] pathElements = packageName.split("[.]");
if (pathElements.length == 1) {
return annotations;
}

Annotation[] upperPackageAnnotations = getPackageAnnotations(join(".", copyOfRange(pathElements, 0, pathElements.length - 1)));
List<Annotation> annotationList = new ArrayList<>(asList(annotations));
List<Annotation> result = new ArrayList<>(asList(upperPackageAnnotations));
result.addAll(annotationList);
return result.toArray(new Annotation[] {});
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.qameta.allure.annotatedpack;

import io.qameta.allure.Flaky;
import io.qameta.allure.Muted;

@Muted
@Flaky
public class MutedAndFlakyTest {

@Muted
@Flaky
public void mutedAndFlakyMethod() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.qameta.allure.annotatedpack;

public class NotMutedAndFlakyTest {

public void notMutedAndFlakyMethod() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.qameta.allure.annotatedpack.muted.and.flaky;

public class MutedAndFlakyByPackageTest {

public void notMutedAndFlakyMethod() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@Muted
@Flaky
package io.qameta.allure.annotatedpack.muted.and.flaky;

import io.qameta.allure.Flaky;
import io.qameta.allure.Muted;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@Epic("High level epic")
@Link("General link")
package io.qameta.allure.annotatedpack;

import io.qameta.allure.Epic;
import io.qameta.allure.Link;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.qameta.allure.annotatedpack.subpack.innerpack;

import io.qameta.allure.Story;

@Story("Marked pack story")
public class SomeTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@Feature("Some general feature")
@Link("Some second level link")
package io.qameta.allure.annotatedpack.subpack;

import io.qameta.allure.Feature;
import io.qameta.allure.Link;
Loading
Loading