<?xml version="1.0"?>

<ruleset name="JUnit"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
  <description>
These rules deal with different problems that can occur with JUnit tests.
  </description>

    <rule name="JUnitStaticSuite"
   		language="java"
    		 since="1.0"
          message="You have a suite() method that is not both public and static, so JUnit won't call it to get your TestSuite.  Is that what you wanted to do?"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#JUnitStaticSuite">
      <description>
The suite() method in a JUnit test needs to be both public and static.
      </description>
      <priority>3</priority>
        <properties>
        <property name="xpath">
            <value>
                <![CDATA[
//MethodDeclaration[not(@Static='true') or not(@Public='true')]
[MethodDeclarator/@Image='suite']
[MethodDeclarator/FormalParameters/@ParameterCount=0]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
                ]]>
            </value>
        </property>
        </properties>
      <example>
  <![CDATA[
import junit.framework.*;

public class Foo extends TestCase {
   public void suite() {}         // oops, should be static
   private static void suite() {} // oops, should be public
}
  ]]>
      </example>
      </rule>

  <rule name="JUnitSpelling"
   		language="java"
  		  since="1.0"
        message="You may have misspelled a JUnit framework method (setUp or tearDown)"
        class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#JUnitSpelling">
    <description>
Some JUnit framework methods are easy to misspell.
    </description>
    <priority>3</priority>
      <properties>
      <property name="xpath">
          <value>
              <![CDATA[
//MethodDeclarator[(not(@Image = 'setUp')
 and translate(@Image, 'SETuP', 'setUp') = 'setUp')
 or (not(@Image = 'tearDown')
 and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')]
 [FormalParameters[count(*) = 0]]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
              ]]>
          </value>
      </property>
      </properties>
    <example>
<![CDATA[
import junit.framework.*;

public class Foo extends TestCase {
   public void setup() {}    // oops, should be setUp
   public void TearDown() {} // oops, should be tearDown
}
]]>
    </example>
    </rule>

    <rule name="JUnitAssertionsShouldIncludeMessage"
    		 since="1.04"
          message="JUnit assertions should include a message"
          class="net.sourceforge.pmd.lang.java.rule.junit.JUnitAssertionsShouldIncludeMessageRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#JUnitAssertionsShouldIncludeMessage">
      <description>
JUnit assertions should include an informative message - i.e., use the three-argument version of 
assertEquals(), not the two-argument version.
      </description>
        <priority>3</priority>
      <example>
  <![CDATA[
public class Foo extends TestCase {
 public void testSomething() {
  assertEquals("foo", "bar");
  // Use the form:
  // assertEquals("Foo does not equals bar", "foo", "bar");
  // instead
 }
}
  ]]>
      </example>
    </rule>

    <rule name="JUnitTestsShouldIncludeAssert"
    		 since="2.0"
          message="JUnit tests should include assert() or fail()"
          class="net.sourceforge.pmd.lang.java.rule.junit.JUnitTestsShouldIncludeAssertRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#JUnitTestsShouldIncludeAssert">
        <description>
JUnit tests should include at least one assertion.  This makes the tests more robust, and using assert 
with messages provide the developer a clearer idea of what the test does.
        </description>
          <priority>3</priority>
        <example>
    <![CDATA[
public class Foo extends TestCase {
   public void testSomething() {
      Bar b = findBar();
   // This is better than having a NullPointerException
   // assertNotNull("bar not found", b);
   b.work();
   }
}
    ]]>
        </example>
      </rule>

    <rule name="TestClassWithoutTestCases"
    		 since="3.0"
          message="This class name ends with 'Test' but contains no test cases"
          class="net.sourceforge.pmd.lang.java.rule.junit.TestClassWithoutTestCasesRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#TestClassWithoutTestCases">
      <description>
Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, 
since most people will assume it is a test case. Test classes have test methods named testXXX.
      </description>
        <priority>3</priority>
      <example>
