Coverage Report - com.puppycrawl.tools.checkstyle.checks.coding.JUnitTestCaseCheck
 
Classes in this File Line Coverage Branch Coverage Complexity
JUnitTestCaseCheck
94%
52/55
87%
35/40
2.545
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 // checkstyle: Checks Java source code for adherence to a set of rules.
 3  
 // Copyright (C) 2001-2014  Oliver Burn
 4  
 //
 5  
 // This library is free software; you can redistribute it and/or
 6  
 // modify it under the terms of the GNU Lesser General Public
 7  
 // License as published by the Free Software Foundation; either
 8  
 // version 2.1 of the License, or (at your option) any later version.
 9  
 //
 10  
 // This library is distributed in the hope that it will be useful,
 11  
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // Lesser General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU Lesser General Public
 16  
 // License along with this library; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 18  
 ////////////////////////////////////////////////////////////////////////////////
 19  
 package com.puppycrawl.tools.checkstyle.checks.coding;
 20  
 
 21  
 import com.puppycrawl.tools.checkstyle.api.Check;
 22  
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
 23  
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 24  
 
 25  
 import com.puppycrawl.tools.checkstyle.checks.CheckUtils;
 26  
 
 27  
 /**
 28  
  * Ensures that the setUp(), tearDown()methods are named correctly,
 29  
  * have no arguments, return void and are either public or protected.
 30  
  * Also ensures that suite() is named correctly, has no arguments, returns
 31  
  * junit.framework.Test, and is public and static.
 32  
  *
 33  
  * Rationale: Developers will often misname one or more of these
 34  
  * methods and not realise that the method is not being called.
 35  
  *
 36  
  * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
 37  
  */
 38  1
 public final class JUnitTestCaseCheck extends Check
 39  
 {
 40  
     /** <code>setUp()</code> method name. */
 41  
     private static final String SET_UP_METHOD_NAME = "setUp";
 42  
     /** <code>tearDown()</code> method name. */
 43  
     private static final String TEAR_DOWN_METHOD_NAME = "tearDown";
 44  
     /** <code>suite()</code> method name. */
 45  
     private static final String SUITE_METHOD_NAME = "suite";
 46  
 
 47  
     @Override
 48  
     public int[] getDefaultTokens()
 49  
     {
 50  1
         return new int[] {TokenTypes.METHOD_DEF};
 51  
     }
 52  
 
 53  
     @Override
 54  
     public int[] getRequiredTokens()
 55  
     {
 56  0
         return getDefaultTokens();
 57  
     }
 58  
 
 59  
     @Override
 60  
     public void visitToken(DetailAST aAST)
 61  
     {
 62  13
         switch (aAST.getType()) {
 63  
         case TokenTypes.METHOD_DEF:
 64  13
             visitMethodDef(aAST);
 65  13
             break;
 66  
         default:
 67  0
             throw new IllegalStateException(aAST.toString());
 68  
         }
 69  13
     }
 70  
 
 71  
     /**
 72  
      * Checks given method definition.
 73  
      * @param aAST a method def node for check
 74  
      */
 75  
     private void visitMethodDef(DetailAST aAST)
 76  
     {
 77  13
         final String name = aAST.findFirstToken(TokenTypes.IDENT).getText();
 78  
 
 79  13
         if (name.equalsIgnoreCase(SET_UP_METHOD_NAME)) {
 80  4
             checkSetUpTearDownMethod(aAST, name, SET_UP_METHOD_NAME);
 81  
         }
 82  9
         else if (name.equalsIgnoreCase(TEAR_DOWN_METHOD_NAME)) {
 83  4
             checkSetUpTearDownMethod(aAST, name, TEAR_DOWN_METHOD_NAME);
 84  
         }
 85  5
         else if (name.equalsIgnoreCase(SUITE_METHOD_NAME)) {
 86  4
             checkSuiteMethod(aAST, name);
 87  
         }
 88  13
     }
 89  
 
 90  
     /**
 91  
      * Checks signature/name of <code>suite()</code>.
 92  
      * @param aAST method definition node
 93  
      * @param aActualName method name
 94  
      */
 95  
     private void checkSuiteMethod(DetailAST aAST, String aActualName)
 96  
     {
 97  4
         if (!aActualName.equals(SUITE_METHOD_NAME)) {
 98  0
             log(aAST, "junit.method.name", SUITE_METHOD_NAME);
 99  
         }
 100  
 
 101  4
         if (!isPublicAndStatic(aAST)) {
 102  2
             log(aAST, "junit.method.public.and.static", SUITE_METHOD_NAME);
 103  
         }
 104  
 
 105  
         // let's check return type
 106  4
         final DetailAST typeAST = aAST.findFirstToken(TokenTypes.TYPE);
 107  4
         final boolean isArray =
 108  
             (typeAST.findFirstToken(TokenTypes.ARRAY_DECLARATOR) != null);
 109  4
         final String type = CheckUtils.createFullType(typeAST).getText();
 110  4
         if (isArray
 111  
             || (!"Test".equals(type)
 112  
             && !"junit.framework.Test".equals(type)))
 113  
         {
 114  1
             log(aAST, "junit.method.return.type",
 115  
                 SUITE_METHOD_NAME, "junit.framework.Test");
 116  
         }
 117  4
         checkParameters(aAST, SUITE_METHOD_NAME);
 118  4
     }
 119  
 
 120  
     /**
 121  
      * Checks signature/name of <code>setUp()</code>/<code>tearDown</code>.
 122  
      * @param aAST method definition node
 123  
      * @param aActualName actual method name
 124  
      * @param aExpectedName expected method name
 125  
      */
 126  
     private void checkSetUpTearDownMethod(DetailAST aAST, String aActualName,
 127  
                                           String aExpectedName)
 128  
     {
 129  8
         if (!aActualName.equals(aExpectedName)) {
 130  1
             log(aAST, "junit.method.name", aActualName, aExpectedName);
 131  
         }
 132  
 
 133  8
         if (!isPublicOrProtected(aAST)) {
 134  1
             log(aAST, "junit.method.protected.or.public", aExpectedName);
 135  
         }
 136  
 
 137  8
         if (isStatic(aAST)) {
 138  1
             log(aAST, "junit.method.static", aExpectedName);
 139  
         }
 140  
 
 141  8
         checkReturnValue(aAST, aActualName);
 142  8
         checkParameters(aAST, aActualName);
 143  8
     }
 144  
 
 145  
     /**
 146  
      * Checks that given method returns <code>void</code>.
 147  
      * @param aAST method definition node
 148  
      * @param aName method name
 149  
      */
 150  
     private void checkReturnValue(DetailAST aAST, String aName)
 151  
     {
 152  8
         final DetailAST returnValueAST = aAST.findFirstToken(TokenTypes.TYPE);
 153  
 
 154  8
         if (returnValueAST.findFirstToken(TokenTypes.LITERAL_VOID) == null) {
 155  1
             log(aAST, "junit.method.return.type", aName, "void");
 156  
         }
 157  8
     }
 158  
 
 159  
     /**
 160  
      * Checks return value of given method.
 161  
      * @param aAST method definition node
 162  
      * @param aName method name
 163  
      */
 164  
     private void checkParameters(DetailAST aAST, String aName)
 165  
     {
 166  12
         final DetailAST parametersAST =
 167  
             aAST.findFirstToken(TokenTypes.PARAMETERS);
 168  
 
 169  12
         if (parametersAST.getChildCount() != 0) {
 170  2
             log(aAST, "junit.method.parameters", aName);
 171  
         }
 172  12
     }
 173  
 
 174  
     /**
 175  
      * Checks if given method declared as public or
 176  
      * protected and non-static.
 177  
      * @param aAST method definition node
 178  
      * @return true if given method is declared as public or protected
 179  
      */
 180  
     private boolean isPublicOrProtected(DetailAST aAST)
 181  
     {
 182  8
         final DetailAST modifiersAST =
 183  
             aAST.findFirstToken(TokenTypes.MODIFIERS);
 184  8
         final DetailAST publicAST =
 185  
             modifiersAST.findFirstToken(TokenTypes.LITERAL_PUBLIC);
 186  8
         final DetailAST protectedAST =
 187  
             modifiersAST.findFirstToken(TokenTypes.LITERAL_PROTECTED);
 188  
 
 189  8
         return (publicAST != null) || (protectedAST != null);
 190  
     }
 191  
 
 192  
     /**
 193  
      * Checks if given method declared as <code>public</code> and
 194  
      * <code>static</code>.
 195  
      * @param aAST method definition node
 196  
      * @return true if given method is declared as public and static
 197  
      */
 198  
     private boolean isPublicAndStatic(DetailAST aAST)
 199  
     {
 200  4
         final DetailAST modifiersAST =
 201  
             aAST.findFirstToken(TokenTypes.MODIFIERS);
 202  4
         final DetailAST publicAST =
 203  
             modifiersAST.findFirstToken(TokenTypes.LITERAL_PUBLIC);
 204  4
         final DetailAST staticAST =
 205  
             modifiersAST.findFirstToken(TokenTypes.LITERAL_STATIC);
 206  
 
 207  4
         return (publicAST != null) && (staticAST != null);
 208  
     }
 209  
 
 210  
     /**
 211  
      * Checks if given method declared as static.
 212  
      * @param aAST method definition node
 213  
      * @return true if given method is declared as static
 214  
      */
 215  
     private boolean isStatic(DetailAST aAST)
 216  
     {
 217  8
         final DetailAST modifiersAST =
 218  
             aAST.findFirstToken(TokenTypes.MODIFIERS);
 219  8
         final DetailAST staticAST =
 220  
             modifiersAST.findFirstToken(TokenTypes.LITERAL_STATIC);
 221  
 
 222  8
         return (staticAST != null);
 223  
     }
 224  
 }