Java: include RepeatedTest, ParameterizedTest, TestFactory, and TestTemplate when identifying JUnit 5 test methods

This commit is contained in:
Jami Cogswell
2025-03-23 16:36:08 -04:00
parent 4d7bed6181
commit 35b647839c
9 changed files with 192 additions and 9 deletions

View File

@@ -113,11 +113,36 @@ class JUnitJupiterTestMethod extends Method {
}
/**
* A JUnit test class that contains at least one method annotated with
* `org.junit.jupiter.api.Test`.
* A JUnit 5 test method.
* A test method is defined by JUnit as "any instance method
* that is directly annotated or meta-annotated with `@Test`,
* `@RepeatedTest`, `@ParameterizedTest`, `@TestFactory`, or
* `@TestTemplate`."
* See https://junit.org/junit5/docs/current/user-guide/#writing-tests-definitions
*/
class JUnit5TestMethod extends Method {
JUnit5TestMethod() {
this instanceof JUnitJupiterTestMethod or
this.getAnAnnotation()
.getType()
.hasQualifiedName("org.junit.jupiter.api", ["RepeatedTest", "TestFactory", "TestTemplate"]) or
this.getAnAnnotation()
.getType()
.hasQualifiedName("org.junit.jupiter.params", "ParameterizedTest")
}
}
/**
* A JUnit 5 test class.
* A test class must contain at least one test method, and
* cannot be abstract.
* See https://junit.org/junit5/docs/current/user-guide/#writing-tests-definitions
*/
class JUnit5TestClass extends Class {
JUnit5TestClass() { this.getAMethod() instanceof JUnitJupiterTestMethod }
JUnit5TestClass() {
this.getAMethod() instanceof JUnit5TestMethod and
not this.isAbstract()
}
}
/**

View File

@@ -16,8 +16,5 @@
import java
from JUnit5InnerTestClass testClass
where
not testClass.hasAnnotation("org.junit.jupiter.api", "Nested") and
// An abstract class should not have a `@Nested` annotation
not testClass.isAbstract()
where not testClass.hasAnnotation("org.junit.jupiter.api", "Nested")
select testClass, "This JUnit 5 inner test class lacks a '@Nested' annotation."

View File

@@ -1,5 +1,11 @@
import java.util.Collection;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
public class AnnotationTest {
@Nested
@@ -10,12 +16,42 @@ public class AnnotationTest {
}
// NON_COMPLIANT: Inner test class is missing `@Nested`
public class Test2 { // $ Alert
public class Test2_Test { // $ Alert
@Test
public void test() {
}
}
// NON_COMPLIANT: Inner test class is missing `@Nested`
public class Test2_RepeatedTest { // $ Alert
@RepeatedTest(2)
public void test() {
}
}
// NON_COMPLIANT: Inner test class is missing `@Nested`
public class Test2_ParameterizedTest { // $ Alert
@ParameterizedTest
@ValueSource(strings = { "" })
public void test(String s) {
}
}
// NON_COMPLIANT: Inner test class is missing `@Nested`
public class Test2_TestFactory { // $ Alert
@TestFactory
Collection<Object> test() {
return null;
}
}
// NON_COMPLIANT: Inner test class is missing `@Nested`
public class Test2_TestTemplate { // $ Alert
@TestTemplate
public void test() {
}
}
public class Test3 { // COMPLIANT: Since it is empty, it is not a test class
}

View File

@@ -1 +1,5 @@
| AnnotationTest.java:13:16:13:20 | Test2 | This JUnit 5 inner test class lacks a '@Nested' annotation. |
| AnnotationTest.java:19:16:19:25 | Test2_Test | This JUnit 5 inner test class lacks a '@Nested' annotation. |
| AnnotationTest.java:26:16:26:33 | Test2_RepeatedTest | This JUnit 5 inner test class lacks a '@Nested' annotation. |
| AnnotationTest.java:33:16:33:38 | Test2_ParameterizedTest | This JUnit 5 inner test class lacks a '@Nested' annotation. |
| AnnotationTest.java:41:16:41:32 | Test2_TestFactory | This JUnit 5 inner test class lacks a '@Nested' annotation. |
| AnnotationTest.java:49:16:49:33 | Test2_TestTemplate | This JUnit 5 inner test class lacks a '@Nested' annotation. |

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@TestTemplate
public @interface RepeatedTest {
int value();
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestFactory {
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestTemplate {
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.params;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.TestTemplate;
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@TestTemplate
public @interface ParameterizedTest {
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.params.provider;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValueSource {
String[] strings() default {};
}