[java] UnitTestShouldUseAfterAnnotation: Consider JUnit 5 and TestNG
This commit is contained in:
@ -17,6 +17,7 @@ This is a {{ site.pmd.release_type }} release.
|
|||||||
### 🌟 Rule Changes
|
### 🌟 Rule Changes
|
||||||
|
|
||||||
#### Changed Rules
|
#### Changed Rules
|
||||||
|
* {% rule java/bestpractices/UnitTestShouldUseAfterAnnotation %} (Java Best Practices) now also considers JUnit 5 and TestNG tests.
|
||||||
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) now also considers JUnit 5 and TestNG tests.
|
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) now also considers JUnit 5 and TestNG tests.
|
||||||
|
|
||||||
#### Renamed Rules
|
#### Renamed Rules
|
||||||
|
@ -1295,36 +1295,46 @@ public class MyTestCase {
|
|||||||
<rule name="UnitTestShouldUseAfterAnnotation"
|
<rule name="UnitTestShouldUseAfterAnnotation"
|
||||||
language="java"
|
language="java"
|
||||||
since="4.0"
|
since="4.0"
|
||||||
message="JUnit 4 tests that clean up tests should use the @After annotation, JUnit5 tests should use @AfterEach or @AfterAll"
|
message="Apply the correct annotation if this method is used to clean 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#unittestshoulduseafterannotation">
|
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#unittestshoulduseafterannotation">
|
||||||
<description>
|
<description>
|
||||||
This rule detects methods called `tearDown()` that are not properly annotated as a cleanup method.
|
This rule detects methods called `tearDown()` that are not properly annotated as a cleanup method.
|
||||||
This is primarily intended to assist in upgrading from JUnit 3, where tear down methods were required to be called `tearDown()`.
|
This is primarily intended to assist in upgrading from JUnit 3, where tear down methods were required to be called `tearDown()`.
|
||||||
To a lesser extent, this may help detect omissions 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 `@After` after running each test.
|
* JUnit 4 will only execute methods annotated with `@After` after running each test.
|
||||||
JUnit 5 introduced `@AfterEach` and `@AfterAll` annotations to execute methods after each test or after all tests in the class, respectively.
|
* JUnit 5 introduced `@AfterEach` and `@AfterAll` annotations to execute methods after each test or after
|
||||||
|
all tests in the class, respectively.
|
||||||
|
* TestNG provides the annotations `@AfterMethod` and `@AfterClass` to execute methods after each test or after
|
||||||
|
tests in the class, respectively.
|
||||||
</description>
|
</description>
|
||||||
<priority>3</priority>
|
<priority>3</priority>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="xpath">
|
<property name="xpath">
|
||||||
<value>
|
<value>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
//MethodDeclaration[@Name='tearDown' and @Arity=0]
|
//MethodDeclaration[@Name='tearDown' and @Arity=0]
|
||||||
[not(ModifierList/Annotation[
|
[not(ModifierList/Annotation[
|
||||||
pmd-java:typeIs('org.junit.After')
|
pmd-java:typeIs('org.junit.After')
|
||||||
or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
|
or pmd-java:typeIs('org.junit.jupiter.api.AfterEach')
|
||||||
or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
|
or pmd-java:typeIs('org.junit.jupiter.api.AfterAll')
|
||||||
or pmd-java:typeIs('org.testng.annotations.AfterMethod')])]
|
or pmd-java:typeIs('org.testng.annotations.AfterClass')
|
||||||
(: Make sure this is a junit 4 class :)
|
or pmd-java:typeIs('org.testng.annotations.AfterMethod')
|
||||||
[../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>
|
||||||
</properties>
|
</properties>
|
||||||
<example>
|
<example>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
public class MyTest {
|
public class MyTest {
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
bad();
|
bad();
|
||||||
|
@ -5,129 +5,69 @@
|
|||||||
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 tearDown</description>
|
<description>JUnit4 test class contains tearDown</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 {
|
||||||
public void tearDown() {
|
public void tearDown() {}
|
||||||
}
|
|
||||||
@Test
|
@Test
|
||||||
public void foo() {
|
public void foo() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
<test-code>
|
<test-code>
|
||||||
<description>Contains @After tearDown</description>
|
<description>JUnit4 test class contains tearDown with different signature is ok</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.junit.Test;
|
||||||
|
public class Foo {
|
||||||
|
public void tearDown(int something) {}
|
||||||
|
@Test
|
||||||
|
public void foo() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>JUnit4 test class contains @After tearDown is ok</description>
|
||||||
<expected-problems>0</expected-problems>
|
<expected-problems>0</expected-problems>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
public class Foo {
|
public class Foo {
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {}
|
||||||
}
|
|
||||||
@Test
|
@Test
|
||||||
public void foo() {
|
public void foo() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
<test-code>
|
<test-code>
|
||||||
<description>Renamed tearDown</description>
|
<description>JUnit4 test class contains renamed tearDown is ok</description>
|
||||||
<expected-problems>0</expected-problems>
|
<expected-problems>0</expected-problems>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
public class Foo {
|
public class Foo {
|
||||||
@After
|
@After
|
||||||
public void clean() {
|
public void clean() {}
|
||||||
}
|
|
||||||
@Test
|
@Test
|
||||||
public void foo() {
|
public void foo() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
<test-code>
|
<test-code>
|
||||||
<description>#1446 False positive with JUnit4TestShouldUseBeforeAnnotation when TestNG is used</description>
|
<description>Contains tearDown, not a JUnit 4/5 or TestNG test is ok</description>
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
import org.testng.annotations.AfterMethod;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
public class Foo {
|
|
||||||
@AfterMethod
|
|
||||||
public void tearDown(java.lang.reflect.Method m) {
|
|
||||||
//...
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void someTest() {}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
|
|
||||||
<test-code>
|
|
||||||
<description>#940 False positive with JUnit4TestShouldUseAfterAnnotation when JUnit5's 'AfterEach' is used</description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
import org.junit.jupiter.api.*;
|
|
||||||
|
|
||||||
public class Foo {
|
|
||||||
@AfterEach
|
|
||||||
public void tearDown() {
|
|
||||||
//...
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void someTest() {}
|
|
||||||
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
|
|
||||||
<test-code>
|
|
||||||
<description>#940 False positive with JUnit4TestShouldUseAfterAnnotation when JUnit5's 'AfterAll' is used</description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
import org.junit.jupiter.api.*;
|
|
||||||
|
|
||||||
public class Foo {
|
|
||||||
@AfterAll
|
|
||||||
public void tearDown() {
|
|
||||||
//...
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void someTest() {}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description>Contains tearDown, not a junit 4 test</description>
|
|
||||||
<expected-problems>0</expected-problems>
|
<expected-problems>0</expected-problems>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
public void tearDown() {
|
public void tearDown() {}
|
||||||
}
|
public void foo() {}
|
||||||
public void foo() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description>Contains tearDown with different signature</description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
import org.junit.Test;
|
|
||||||
public class Foo {
|
|
||||||
public void tearDown(int something) {
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void foo() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
@ -151,4 +91,119 @@ public class AReallyCoolFeatureTest extends BaseTest {
|
|||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>TestNG test contains tearDown</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>4</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
public void tearDown() {} // violation expected
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>TestNG test contains tearDown with different signature is ok (#1446)</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.testng.annotations.AfterMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
public class Foo {
|
||||||
|
@AfterMethod
|
||||||
|
public void tearDown(java.lang.reflect.Method m) {}
|
||||||
|
@Test
|
||||||
|
public void foo() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>TestNG test contains tearDown with @AfterMethod is ok</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.testng.annotations.AfterMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
@AfterMethod
|
||||||
|
public void tearDown() {}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>TestNG test contains tearDown with @AfterClass is ok</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.testng.annotations.AfterClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
@AfterClass
|
||||||
|
public void tearDown() {}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>JUnit 5 test class contains tearDown</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>4</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
public void tearDown() {} // violation expected
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>JUnit 5 test class contains tearDown with @AfterEach is ok (#940)</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>JUnit 5 test class contains tearDown with @AfterAll is ok (#940)</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MyTestCase {
|
||||||
|
@AfterAll
|
||||||
|
public void tearDown() {}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
</test-data>
|
</test-data>
|
||||||
|
Reference in New Issue
Block a user