Java: remove redundant 'non-static' wording and update qhelp

This commit is contained in:
Jami Cogswell
2025-03-21 22:43:35 -04:00
parent 640096c822
commit 3e13f0ed41
9 changed files with 57 additions and 82 deletions

View File

@@ -0,0 +1,45 @@
## Overview
JUnit tests are grouped in a class, and starting from JUnit 5 users can group the test classes in a bigger class so they can share the local environment of the enclosing class. While this helps to organize the unit tests and foster code reuse, if an inner test class is not annotated with `@Nested`, the unit tests in it will fail to execute during builds.
## Recommendation
If you want the tests defined in an inner class to be recognized by the build plugin and be executed, annotate the class with `@Nested`, imported from `org.junit.jupiter.api`.
## Example
```java
import org.junit.jupiter.api.Nested;
import static org.junit.Assert.assertEquals;
public class IntegerOperationTest {
private int i; // Shared variable among the inner classes.
@BeforeEach
public void initTest() { i = 0; }
@Nested
public class AdditionTest { // COMPLIANT: Inner test class annotated with `@Nested`.
@Test
public void addTest1() {
assertEquals(1, i + 1);
}
}
public class SubtractionTest { // NON_COMPLIANT: Inner test class missing `@Nested`.
@Test
public void addTest1() {
assertEquals(-1, i - 1);
}
}
}
```
## Implementation Notes
This rule is focused on missing `@Nested` annotations on non-static nested (inner) test classes. Static nested test classes and abstract nested test classes should not be annotated with `@Nested`. As a result, the absence of a `@Nested` annotation on such classes is compliant. Identifying incorrect application of a `@Nested` annotation to static and abstract classes is out of scope for this rule.
## References
- JUnit 5 API Documentation: [Annotation Interface Nested](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Nested.html).
- JUnit 5 User Guide: [Nested Tests](https://junit.org/junit5/docs/current/user-guide/#writing-tests-nested).

View File

@@ -1,8 +1,8 @@
/**
* @id java/junit5-non-static-inner-class-missing-nested-annotation
* @name Non-static inner class defined in a JUnit 5 test is missing a `@Nested` annotation
* @description A non-static inner class defined in a JUnit 5 test missing a `@Nested` annotation
* will be excluded from execution and it may indicate a misunderstanding from the
* @id java/junit5-missing-nested-annotation
* @name Missing `@Nested` annotation on JUnit 5 inner test class
* @description A JUnit 5 inner test class that is missing a `@Nested` annotation will be
* excluded from execution and it may indicate a misunderstanding from the
* programmer.
* @kind problem
* @precision very-high
@@ -10,6 +10,7 @@
* @tags quality
* maintainability
* correctness
* previous-id:java/junit5-non-static-inner-class-missing-nested-annotation
*/
import java
@@ -21,4 +22,4 @@ where
not testClass.hasAnnotation("org.junit.jupiter.api", "Nested") and
// An abstract class should not have a `@Nested` annotation
not testClass.isAbstract()
select testClass, "This JUnit5 inner test class lacks a '@Nested' annotation."
select testClass, "This JUnit 5 inner test class lacks a '@Nested' annotation."

View File

@@ -1,71 +0,0 @@
# J-T-004: Non-static inner class defined in a JUnit 5 is missing a `@Nested` annotation
A non-static inner class defined in a JUnit 5 test missing a `@Nested` annotation will be excluded from execution and it may indicate a misunderstanding from the programmer.
## Overview
JUnit tests are grouped in a class, and starting from JUnit 5 users can group the test classes in a bigger class so they can share the local environment of the enclosing class. While this helps to organize the unit tests and foster code reuse, if the inner class is not annotated with `@Nested`, the unit tests in it will fail to execute during builds.
Note that static classes, whether static or not, behave as independent sets of unit tests. Thus, inner static classes do not share the information provided by the outer class with other inner classes. Thus, this rule only applies to non-static JUnit 5 inner classes.
## Recommendation
If you want the tests defined in an inner class to be recognized by the build plugin and be executed, annotate with `@Nested`, imported from `org.junit.jupiter.api`.
## Example
```java
import org.junit.jupiter.api.Nested;
import static org.junit.Assert.assertEquals;
public class IntegerOperationTest {
private int i; // Shared variable among the inner classes.
@BeforeEach
public void initTest() { i = 0; }
@Nested
public class AdditionTest { // COMPLIANT: Inner test class annotated with `@Nested`.
@Test
public void addTest1() { // Test of an inner class, implying `AdditionTest` is a test class.
assertEquals(1, i+1);
}
}
public class SubtractionTest { // NON_COMPLIANT: Inner test class missing `@Nested`.
@Test
public void addTest1() { // Test of an inner class, implying `SubtractionTest` is a test class.
assertEquals(-1, i-1);
}
}
static public class MultiplicationTest { // COMPLIANT: static test class should not be annotated as `@Nested`.
...
}
}
```
## Implementation Notes
The `@Nested` annotation does not apply to inner static classes, since the meaning of the annotation is to mark a class as "a *non-static* inner class containing `@Test` methods to be picked up by a build system". It also does not apply to inner abstract classes since there is no use case for an `@Nested` annotation on an abstract class. Therefore, this rule does not aim to target static or abstract inner test classes with a `@Nested` annotation, nor does it try to enforce such correct usage of `@Nested`. Therefore, any code that resembles the below is not non-compliant to this rule.
``` java
@Nested
public static class TestStatic { // COMPLIANT: Although invalid, this matter is out of the scope
@Test
public void test() {
}
}
@Nested
public abstract class TestAbstract { // COMPLIANT: Although invalid, this matter is out of the scope
@Test
public void test() {
}
}
```
## References
- JUnit: [Documentation on `@Nested`](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Nested.html).
- Baeldung: [JUnit 5 @Nested Test Classes](https://www.baeldung.com/junit-5-nested-test-classes).

View File

@@ -1,4 +1,4 @@
---
category: newQuery
---
* Added a new quality query, `java/junit5-non-static-inner-class-missing-nested-annotation`, to detect missing `@Nested` annotations on non-static, inner JUnit 5 test classes.
* Added a new quality query, `java/junit5-missing-nested-annotation`, to detect missing `@Nested` annotations on JUnit 5 inner test classes.

View File

@@ -30,7 +30,7 @@ public class AnnotationTest {
}
}
public static class Test5 { // COMPLIANT: Static inner test classes don't need `@Nested`
public static class Test5 { // COMPLIANT: Static nested test classes don't need `@Nested`
@Test
public void test() {
}
@@ -45,7 +45,7 @@ public class AnnotationTest {
}
}
public abstract class Test7 { // COMPLIANT: Abstract inner test classes don't need `@Nested`
public abstract class Test7 { // COMPLIANT: Abstract nested test classes don't need `@Nested`
@Test
public void test() {
}

View File

@@ -0,0 +1 @@
| AnnotationTest.java:13:16:13:20 | Test2 | This JUnit 5 inner test class lacks a '@Nested' annotation. |

View File

@@ -0,0 +1,2 @@
query: Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1 +0,0 @@
| AnnotationTest.java:13:16:13:20 | Test2 | This JUnit5 inner test class lacks a '@Nested' annotation. |

View File

@@ -1,2 +0,0 @@
query: Likely Bugs/Frameworks/JUnit/JUnit5NonStaticInnerClassMissingNestedAnnotation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql