Skip to content

Commit 096af47

Browse files
committed
Check that JUnit 5 test classes are package-private
Closes gh-281
1 parent 2c8dbd9 commit 096af47

File tree

6 files changed

+64
-17
lines changed

6 files changed

+64
-17
lines changed

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringJUnit5Check.java

+38-13
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public class SpringJUnit5Check extends AbstractSpringCheck {
6363
LIFECYCLE_ANNOTATIONS = Collections.unmodifiableList(new ArrayList<>(annotations));
6464
}
6565

66+
private static final Annotation NESTED_ANNOTATION = new Annotation("org.junit.jupiter.api", "Nested");
67+
6668
private static final Set<String> BANNED_IMPORTS;
6769
static {
6870
Set<String> bannedImports = new LinkedHashSet<>();
@@ -84,9 +86,13 @@ public class SpringJUnit5Check extends AbstractSpringCheck {
8486

8587
private final List<DetailAST> lifecycleMethods = new ArrayList<>();
8688

89+
private final List<DetailAST> nestedTestClasses = new ArrayList<>();
90+
91+
private DetailAST testClass;
92+
8793
@Override
8894
public int[] getAcceptableTokens() {
89-
return new int[] { TokenTypes.METHOD_DEF, TokenTypes.IMPORT };
95+
return new int[] { TokenTypes.METHOD_DEF, TokenTypes.IMPORT, TokenTypes.CLASS_DEF };
9096
}
9197

9298
@Override
@@ -101,9 +107,13 @@ public void visitToken(DetailAST ast) {
101107
switch (ast.getType()) {
102108
case TokenTypes.METHOD_DEF:
103109
visitMethodDef(ast);
110+
break;
104111
case TokenTypes.IMPORT:
105112
visitImport(ast);
106113
break;
114+
case TokenTypes.CLASS_DEF:
115+
visitClassDefinition(ast);
116+
break;
107117
}
108118
}
109119

@@ -140,6 +150,17 @@ private void visitImport(DetailAST ast) {
140150
this.imports.put(ident.getText(), ident);
141151
}
142152

153+
private void visitClassDefinition(DetailAST ast) {
154+
if (ast.getParent().getType() == TokenTypes.COMPILATION_UNIT) {
155+
this.testClass = ast;
156+
}
157+
else {
158+
if (containsAnnotation(ast, Arrays.asList(NESTED_ANNOTATION))) {
159+
this.nestedTestClasses.add(ast);
160+
}
161+
}
162+
}
163+
143164
@Override
144165
public void finishTree(DetailAST rootAST) {
145166
if (shouldCheck()) {
@@ -148,7 +169,7 @@ public void finishTree(DetailAST rootAST) {
148169
}
149170

150171
private boolean shouldCheck() {
151-
if (this.testMethods.isEmpty() && this.lifecycleMethods.isEmpty()) {
172+
if (this.testMethods.isEmpty() && this.lifecycleMethods.isEmpty() && this.nestedTestClasses.isEmpty()) {
152173
return false;
153174
}
154175
for (String unlessImport : this.unlessImports) {
@@ -160,6 +181,10 @@ private boolean shouldCheck() {
160181
}
161182

162183
private void check() {
184+
if (this.testClass != null) {
185+
checkVisibility(Arrays.asList(this.testClass), "junit5.publicClass", null);
186+
}
187+
checkVisibility(this.nestedTestClasses, "junit5.publicNestedClass", "junit5.privateNestedClass");
163188
for (String bannedImport : BANNED_IMPORTS) {
164189
FullIdent ident = this.imports.get(bannedImport);
165190
if (ident != null) {
@@ -171,25 +196,25 @@ private void check() {
171196
log(testMethod, "junit5.bannedTestAnnotation");
172197
}
173198
}
174-
checkMethodVisibility(this.testMethods, "junit5.testPublicMethod", "junit5.testPrivateMethod");
175-
checkMethodVisibility(this.lifecycleMethods, "junit5.lifecyclePublicMethod", "junit5.lifecyclePrivateMethod");
199+
checkVisibility(this.testMethods, "junit5.testPublicMethod", "junit5.testPrivateMethod");
200+
checkVisibility(this.lifecycleMethods, "junit5.lifecyclePublicMethod", "junit5.lifecyclePrivateMethod");
176201
}
177202

178-
private void checkMethodVisibility(List<DetailAST> methods, String publicMessageKey, String privateMessageKey) {
179-
for (DetailAST method : methods) {
180-
DetailAST modifiers = method.findFirstToken(TokenTypes.MODIFIERS);
203+
private void checkVisibility(List<DetailAST> asts, String publicMessageKey, String privateMessageKey) {
204+
for (DetailAST ast : asts) {
205+
DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
181206
if (modifiers.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null) {
182-
log(method, publicMessageKey);
207+
log(ast, publicMessageKey);
183208
}
184-
if (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null) {
185-
log(method, privateMessageKey);
209+
if ((privateMessageKey != null) && (modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null)) {
210+
log(ast, privateMessageKey);
186211
}
187212
}
188213
}
189214

190-
private void log(DetailAST method, String key) {
191-
String name = method.findFirstToken(TokenTypes.IDENT).getText();
192-
log(method.getLineNo(), method.getColumnNo(), key, name);
215+
private void log(DetailAST ast, String key) {
216+
String name = ast.findFirstToken(TokenTypes.IDENT).getText();
217+
log(ast.getLineNo(), ast.getColumnNo(), key, name);
193218
}
194219

195220
public void setUnlessImports(String unlessImports) {

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/main/java/io/spring/javaformat/checkstyle/check/SpringTestFileNameCheck.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected void processFiltered(File file, FileText fileText) throws CheckstyleEx
4141
visitCompilationUnit(JavaParser.parseFileText(fileText, Options.WITHOUT_COMMENTS));
4242
}
4343
}
44-
44+
4545
private void visitCompilationUnit(DetailAST ast) {
4646
DetailAST child = ast.getFirstChild();
4747
while (child != null) {
@@ -52,5 +52,5 @@ private void visitCompilationUnit(DetailAST ast) {
5252
child = child.getNextSibling();
5353
}
5454
}
55-
55+
5656
}

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/main/resources/io/spring/javaformat/checkstyle/check/messages.properties

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ junit5.bannedImport=Import ''{0}'' should not be used in a JUnit 5 test.
1616
junit5.bannedTestAnnotation=JUnit 4 @Test annotation should not be used in a JUnit 5 test.
1717
junit5.lifecyclePrivateMethod=Lifecycle method ''{0}'' should not be private.
1818
junit5.lifecyclePublicMethod=Lifecycle method ''{0}'' should not be public.
19+
junit5.publicClass=Test class ''{0}'' should not be public.
20+
junit5.publicNestedClass=Nested test class ''{0}'' should not be public.
21+
junit5.privateNestedClass=Nested test class ''{0}'' should not be private.
1922
junit5.testPrivateMethod=Test method ''{0}'' should not be private.
2023
junit5.testPublicMethod=Test method ''{0}'' should not be public.
2124
lambda.missingParen=Lambda argument missing parentheses.

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/test/resources/check/JUnit5BadModifier.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
+Test class 'JUnit5BadModifier' should not be public
2+
+Nested test class 'PublicNestedTests' should not be public
3+
+Nested test class 'PrivateNestedTests' should not be private
14
+Test method 'doSomethingWorks' should not be public
25
+Test method 'doSomethingElseWorks' should not be private
36
+Test method 'doSomethingWithTemplateWorks' should not be public
47
+Test method 'doSomethingElseWithTemplateWorks' should not be private
8+
+Test method 'nestedPublicTest' should not be public
59
+Lifecycle method 'publicBeforeAll' should not be public
610
+Lifecycle method 'publicBeforeEach' should not be public
711
+Lifecycle method 'publicAfterAll' should not be public

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5BadModifier.java

+15
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,19 @@ private void doSomethingElseWithTemplateWorks() {
8888
// test here
8989
}
9090

91+
@Nested
92+
public static class PublicNestedTests {
93+
94+
@Test
95+
public void nestedPublicTest() {
96+
97+
}
98+
99+
}
100+
101+
@Nested
102+
private static class PrivateNestedTests {
103+
104+
}
105+
91106
}

Diff for: spring-javaformat/spring-javaformat-checkstyle/src/test/resources/source/JUnit5Valid.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2019 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
2121
*
2222
* @author Phillip Webb
2323
*/
24-
public class JUnit5Valid {
24+
class JUnit5Valid {
2525

2626
@Test
2727
void doSomethingWorks() {

0 commit comments

Comments
 (0)