Skip to content

Commit 70c5fd7

Browse files
TikhomirovSergeys.tikhomirov
authored and
s.tikhomirov
committed
- provided ability to handle package annotations
- add package target to Epic(s), Feature(s), Flaky, Issue(s), Link(s), Muted, Owner, Severity, Story(es), TmsLink(s)
1 parent 3d361dd commit 70c5fd7

25 files changed

+195
-22
lines changed

allure-java-commons/src/main/java/io/qameta/allure/Epic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@Documented
3232
@Inherited
3333
@Retention(RetentionPolicy.RUNTIME)
34-
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3535
@Repeatable(Epics.class)
3636
@LabelAnnotation(name = EPIC_LABEL_NAME)
3737
public @interface Epic {

allure-java-commons/src/main/java/io/qameta/allure/Epics.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Epics {
3333

3434
Epic[] value();

allure-java-commons/src/main/java/io/qameta/allure/Feature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@Documented
3232
@Inherited
3333
@Retention(RetentionPolicy.RUNTIME)
34-
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3535
@Repeatable(Features.class)
3636
@LabelAnnotation(name = FEATURE_LABEL_NAME)
3737
public @interface Feature {

allure-java-commons/src/main/java/io/qameta/allure/Features.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Features {
3333

3434
Feature[] value();

allure-java-commons/src/main/java/io/qameta/allure/Flaky.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Flaky {
3333
}

allure-java-commons/src/main/java/io/qameta/allure/Issue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@Documented
3232
@Inherited
3333
@Retention(RetentionPolicy.RUNTIME)
34-
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3535
@LinkAnnotation(type = ISSUE_LINK_TYPE)
3636
@Repeatable(Issues.class)
3737
public @interface Issue {

allure-java-commons/src/main/java/io/qameta/allure/Issues.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Issues {
3333

3434
Issue[] value();

allure-java-commons/src/main/java/io/qameta/allure/Link.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
@Documented
3838
@Inherited
3939
@Retention(RetentionPolicy.RUNTIME)
40-
@Target({ElementType.METHOD, ElementType.TYPE})
40+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
4141
@LinkAnnotation
4242
@Repeatable(Links.class)
4343
public @interface Link {

allure-java-commons/src/main/java/io/qameta/allure/Links.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Links {
3333

3434
Link[] value();

allure-java-commons/src/main/java/io/qameta/allure/Muted.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Muted {
3333
}

allure-java-commons/src/main/java/io/qameta/allure/Owner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
@Documented
3434
@Inherited
3535
@Retention(RetentionPolicy.RUNTIME)
36-
@Target({ElementType.METHOD, ElementType.TYPE})
36+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3737
@LabelAnnotation(name = OWNER_LABEL_NAME)
3838
public @interface Owner {
3939

allure-java-commons/src/main/java/io/qameta/allure/Severity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Severity {
3333

3434
SeverityLevel value();

allure-java-commons/src/main/java/io/qameta/allure/Stories.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface Stories {
3333

3434
Story[] value();

allure-java-commons/src/main/java/io/qameta/allure/Story.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@Documented
3232
@Inherited
3333
@Retention(RetentionPolicy.RUNTIME)
34-
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3535
@Repeatable(Stories.class)
3636
@LabelAnnotation(name = STORY_LABEL_NAME)
3737
public @interface Story {

allure-java-commons/src/main/java/io/qameta/allure/TmsLink.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@Documented
3232
@Inherited
3333
@Retention(RetentionPolicy.RUNTIME)
34-
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3535
@LinkAnnotation(type = TMS_LINK_TYPE)
3636
@Repeatable(TmsLinks.class)
3737
public @interface TmsLink {

allure-java-commons/src/main/java/io/qameta/allure/TmsLinks.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
@Documented
2929
@Inherited
3030
@Retention(RetentionPolicy.RUNTIME)
31-
@Target({ElementType.METHOD, ElementType.TYPE})
31+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PACKAGE})
3232
public @interface TmsLinks {
3333

3434
TmsLink[] value();

allure-java-commons/src/main/java/io/qameta/allure/util/AnnotationUtils.java

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
import java.lang.reflect.AnnotatedElement;
3030
import java.lang.reflect.InvocationTargetException;
3131
import java.lang.reflect.Method;
32+
import java.util.ArrayList;
3233
import java.util.Collection;
3334
import java.util.HashSet;
35+
import java.util.List;
3436
import java.util.Objects;
3537
import java.util.Set;
3638
import java.util.function.BiFunction;
@@ -39,7 +41,11 @@
3941

4042
import static io.qameta.allure.util.ResultsUtils.createLabel;
4143
import static io.qameta.allure.util.ResultsUtils.createLink;
44+
import static java.lang.String.join;
4245
import static java.util.Arrays.asList;
46+
import static java.util.Arrays.copyOfRange;
47+
import static java.util.Arrays.stream;
48+
import static java.util.Optional.ofNullable;
4349

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

7076
/**
@@ -74,7 +80,7 @@ public static boolean isFlaky(final AnnotatedElement annotatedElement) {
7480
* @return true if {@link io.qameta.allure.Muted} annotation is present, false otherwise.
7581
*/
7682
public static boolean isMuted(final AnnotatedElement annotatedElement) {
77-
return annotatedElement.isAnnotationPresent(Muted.class);
83+
return isAnnotationPresent(annotatedElement, Muted.class);
7884
}
7985

8086
/**
@@ -84,7 +90,7 @@ public static boolean isMuted(final AnnotatedElement annotatedElement) {
8490
* @return discovered links.
8591
*/
8692
public static Set<Link> getLinks(final AnnotatedElement annotatedElement) {
87-
return getLinks(annotatedElement.getAnnotations());
93+
return getLinks(getAnnotationsFrom(annotatedElement));
8894
}
8995

9096
/**
@@ -116,7 +122,7 @@ public static Set<Link> getLinks(final Collection<Annotation> annotations) {
116122
* @return discovered labels.
117123
*/
118124
public static Set<Label> getLabels(final AnnotatedElement annotatedElement) {
119-
return getLabels(annotatedElement.getAnnotations());
125+
return getLabels(getAnnotationsFrom(annotatedElement));
120126
}
121127

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

149+
private static <T extends Annotation> boolean isAnnotationPresent(final AnnotatedElement annotatedElement, Class<T> annotationClass) {
150+
boolean isPresent = annotatedElement.isAnnotationPresent(annotationClass);
151+
if (!isPresent && annotatedElement instanceof Class<?>) {
152+
Annotation[] packageAnnotations = PackageUtil.getPackageAnnotations((Class<?>) annotatedElement);
153+
return stream(packageAnnotations).anyMatch(a -> a.annotationType().equals(annotationClass));
154+
}
155+
156+
return isPresent;
157+
}
158+
159+
private static Annotation[] getAnnotationsFrom(AnnotatedElement annotatedElement) {
160+
Annotation[] result = annotatedElement.getAnnotations();
161+
if (annotatedElement instanceof Class<?>) {
162+
Annotation[] packageAnnotations = PackageUtil.getPackageAnnotations((Class<?>) annotatedElement);
163+
List<Annotation> annotationList = new ArrayList<>(asList(result));
164+
List<Annotation> packageAnnotationList = new ArrayList<>(asList(packageAnnotations));
165+
annotationList.addAll(packageAnnotationList);
166+
result = annotationList.toArray(new Annotation[]{});
167+
}
168+
169+
return result;
170+
}
171+
143172
private static <T, U extends Annotation> Stream<T> extractMetaAnnotations(
144173
final Class<U> annotationType,
145174
final BiFunction<U, Annotation, Stream<T>> mapper,
@@ -262,4 +291,41 @@ private static boolean isInJavaLangAnnotationPackage(final Class<? extends Annot
262291
return annotationType != null && annotationType.getName().startsWith("java.lang.annotation");
263292
}
264293

294+
/**
295+
* Extracts annotations from packages hierarchically by given classes
296+
*
297+
* @author TikhomirovSergey (Sergey Tikhomirov).
298+
*/
299+
static class PackageUtil {
300+
301+
static Annotation[] getPackageAnnotations(Class<?> clz) {
302+
Objects.requireNonNull(clz, "Class should not be a null value");
303+
return getPackageAnnotations(clz.getPackage().getName());
304+
}
305+
306+
static Annotation[] getPackageAnnotations(String packageName) {
307+
Objects.requireNonNull(packageName, "Package name should not be a null value");
308+
309+
//the code below would look better if allure supported Java from 9 and higher versions
310+
Class<?> packInfo;
311+
try {
312+
packInfo = Class.forName(packageName + ".package-info", false, PackageUtil.class.getClassLoader());
313+
} catch (ClassNotFoundException e) {
314+
packInfo = null;
315+
}
316+
317+
Annotation[] annotations = ofNullable(packInfo).map(clazz -> clazz.getPackage().getAnnotations()).orElse(new Annotation[]{});
318+
String[] pathElements = packageName.split("[.]");
319+
if (pathElements.length == 1) {
320+
return annotations;
321+
}
322+
323+
Annotation[] upperPackageAnnotations = getPackageAnnotations(join(".", copyOfRange(pathElements, 0, pathElements.length - 1)));
324+
List<Annotation> annotationList = new ArrayList<>(asList(annotations));
325+
List<Annotation> result = new ArrayList<>(asList(upperPackageAnnotations));
326+
result.addAll(annotationList);
327+
return result.toArray(new Annotation[] {});
328+
}
329+
}
330+
265331
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.qameta.allure.annotatedpack;
2+
3+
import io.qameta.allure.Flaky;
4+
import io.qameta.allure.Muted;
5+
6+
@Muted
7+
@Flaky
8+
public class MutedAndFlakyTest {
9+
10+
@Muted
11+
@Flaky
12+
public void mutedAndFlakyMethod() {
13+
14+
}
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.qameta.allure.annotatedpack;
2+
3+
public class NotMutedAndFlakyTest {
4+
5+
public void notMutedAndFlakyMethod() {
6+
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.qameta.allure.annotatedpack.muted.and.flaky;
2+
3+
public class MutedAndFlakyByPackageTest {
4+
5+
public void notMutedAndFlakyMethod() {
6+
7+
}
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Muted
2+
@Flaky
3+
package io.qameta.allure.annotatedpack.muted.and.flaky;
4+
5+
import io.qameta.allure.Flaky;
6+
import io.qameta.allure.Muted;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Epic("High level epic")
2+
@Link("General link")
3+
package io.qameta.allure.annotatedpack;
4+
5+
import io.qameta.allure.Epic;
6+
import io.qameta.allure.Link;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.qameta.allure.annotatedpack.subpack.innerpack;
2+
3+
import io.qameta.allure.Story;
4+
5+
@Story("Marked pack story")
6+
public class SomeTest {
7+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@Feature("Some general feature")
2+
@Link("Some second level link")
3+
package io.qameta.allure.annotatedpack.subpack;
4+
5+
import io.qameta.allure.Feature;
6+
import io.qameta.allure.Link;

0 commit comments

Comments
 (0)