[java] UnitTestShouldUseBeforeAnnotation: Consider JUnit 5 and TestNG

This commit is contained in:
Andreas Dangel 2024-10-03 17:01:24 +02:00
parent b7c4a5e492
commit 33c737718c
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
3 changed files with 159 additions and 85 deletions

View File

@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release.
### 🌟 Rule Changes ### 🌟 Rule Changes
#### Changed Rules
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) now also considers JUnit 5 and TestNG tests.
#### Renamed Rules #### Renamed Rules
Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG. after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.

View File

@ -1342,16 +1342,20 @@ public class MyTest2 {
<rule name="UnitTestShouldUseBeforeAnnotation" <rule name="UnitTestShouldUseBeforeAnnotation"
language="java" language="java"
since="4.0" since="4.0"
message="JUnit 4 tests that set up tests should use the @Before annotation, JUnit5 tests should use @BeforeEach or @BeforeAll" message="Apply the correct annotation if this method is used to set up the tests"
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#unittestshouldusebeforeannotation"> externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#unittestshouldusebeforeannotation">
<description> <description>
This rule detects methods called `setUp()` that are not properly annotated as a setup method. This rule detects methods called `setUp()` that are not properly annotated as a setup method.
This is primarily intended to assist in upgrading from JUnit 3, where setup methods were required to be called `setUp()`. This is primarily intended to assist in upgrading from JUnit 3, where setup methods were required to be called `setUp()`.
To a lesser extent, this may help detect omissions even under newer JUnit versions, as long as you are following this convention to name the methods. To a lesser extent, this may help detect omissions even under newer JUnit versions or under TestNG,
as long as you are following this convention to name the methods.
JUnit 4 will only execute methods annotated with `@Before` before all tests. * JUnit 4 will only execute methods annotated with `@Before` before all tests.
JUnit 5 introduced `@BeforeEach` and `@BeforeAll` annotations to execute methods before each test or before all tests in the class, respectively. * JUnit 5 introduced `@BeforeEach` and `@BeforeAll` annotations to execute methods before each test or before all
tests in the class, respectively.
* TestNG provides the annotations `@BeforeMethod` and `@BeforeClass` to execute methods before each test or before
tests in the class, respectively.
</description> </description>
<priority>3</priority> <priority>3</priority>
<properties> <properties>
@ -1363,9 +1367,15 @@ public class MyTest2 {
pmd-java:typeIs('org.junit.Before') pmd-java:typeIs('org.junit.Before')
or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach') or pmd-java:typeIs('org.junit.jupiter.api.BeforeEach')
or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll') or pmd-java:typeIs('org.junit.jupiter.api.BeforeAll')
or pmd-java:typeIs('org.testng.annotations.BeforeMethod')])] or pmd-java:typeIs('org.testng.annotations.BeforeMethod')
(: Make sure this is a junit 4 class :) or pmd-java:typeIs('org.testng.annotations.BeforeClass')
[../MethodDeclaration[pmd-java:hasAnnotation('org.junit.Test')]] ])]
(: Make sure this is a JUnit 4/5 or TestNG class :)
[../MethodDeclaration[
pmd-java:hasAnnotation('org.junit.Test')
or pmd-java:hasAnnotation('org.junit.jupiter.api.Test')
or pmd-java:hasAnnotation('org.testng.annotations.Test')
]]
]]> ]]>
</value> </value>
</property> </property>

View File

