1
2
3
4
5 package com.qulice.checkstyle;
6
7 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8 import com.puppycrawl.tools.checkstyle.api.DetailAST;
9 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public final class ProhibitTestMethodNameCheck extends AbstractCheck {
31
32
33
34
35 public ProhibitTestMethodNameCheck() {
36
37 }
38
39 @Override
40 public int[] getDefaultTokens() {
41 return this.getRequiredTokens();
42 }
43
44 @Override
45 public int[] getAcceptableTokens() {
46 return this.getRequiredTokens();
47 }
48
49 @Override
50 public int[] getRequiredTokens() {
51 return new int[] {TokenTypes.METHOD_DEF};
52 }
53
54 @Override
55 public void visitToken(final DetailAST ast) {
56 if (ProhibitTestMethodNameCheck.isTest(ast)) {
57 final DetailAST name = ast.findFirstToken(TokenTypes.IDENT);
58 final String text = name.getText();
59 if (ProhibitTestMethodNameCheck.startsWithForbidden(text)) {
60 this.log(
61 name.getLineNo(),
62 String.format(
63 "Test method name \"%s\" must not start with \"test\" or \"should\", use a verb that describes the behaviour",
64 text
65 )
66 );
67 }
68 }
69 }
70
71 private static boolean isTest(final DetailAST ast) {
72 final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
73 boolean found = false;
74 if (modifiers != null) {
75 DetailAST child = modifiers.getFirstChild();
76 while (child != null) {
77 if (child.getType() == TokenTypes.ANNOTATION
78 && ProhibitTestMethodNameCheck.isTestAnnotation(child)) {
79 found = true;
80 break;
81 }
82 child = child.getNextSibling();
83 }
84 }
85 return found;
86 }
87
88 private static boolean isTestAnnotation(final DetailAST ast) {
89 final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
90 final boolean match;
91 if (ident == null) {
92 final DetailAST dot = ast.findFirstToken(TokenTypes.DOT);
93 match = dot != null
94 && dot.getLastChild() != null
95 && "Test".equals(dot.getLastChild().getText());
96 } else {
97 match = "Test".equals(ident.getText());
98 }
99 return match;
100 }
101
102 private static boolean startsWithForbidden(final String name) {
103 return startsWithWord(name, "should")
104 || startsWithWord(name, "test") && !startsWithWord(name, "tests");
105 }
106
107 private static boolean startsWithWord(final String name, final String prefix) {
108 final boolean result;
109 if (name.startsWith(prefix)) {
110 if (name.length() == prefix.length()) {
111 result = true;
112 } else {
113 final char next = name.charAt(prefix.length());
114 result = Character.isUpperCase(next) || next == '_';
115 }
116 } else {
117 result = false;
118 }
119 return result;
120 }
121 }