<![CDATA[
//Consider changing the name of the class if it is not a test
//Consider adding test methods if it is a test
public class CarTest {
   public static void main(String[] args) {
    // do something
   }
   // code
}
]]>
      </example>
    </rule>

    <rule name="UnnecessaryBooleanAssertion"
   		language="java"
    		 since="3.0"
          message="assertTrue(true) or similar statements are unnecessary"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#UnnecessaryBooleanAssertion">
      <description>
A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing.
Consider using flow control (in case of assertTrue(false) or similar) or simply removing
statements like assertTrue(true) and assertFalse(false).  If you just want a test to halt after finding
an error, use the fail() method and provide an indication message of why it did.
      </description>
      <priority>3</priority>
      <properties>
          <property name="xpath">
              <value>
    <![CDATA[
//StatementExpression
[
PrimaryExpression/PrimaryPrefix/Name[@Image='assertTrue' or  @Image='assertFalse']
and
PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression
[PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral
or
UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]]
]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
]]>
              </value>
          </property>
      </properties>
      <example>
<![CDATA[
public class SimpleTest extends TestCase {
	public void testX() {
		assertTrue(true);		 // serves no real purpose
	}
}
]]>
          </example>
    </rule>

    <rule name="UseAssertEqualsInsteadOfAssertTrue"
   		language="java"
    		 since="3.1"
          message="Use assertEquals(x, y) instead of assertTrue(x.equals(y))"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#UseAssertEqualsInsteadOfAssertTrue">
      <description>
This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
      </description>
      <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
                <![CDATA[
//PrimaryExpression[
    PrimaryPrefix/Name[@Image = 'assertTrue']
][
    PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
    [ends-with(@Image, '.equals')]
]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
 ]]>
            </value>
        </property>
    </properties>
      <example>
<![CDATA[
public class FooTest extends TestCase {
	void testCode() {
		Object a, b;
		assertTrue(a.equals(b)); 					// bad usage
		assertEquals(?a should equals b?, a, b);	// good usage
	}
}
]]>
      </example>
    </rule>

   <rule name="UseAssertSameInsteadOfAssertTrue"
   		language="java"
   		 since="3.1"
          message="Use assertSame(x, y) instead of assertTrue(x==y), or assertNotSame(x,y) vs assertFalse(x==y)"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#UseAssertSameInsteadOfAssertTrue">
      <description>
This rule detects JUnit assertions in object references equality. These assertions should be made 
by more specific methods, like assertSame, assertNotSame.
      </description>
      <priority>3</priority>
    <properties>
        <property name="xpath">
            <value>
                <![CDATA[
//PrimaryExpression[
    PrimaryPrefix/Name
     [@Image = 'assertTrue' or @Image = 'assertFalse']
]
[PrimarySuffix/Arguments
 /ArgumentList/Expression
 /EqualityExpression[count(.//NullLiteral) = 0]]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
 ]]>
            </value>
        </property>
    </properties>
      <example>
<![CDATA[
public class FooTest extends TestCase {
 void testCode() {
  Object a, b;
  assertTrue(a == b); // bad usage
  assertSame(a, b);  // good usage
 }
}
]]>
      </example>
    </rule>

    <rule name="UseAssertNullInsteadOfAssertTrue"
   		language="java"
           since="3.5"
           message="Use assertNull(x) instead of assertTrue(x==null), or assertNotNull(x) vs assertFalse(x==null)"
           class="net.sourceforge.pmd.lang.rule.XPathRule"
           externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#UseAssertNullInsteadOfAssertTrue">
       <description>
This rule detects JUnit assertions in object references equality. These assertions should be made by 
more specific methods, like assertNull, assertNotNull.
       </description>
       <priority>3</priority>
     <properties>
         <property name="xpath">
             <value>
                 <![CDATA[
//PrimaryExpression[
 PrimaryPrefix/Name[@Image = 'assertTrue' or @Image = 'assertFalse']
][
 PrimarySuffix/Arguments/ArgumentList[
  Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral
 ]
]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
  ]]>
             </value>
         </property>
     </properties>
       <example>
 <![CDATA[
 public class FooTest extends TestCase {
  void testCode() {
   Object a = doSomething();
   assertTrue(a==null); // bad usage
   assertNull(a);  // good usage
   assertTrue(a != null); // bad usage
   assertNotNull(a);  // good usage
  }
 }
 ]]>
       </example>
     </rule>

    <rule name="SimplifyBooleanAssertion"
   		language="java"
       since="3.6"
	    message="assertTrue(!expr) can be replaced by assertFalse(expr)"
        class="net.sourceforge.pmd.lang.rule.XPathRule"
       externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#SimplifyBooleanAssertion">
      <description>
Avoid negation in an assertTrue or assertFalse test.

For example, rephrase:

   assertTrue(!expr);
   
as:

   assertFalse(expr);
      </description>
      <priority>3</priority>
      <properties>
          <property name="xpath">
              <value>
    <![CDATA[
//StatementExpression
[
.//Name[@Image='assertTrue' or  @Image='assertFalse']
and
PrimaryExpression/PrimarySuffix/Arguments/ArgumentList
 /Expression/UnaryExpressionNotPlusMinus[@Image='!']
/PrimaryExpression/PrimaryPrefix
]
[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]]
]]>
              </value>
          </property>
      </properties>
      <example>
