1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.rules.junit;
5
6 import net.sourceforge.pmd.AbstractRule;
7 import net.sourceforge.pmd.Rule;
8 import net.sourceforge.pmd.RuleContext;
9 import net.sourceforge.pmd.ast.ASTBlock;
10 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
11 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
12 import net.sourceforge.pmd.ast.ASTMethodDeclarator;
13 import net.sourceforge.pmd.ast.ASTName;
14 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
15 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
16 import net.sourceforge.pmd.ast.ASTResultType;
17 import net.sourceforge.pmd.ast.ASTStatementExpression;
18 import net.sourceforge.pmd.ast.Node;
19
20 public class JUnitTestsShouldContainAsserts extends AbstractRule implements Rule {
21
22 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
23 if (node.isInterface()) {
24 return data;
25 }
26 return super.visit(node, data);
27 }
28
29
30
31
32
33
34
35
36
37 public Object visit(ASTMethodDeclaration declaration, Object data) {
38 if (!declaration.isPublic() || declaration.isAbstract() || declaration.isNative()) {
39 return data;
40 }
41
42 if (declaration.jjtGetNumChildren()==3) {
43 ASTResultType resultType = (ASTResultType) declaration.jjtGetChild(0);
44 ASTMethodDeclarator declarator = (ASTMethodDeclarator) declaration.jjtGetChild(1);
45 ASTBlock block = (ASTBlock) declaration.jjtGetChild(2);
46 if (resultType.isVoid() && declarator.getImage().startsWith("test")) {
47 if (!hasAssertStatement(block)) {
48 RuleContext ctx = (RuleContext)data;
49 ctx.getReport().addRuleViolation(createRuleViolation(ctx, declaration));
50 }
51 }
52 }
53 return data;
54 }
55
56 private boolean hasAssertStatement(ASTBlock block) {
57 return containsAssert(block, false);
58 }
59
60 private boolean containsAssert(Node n, boolean assertFound) {
61 if (!assertFound) {
62 if (n instanceof ASTStatementExpression) {
63 if (isAssertOrFailStatement((ASTStatementExpression)n)) {
64 return true;
65 }
66 }
67 if (!assertFound) {
68 for (int i=0;i<n.jjtGetNumChildren() && ! assertFound;i++) {
69 Node c = n.jjtGetChild(i);
70 if (containsAssert(c, assertFound))
71 return true;
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
88 && pe.jjtGetChild(0) instanceof ASTPrimaryPrefix) {
89 ASTPrimaryPrefix pp = (ASTPrimaryPrefix) pe.jjtGetChild(0);
90 if (pp.jjtGetNumChildren()>0 && pp.jjtGetChild(0) instanceof ASTName) {
91 ASTName n = (ASTName) pp.jjtGetChild(0);
92 if (n.getImage()!=null && (n.getImage().startsWith("assert") || n.getImage().startsWith("fail") )) {
93 return true;
94 }
95 }
96 }
97 }
98 return false;
99 }
100 }