@ -5,8 +5,9 @@
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
<test-code> <test-code>
<description>Contains setUp</description> <description>JUnit4 Test class contains setUp</description>
<expected-problems>1</expected-problems> <expected-problems>1</expected-problems>
<expected-linenumbers>3</expected-linenumbers>
<code><![CDATA[ <code><![CDATA[
import org.junit.Test; import org.junit.Test;
public class Foo { public class Foo {
@ -20,7 +21,7 @@ public class Foo {
</test-code> </test-code>
<test-code> <test-code>
<description>Contains @setUp</description> <description>JUnit4 Test class with Before is ok</description>
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code><![CDATA[ <code><![CDATA[
import org.junit.Before; import org.junit.Before;
@ -37,7 +38,7 @@ public class Foo {
</test-code> </test-code>
<test-code> <test-code>
<description>Renamed setup</description> <description>JUnit4 Test class with renamed setup using Before is ok</description>
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code><![CDATA[ <code><![CDATA[
import org.junit.Before; import org.junit.Before;
@ -73,85 +74,29 @@ public class Foo {
</test-code> </test-code>
<test-code> <test-code>
<description>#1446 False positive with JUnit4TestShouldUseBeforeAnnotation when TestNG is used</description> <description>Contains setUp, not a JUnit 4/5/TestNG test</description>
<expected-problems>0</expected-problems> <expected-problems>0</expected-problems>
<code><![CDATA[ <code><![CDATA[
import org.testng.annotations.BeforeMethod; public class Foo {
import org.testng.annotations.Test; public void setUp() {}
import java.lang.reflect.Method; public void foo() {}
}
]]></code>
</test-code>
<test-code>
<description>JUnit4 Test class contains setUp with different signature is ok</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.Test;
public class Foo { public class Foo {
@BeforeMethod public void setUp(int something) {}
public void setUp(Method m) {
//...
}
@Test @Test
public void someTest() {} public void foo() {}
} }
]]></code> ]]></code>
</test-code>
<test-code>
<description>#940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'BeforeEach' is used</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.jupiter.api.*;
public class Foo {
@BeforeEach
public void setUp() {
//...
}
@Test
public void someTest() {}
}
]]></code>
</test-code>
<test-code>
<description>#940 False positive with JUnit4TestShouldUseBeforeAnnotation when JUnit5's 'BeforeAll' is used</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.jupiter.api.*;
public class Foo {
@BeforeAll
public void setUp() {
//...
}
@Test
public void someTest() {}
}
]]></code>
</test-code>
<test-code>
<description>Contains setUp, not a junit 4 test</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public void setUp() {
}
public void foo() {
}
}
]]></code>
</test-code>
<test-code>
<description>Contains setUp with different signature</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.Test;
public class Foo {
public void setUp(int something) {
}
@Test
public void foo() {
}
}
]]></code>
</test-code> </test-code>
<test-code> <test-code>
@ -173,4 +118,120 @@ public class AReallyCoolFeatureTest extends BaseTest {
} }
]]></code> ]]></code>
</test-code> </test-code>
<test-code>
<description>TestNG class contains setUp</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
import org.testng.annotations.Test;
public class MyTestCase {
public void setUp() {} // violation expected here
@Test
public void myTest() {}
}
]]></code>
</test-code>
<test-code>
<description>TestNG class contains setUp with different signature is ok (#1446)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.testng.annotations.Test;
import java.lang.reflect.Method;
public class Foo {
public void setUp(Method m) {}
@Test
public void foo() {}
}
]]></code>
</test-code>
<test-code>
<description>TestNG with @BeforeMethod is ok (#1446)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class MyTestCase {
@BeforeMethod
public void setUp() {}
@Test
public void myTest() {}
}
]]></code>
</test-code>
<test-code>
<description>TestNG with @BeforeClass is ok</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class MyTestCase {
@BeforeClass
public void setUp() {}
@Test
public void myTest() {}
}
]]></code>
</test-code>
<test-code>
<description>JUnit5 Test class contains setUp</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
import org.junit.jupiter.api.Test;
public class MyTestCase {
public void setUp() {} // violation expected
@Test
public void myTest() {}
}
]]></code>
</test-code>
<test-code>
<description>JUnit5 Test class with BeforeEach is ok (#940)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class MyTestCase {
@BeforeEach
public void setUp() {}
@Test
public void myTest() {}
}
]]></code>
</test-code>
<test-code>
<description>JUnit5 Test class with BeforeAll is ok (#940)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class MyTestCase {
@BeforeAll
public void setUp() {}
@Test
public void myTest() {}
}
]]></code>
</test-code>
</test-data> </test-data>