<![CDATA[
public class SimpleTest extends TestCase {
   public void testX() {
     assertTrue("not empty", !r.isEmpty()); // replace with assertFalse("not empty", r.isEmpty())
     assertFalse(!r.isEmpty()); // replace with assertTrue(r.isEmpty())
   }
}
]]>
          </example>
    </rule>
	<rule name="JUnitTestContainsTooManyAsserts"
		language="java"
		since="5.0"
		message="JUnit tests should not contain more than ${maximumAsserts} assert(s)."
		class="net.sourceforge.pmd.lang.rule.XPathRule"
		externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#JUnitTestContainsTooManyAsserts">
		<description>
JUnit tests should not contain too many asserts.  Many asserts are indicative of a complex test, for which 
it is harder to verify correctness.  Consider breaking the test scenario into multiple, shorter test scenarios.  
Customize the maximum number of assertions used by this Rule to suit your needs.
		</description>
		<priority>3</priority>
		<properties>
            <property name="maximumAsserts" type="Integer" min="1" max="1000" description="Maximum number of Asserts in a test method" value="1"/>
			<property name="xpath">
				<value>
<![CDATA[
//MethodDeclarator[(@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[@Image='Test']) and count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts]
]]>
				</value>
			</property>
		</properties>
		<example>
<![CDATA[
public class MyTestCase extends TestCase {
	// Ok
	public void testMyCaseWithOneAssert() {
		boolean myVar = false;		
		assertFalse("should be false", myVar);
	}

	// Bad, too many asserts (assuming max=1)
	public void testMyCaseWithMoreAsserts() {
		boolean myVar = false;		
		assertFalse("myVar should be false", myVar);
		assertEquals("should equals false", false, myVar);
	}
}
]]>
		</example>
	</rule>
	<rule name="UseAssertTrueInsteadOfAssertEquals"
		language="java"
		since="5.0"
		message="Use assertTrue(x)/assertFalse(x) instead of assertEquals(true, x)/assertEquals(false, x)."
		class="net.sourceforge.pmd.lang.rule.XPathRule"
		externalInfoUrl="${pmd.website.baseurl}/rules/java/junit.html#UseAssertTrueInsteadOfAssertEquals">
		<description>
When asserting a value is the same as a boolean literal, use assertTrue/assertFalse, instead of assertEquals.
		</description>
		<priority>3</priority>
		<properties>
			<property name="xpath">
				<value>
<![CDATA[
//PrimaryExpression[PrimaryPrefix/Name[@Image = 'assertEquals']][PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral]
]]>
			</value>
			</property>
		</properties>
		<example>
<![CDATA[
public class MyTestCase extends TestCase {
	public void testMyCase() {
		boolean myVar = true;
		// Ok
		assertTrue("myVar is true", myVar);
		// Bad
		assertEquals("myVar is true", true, myVar);
		// Bad
		assertEquals("myVar is false", false, myVar);
	}
}
]]>
		</example>
	</rule>
</ruleset>
