View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.lang.java.rule.junit;
    5
    6   import java.util.List;
    7
    8   import net.sourceforge.pmd.lang.ast.Node;
    9   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
    10  import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair;
    11  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
    12  import net.sourceforge.pmd.lang.java.ast.ASTName;
    13  import net.sourceforge.pmd.lang.java.ast.ASTNormalAnnotation;
    14  import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
    15  import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
    16  import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
    17
    18  public class JUnitTestsShouldIncludeAssertRule extends AbstractJUnitRule {
    19
    20      @Override
    21      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
    22          if (node.isInterface()) {
    23              return data;
    24          }
    25          return super.visit(node, data);
    26      }
    27
    28      @Override
    29      public Object visit(ASTMethodDeclaration method, Object data) {
    30          if (isJUnitMethod(method, data))  {
    31              if (!containsAssert(method.getBlock(), false)
    32                  && !containsExpect(method.jjtGetParent())) {
    33                  addViolation(data, method);
    34              }
    35          }
    36  		return data;
    37  	}
    38
    39      private boolean containsAssert(Node n, boolean assertFound) {
    40          if (!assertFound) {
    41              if (n instanceof ASTStatementExpression) {
    42                  if (isAssertOrFailStatement((ASTStatementExpression)n)) {
    43                      return true;
    44                  }
    45              }
    46              if (!assertFound) {
    47                  for (int i=0;i<n.jjtGetNumChildren() && ! assertFound;i++) {
    48                      Node c = n.jjtGetChild(i);
    49                      if (containsAssert(c, assertFound)) {
    50                          return true;
    51                      }
    52                  }
    53              }
    54          }
    55          return false;
    56      }
    57
    58      /**
    59       * Tells if the node contains a Test annotation with an expected exception.
    60       */
    61      private boolean containsExpect(Node methodParent) {
    62          List<ASTNormalAnnotation> annotations = methodParent.findDescendantsOfType(ASTNormalAnnotation.class);
    63          for (ASTNormalAnnotation annotation : annotations) {
    64              ASTName name = annotation.getFirstChildOfType(ASTName.class);
    65              if (name != null && ("Test".equals(name.getImage())
    66                      || (name.getType() != null && name.getType().equals(JUNIT4_CLASS)))) {
    67                  List<ASTMemberValuePair> memberValues = annotation.findDescendantsOfType(ASTMemberValuePair.class);
    68                  for (ASTMemberValuePair pair : memberValues) {
    69                      if ("expected".equals(pair.getImage())) {
    70                          return true;
    71                      }
    72                  }
    73              }
    74          }
    75          return false;
    76      }
    77
    78      /**
    79       * Tells if the expression is an assert statement or not.
    80       */
    81      private boolean isAssertOrFailStatement(ASTStatementExpression expression) {
    82          if (expression!=null
    83                  && expression.jjtGetNumChildren()>0
    84                  && expression.jjtGetChild(0) instanceof ASTPrimaryExpression
    85                  ) {
    86              ASTPrimaryExpression pe = (ASTPrimaryExpression) expression.jjtGetChild(0);
    87              if (pe.jjtGetNumChildren()> 0 && pe.jjtGetChild(0) instanceof ASTPrimaryPrefix) {
    88                  ASTPrimaryPrefix pp = (ASTPrimaryPrefix) pe.jjtGetChild(0);
    89                  if (pp.jjtGetNumChildren()>0 && pp.jjtGetChild(0) instanceof ASTName) {
    90                      String img = ((ASTName) pp.jjtGetChild(0)).getImage();
    91                      if (img != null && (img.startsWith("assert") || img.startsWith("fail") || img.startsWith("Assert.assert") || img.startsWith("Assert.fail") )) {
    92                          return true;
    93                      }
    94                  }
    95              }
    96          }
    97          return false;
    98      }
    99  }