Skip to content

Commit 43c4d6b

Browse files
authored
feat(descriptions-javadoc): various improvements (fixes #982, fixes #962, via #981)
1 parent 1017cb5 commit 43c4d6b

File tree

12 files changed

+292
-50
lines changed

12 files changed

+292
-50
lines changed

allure-descriptions-javadoc/build.gradle.kts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ description = "Allure Javadoc Descriptions"
33
val agent: Configuration by configurations.creating
44

55
dependencies {
6-
api("commons-io:commons-io")
7-
api(project(":allure-java-commons"))
86
testImplementation("com.google.testing.compile:compile-testing")
97
testImplementation("io.github.glytching:junit-extensions")
108
testImplementation("org.assertj:assertj-core")
@@ -18,9 +16,11 @@ dependencies {
1816

1917
tasks.jar {
2018
manifest {
21-
attributes(mapOf(
19+
attributes(
20+
mapOf(
2221
"Automatic-Module-Name" to "io.qameta.allure.description"
23-
))
22+
)
23+
)
2424
}
2525
}
2626

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2023 Qameta Software OÜ
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.description;
17+
18+
/**
19+
* @author charlie (Dmitry Baev).
20+
*/
21+
final class ClassNames {
22+
23+
static final String DESCRIPTION_ANNOTATION = "io.qameta.allure.Description";
24+
25+
private ClassNames() {
26+
throw new IllegalStateException("do not instance");
27+
}
28+
}

allure-descriptions-javadoc/src/main/java/io/qameta/allure/description/JavaDocDescriptionsProcessor.java

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package io.qameta.allure.description;
1717

18-
import io.qameta.allure.Description;
19-
2018
import javax.annotation.processing.AbstractProcessor;
2119
import javax.annotation.processing.Filer;
2220
import javax.annotation.processing.Messager;
@@ -28,22 +26,27 @@
2826
import javax.lang.model.element.ExecutableElement;
2927
import javax.lang.model.element.TypeElement;
3028
import javax.lang.model.element.VariableElement;
29+
import javax.lang.model.util.ElementFilter;
3130
import javax.lang.model.util.Elements;
3231
import javax.tools.Diagnostic;
3332
import javax.tools.FileObject;
3433
import javax.tools.StandardLocation;
3534
import java.io.IOException;
3635
import java.io.Writer;
36+
import java.math.BigInteger;
37+
import java.nio.charset.StandardCharsets;
38+
import java.security.MessageDigest;
39+
import java.security.NoSuchAlgorithmException;
3740
import java.util.List;
3841
import java.util.Set;
3942
import java.util.stream.Collectors;
4043

41-
import static io.qameta.allure.util.ResultsUtils.generateMethodSignatureHash;
44+
import static io.qameta.allure.description.ClassNames.DESCRIPTION_ANNOTATION;
4245

4346
/**
4447
* @author Egor Borisov [email protected]
4548
*/
46-
@SupportedAnnotationTypes("io.qameta.allure.Description")
49+
@SupportedAnnotationTypes(DESCRIPTION_ANNOTATION)
4750
public class JavaDocDescriptionsProcessor extends AbstractProcessor {
4851

4952
private static final String ALLURE_DESCRIPTIONS_FOLDER = "META-INF/allureDescriptions/";
@@ -68,24 +71,29 @@ public SourceVersion getSupportedSourceVersion() {
6871

6972
@Override
7073
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment env) {
71-
final Set<? extends Element> elements = env.getElementsAnnotatedWith(Description.class);
72-
elements.forEach(el -> {
73-
if (!el.getAnnotation(Description.class).useJavaDoc()) {
74+
final TypeElement typeElement = elementUtils.getTypeElement(DESCRIPTION_ANNOTATION);
75+
final Set<? extends Element> elements = env.getElementsAnnotatedWith(typeElement);
76+
final Set<ExecutableElement> methods = ElementFilter.methodsIn(elements);
77+
methods.forEach(method -> {
78+
final String rawDocs = elementUtils.getDocComment(method);
79+
80+
if (rawDocs == null) {
7481
return;
7582
}
76-
final String docs = elementUtils.getDocComment(el);
77-
final List<String> typeParams = ((ExecutableElement) el).getParameters().stream()
78-
.map(this::methodParameterTypeMapper)
79-
.collect(Collectors.toList());
80-
final String name = el.getSimpleName().toString();
81-
if (docs == null) {
82-
messager.printMessage(Diagnostic.Kind.WARNING,
83-
"Unable to create resource for method " + name + typeParams
84-
+ " as it does not have a docs comment");
83+
84+
final String docs = rawDocs.trim();
85+
if ("".equals(docs)) {
8586
return;
8687
}
8788

88-
final String hash = generateMethodSignatureHash(el.getEnclosingElement().toString(), name, typeParams);
89+
final String name = method.getSimpleName().toString();
90+
final List<String> typeParams = method.getParameters().stream()
91+
.map(this::methodParameterTypeMapper)
92+
.collect(Collectors.toList());
93+
94+
final String hash = generateMethodSignatureHash(
95+
method.getEnclosingElement().toString(), name, typeParams
96+
);
8997
try {
9098
final FileObject file = filer.createResource(StandardLocation.CLASS_OUTPUT, "",
9199
ALLURE_DESCRIPTIONS_FOLDER + hash);
@@ -105,4 +113,29 @@ private String methodParameterTypeMapper(final VariableElement parameter) {
105113
final Element typeElement = processingEnv.getTypeUtils().asElement(parameter.asType());
106114
return typeElement != null ? typeElement.toString() : parameter.asType().toString();
107115
}
116+
117+
private static String generateMethodSignatureHash(final String className,
118+
final String methodName,
119+
final List<String> parameterTypes) {
120+
final MessageDigest md = getMd5Digest();
121+
md.update(className.getBytes(StandardCharsets.UTF_8));
122+
md.update(methodName.getBytes(StandardCharsets.UTF_8));
123+
parameterTypes.stream()
124+
.map(string -> string.getBytes(StandardCharsets.UTF_8))
125+
.forEach(md::update);
126+
final byte[] bytes = md.digest();
127+
return bytesToHex(bytes);
128+
}
129+
130+
private static MessageDigest getMd5Digest() {
131+
try {
132+
return MessageDigest.getInstance("MD5");
133+
} catch (NoSuchAlgorithmException e) {
134+
throw new IllegalStateException("Can not find hashing algorithm", e);
135+
}
136+
}
137+
138+
private static String bytesToHex(final byte[] bytes) {
139+
return new BigInteger(1, bytes).toString(16);
140+
}
108141
}

allure-descriptions-javadoc/src/test/java/io/qameta/allure/description/ProcessDescriptionsTest.java

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ProcessDescriptionsTest {
3737
void captureDescriptionTest() {
3838
final String expectedMethodSignatureHash = "4e7f896021ef2fce7c1deb7f5b9e38fb";
3939

40-
JavaFileObject source = JavaFileObjects.forSourceLines(
40+
final JavaFileObject source = JavaFileObjects.forSourceLines(
4141
"io.qameta.allure.description.test.DescriptionSample",
4242
"package io.qameta.allure.description.test;",
4343
"import io.qameta.allure.Description;",
@@ -53,19 +53,55 @@ void captureDescriptionTest() {
5353
"}"
5454
);
5555

56-
Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor())
56+
final Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor())
5757
.withOptions("-Werror");
58-
Compilation compilation = compiler.compile(source);
59-
assertThat(compilation).generatedFile(
60-
StandardLocation.CLASS_OUTPUT,
58+
final Compilation compilation = compiler.compile(source);
59+
assertThat(compilation)
60+
.generatedFile(
61+
StandardLocation.CLASS_OUTPUT,
62+
"",
63+
ALLURE_DESCRIPTIONS_FOLDER + expectedMethodSignatureHash
64+
)
65+
.contentsAsUtf8String()
66+
.isEqualTo("Captured javadoc description");
67+
}
68+
69+
@Test
70+
void captureDescriptionTestIfNoUseJavadocIsSpecified() {
71+
final String expectedMethodSignatureHash = "4e7f896021ef2fce7c1deb7f5b9e38fb";
72+
73+
final JavaFileObject source = JavaFileObjects.forSourceLines(
74+
"io.qameta.allure.description.test.DescriptionSample",
75+
"package io.qameta.allure.description.test;",
76+
"import io.qameta.allure.Description;",
6177
"",
62-
ALLURE_DESCRIPTIONS_FOLDER + expectedMethodSignatureHash
78+
"public class DescriptionSample {",
79+
"",
80+
"/**",
81+
"* Captured javadoc description",
82+
"*/",
83+
"@Description",
84+
"public void sampleTest() {",
85+
"}",
86+
"}"
6387
);
88+
89+
final Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor())
90+
.withOptions("-Werror");
91+
final Compilation compilation = compiler.compile(source);
92+
assertThat(compilation)
93+
.generatedFile(
94+
StandardLocation.CLASS_OUTPUT,
95+
"",
96+
ALLURE_DESCRIPTIONS_FOLDER + expectedMethodSignatureHash
97+
)
98+
.contentsAsUtf8String()
99+
.contains("Captured javadoc description");
64100
}
65101

66102
@Test
67103
void skipUncommentedMethodTest() {
68-
JavaFileObject source = JavaFileObjects.forSourceLines(
104+
final JavaFileObject source = JavaFileObjects.forSourceLines(
69105
"io.qameta.allure.description.test.DescriptionSample",
70106
"package io.qameta.allure.description.test;",
71107
"import io.qameta.allure.Description;",
@@ -78,19 +114,16 @@ void skipUncommentedMethodTest() {
78114
"}"
79115
);
80116

81-
Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
82-
Compilation compilation = compiler.compile(source);
117+
final Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
118+
final Compilation compilation = compiler.compile(source);
83119
assertThat(compilation).succeeded();
84-
assertThat(compilation)
85-
.hadWarningContaining("Unable to create resource for method "
86-
+ "sampleTestWithoutJavadocComment[] as it does not have a docs comment");
87120
}
88121

89122
@Test
90123
void captureDescriptionParametrizedTestWithGenericParameterTest() {
91124
final String expectedMethodSignatureHash = "e90e26691bf14511db819d78624ba716";
92125

93-
JavaFileObject source = JavaFileObjects.forSourceLines(
126+
final JavaFileObject source = JavaFileObjects.forSourceLines(
94127
"io.qameta.allure.description.test.DescriptionSample",
95128
"package io.qameta.allure.description.test;",
96129
"import io.qameta.allure.Description;",
@@ -117,8 +150,8 @@ void captureDescriptionParametrizedTestWithGenericParameterTest() {
117150
"}"
118151
);
119152

120-
Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
121-
Compilation compilation = compiler.compile(source);
153+
final Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
154+
final Compilation compilation = compiler.compile(source);
122155
assertThat(compilation).generatedFile(
123156
StandardLocation.CLASS_OUTPUT,
124157
"",
@@ -130,7 +163,7 @@ void captureDescriptionParametrizedTestWithGenericParameterTest() {
130163
void captureDescriptionParametrizedTestWithPrimitivesParameterTest() {
131164
final String expectedMethodSignatureHash = "edeeeaa02f01218cc206e0c6ff024c7a";
132165

133-
JavaFileObject source = JavaFileObjects.forSourceLines(
166+
final JavaFileObject source = JavaFileObjects.forSourceLines(
134167
"io.qameta.allure.description.test.DescriptionSample",
135168
"package io.qameta.allure.description.test;",
136169
"import io.qameta.allure.Description;",
@@ -150,12 +183,15 @@ void captureDescriptionParametrizedTestWithPrimitivesParameterTest() {
150183
"}"
151184
);
152185

153-
Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
154-
Compilation compilation = compiler.compile(source);
155-
assertThat(compilation).generatedFile(
156-
StandardLocation.CLASS_OUTPUT,
157-
"",
158-
ALLURE_DESCRIPTIONS_FOLDER + expectedMethodSignatureHash
159-
);
186+
final Compiler compiler = javac().withProcessors(new JavaDocDescriptionsProcessor());
187+
final Compilation compilation = compiler.compile(source);
188+
assertThat(compilation)
189+
.generatedFile(
190+
StandardLocation.CLASS_OUTPUT,
191+
"",
192+
ALLURE_DESCRIPTIONS_FOLDER + expectedMethodSignatureHash
193+
)
194+
.contentsAsUtf8String()
195+
.isEqualTo("Captured javadoc description");
160196
}
161197
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import java.lang.annotation.Target;
2222

2323
/**
24-
* Annotation that allows to attach a description for a test.
24+
* Annotation that allows to attach a description for a test.
2525
*/
2626
@Retention(RetentionPolicy.RUNTIME)
2727
@Target(ElementType.METHOD)
@@ -39,7 +39,9 @@
3939
* supports html markdown.
4040
*
4141
* @return boolean flag to enable description extraction from javadoc.
42+
* @deprecated use {@link Description} without value specified instead.
4243
*/
44+
@Deprecated
4345
boolean useJavaDoc() default false;
4446

4547
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,12 @@ public static void processDescription(final ClassLoader classLoader,
389389
final Consumer<String> setDescription,
390390
final Consumer<String> setDescriptionHtml) {
391391
if (method.isAnnotationPresent(Description.class)) {
392-
if (method.getAnnotation(Description.class).useJavaDoc()) {
392+
final Description annotation = method.getAnnotation(Description.class);
393+
if ("".equals(annotation.value())) {
393394
getJavadocDescription(classLoader, method)
394395
.ifPresent(setDescriptionHtml);
395396
} else {
396-
final String description = method.getAnnotation(Description.class).value();
397+
final String description = annotation.value();
397398
setDescription.accept(description);
398399
}
399400
}

allure-junit4/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dependencies {
66
api(project(":allure-java-commons"))
77
implementation("junit:junit:$junitVersion")
88
implementation(project(":allure-test-filter"))
9+
testAnnotationProcessor(project(":allure-descriptions-javadoc"))
910
testImplementation("org.assertj:assertj-core")
1011
testImplementation("org.junit.jupiter:junit-jupiter-api")
1112
testImplementation("org.mockito:mockito-core")

0 commit comments

Comments
 (0)