Skip to content

Commit 35b6478

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: include RepeatedTest, ParameterizedTest, TestFactory, and TestTemplate when identifying JUnit 5 test methods
1 parent 4d7bed6 commit 35b6478

File tree

9 files changed

+192
-9
lines changed

9 files changed

+192
-9
lines changed

java/ql/lib/semmle/code/java/UnitTests.qll

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,36 @@ class JUnitJupiterTestMethod extends Method {
113113
}
114114

115115
/**
116-
* A JUnit test class that contains at least one method annotated with
117-
* `org.junit.jupiter.api.Test`.
116+
* A JUnit 5 test method.
117+
* A test method is defined by JUnit as "any instance method
118+
* that is directly annotated or meta-annotated with `@Test`,
119+
* `@RepeatedTest`, `@ParameterizedTest`, `@TestFactory`, or
120+
* `@TestTemplate`."
121+
* See https://junit.org/junit5/docs/current/user-guide/#writing-tests-definitions
122+
*/
123+
class JUnit5TestMethod extends Method {
124+
JUnit5TestMethod() {
125+
this instanceof JUnitJupiterTestMethod or
126+
this.getAnAnnotation()
127+
.getType()
128+
.hasQualifiedName("org.junit.jupiter.api", ["RepeatedTest", "TestFactory", "TestTemplate"]) or
129+
this.getAnAnnotation()
130+
.getType()
131+
.hasQualifiedName("org.junit.jupiter.params", "ParameterizedTest")
132+
}
133+
}
134+
135+
/**
136+
* A JUnit 5 test class.
137+
* A test class must contain at least one test method, and
138+
* cannot be abstract.
139+
* See https://junit.org/junit5/docs/current/user-guide/#writing-tests-definitions
118140
*/
119141
class JUnit5TestClass extends Class {
120-
JUnit5TestClass() { this.getAMethod() instanceof JUnitJupiterTestMethod }
142+
JUnit5TestClass() {
143+
this.getAMethod() instanceof JUnit5TestMethod and
144+
not this.isAbstract()
145+
}
121146
}
122147

123148
/**

java/ql/src/Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,5 @@
1616
import java
1717

1818
from JUnit5InnerTestClass testClass
19-
where
20-
not testClass.hasAnnotation("org.junit.jupiter.api", "Nested") and
21-
// An abstract class should not have a `@Nested` annotation
22-
not testClass.isAbstract()
19+
where not testClass.hasAnnotation("org.junit.jupiter.api", "Nested")
2320
select testClass, "This JUnit 5 inner test class lacks a '@Nested' annotation."

java/ql/test/query-tests/Likely Bugs/Frameworks/JUnit/AnnotationTest.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import java.util.Collection;
12
import org.junit.jupiter.api.Test;
3+
import org.junit.jupiter.api.RepeatedTest;
4+
import org.junit.jupiter.api.TestFactory;
5+
import org.junit.jupiter.api.TestTemplate;
26
import org.junit.jupiter.api.Nested;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.ValueSource;
39

410
public class AnnotationTest {
511
@Nested
@@ -10,12 +16,42 @@ public void test() {
1016
}
1117

1218
// NON_COMPLIANT: Inner test class is missing `@Nested`
13-
public class Test2 { // $ Alert
19+
public class Test2_Test { // $ Alert
1420
@Test
1521
public void test() {
1622
}
1723
}
1824

25+
// NON_COMPLIANT: Inner test class is missing `@Nested`
26+
public class Test2_RepeatedTest { // $ Alert
27+
@RepeatedTest(2)
28+
public void test() {
29+
}
30+
}
31+
32+
// NON_COMPLIANT: Inner test class is missing `@Nested`
33+
public class Test2_ParameterizedTest { // $ Alert
34+
@ParameterizedTest
35+
@ValueSource(strings = { "" })
36+
public void test(String s) {
37+
}
38+
}
39+
40+
// NON_COMPLIANT: Inner test class is missing `@Nested`
41+
public class Test2_TestFactory { // $ Alert
42+
@TestFactory
43+
Collection<Object> test() {
44+
return null;
45+
}
46+
}
47+
48+
// NON_COMPLIANT: Inner test class is missing `@Nested`
49+
public class Test2_TestTemplate { // $ Alert
50+
@TestTemplate
51+
public void test() {
52+
}
53+
}
54+
1955
public class Test3 { // COMPLIANT: Since it is empty, it is not a test class
2056
}
2157

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
| AnnotationTest.java:13:16:13:20 | Test2 | This JUnit 5 inner test class lacks a '@Nested' annotation. |
1+
| AnnotationTest.java:19:16:19:25 | Test2_Test | This JUnit 5 inner test class lacks a '@Nested' annotation. |
2+
| AnnotationTest.java:26:16:26:33 | Test2_RepeatedTest | This JUnit 5 inner test class lacks a '@Nested' annotation. |
3+
| AnnotationTest.java:33:16:33:38 | Test2_ParameterizedTest | This JUnit 5 inner test class lacks a '@Nested' annotation. |
4+
| AnnotationTest.java:41:16:41:32 | Test2_TestFactory | This JUnit 5 inner test class lacks a '@Nested' annotation. |
5+
| AnnotationTest.java:49:16:49:33 | Test2_TestTemplate | This JUnit 5 inner test class lacks a '@Nested' annotation. |

java/ql/test/stubs/junit-jupiter-api-5.2.0/org/junit/jupiter/api/RepeatedTest.java

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/ql/test/stubs/junit-jupiter-api-5.2.0/org/junit/jupiter/api/TestFactory.java

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/ql/test/stubs/junit-jupiter-api-5.2.0/org/junit/jupiter/api/TestTemplate.java

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/ql/test/stubs/junit-jupiter-api-5.2.0/org/junit/jupiter/params/ParameterizedTest.java

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

java/ql/test/stubs/junit-jupiter-api-5.2.0/org/junit/jupiter/params/provider/ValueSource.java

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)