Return to TestUtil

 

TestUtil.2

 

TestUtil: By Example

 

 

Introduction to TestUtil

TestUtil is a Java open source low-effort automated method testing strategy and tool for verifying all matching accessor methods on mutable objects with a single line of unit test code. It is compatible with both in-container and outside-the-container strategies extending JUnit.

 

A Testing Dilemma

A decision confronting an application development team committed to testing – is whether to verify accessor methods (“getters” and “setters”) in a unit test context.  On one hand, invoking methods with presumably little logic seems pedantic.  On the other hand, a simple copy and substitute error can result in a difficult to detect (persisted) data integrity problem.  The following sample Business Object (BO) class contains a coding error: 

 

public class TestUtilSampleBO extends BaseBO {

 

       private String attributeOne;

       private String attributeTwo;

 

       /**

        * @return Returns the attributeOne.

        */

       public String getAttributeOne() {

             return this.attributeOne;

       }

 

       /**

        * @param attributeOne The attributeOne to set.

        */

       public void setAttributeOne(String attributeOne) {

             this.attributeOne = attributeOne;

       }

 

       /**

        * @return Returns the attributeTwo.

        */

       public String getAttributeTwo() {

             return this.attributeOne;  // ß Copy & substitute mistake.

       }

 

       /**

        * @param attributeTwo The attributeTwo to set.

        */

       public void setAttributeTwo(String attributeTwo) {

             this.attributeTwo = attributeTwo;

       }

 

TestUtil was originally intended to catch this type of coding error.

 

Examples

TestUtil was recently utilized during a “Fortune 5” (company) application development project – let’s call it Fortune5.  Approximately one-third of the developers (including Architects) and the Business Analysts were co-located in North America, and approximately two-thirds of the developers were in India.  The first release of Fortune5 went into production (February, 2006) for about 3,500 users in North America. 

 

Individual developers were expected to include single object accessor method verification for all Business Objects (BOs) and Struts Form Beans within their automated method (or JUnit) tests – as follows:

 

    /**
     * Verify accessor methods of a mutable business object.
     */

    public void testPersonBO() {

         assertTrue(TestUtil.verifyMutable(new PersonBO(), 1, 0));
    }

 

Invoking the verifyMutable() method provided developers with timely feedback for eliminating simple coding errors on a single class.  In addition, the Consulting Architect began reviewing the entire code base with the verifyDirectory() method after TestUtil v. 1.1 was released in November, 2005:

 

   /**
    * Verify all accessor methods in project source.
    */
     

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false);

    }

 

The following Verification Chronicle (including lessons learned) focuses on the TestUtil verifyDirectory() method.  In addition, recommended practices for the TestUtil verifyMutable() method are inferred.  In May of 2006, the Chronicle was updated to demonstrate Javadoc annotations introduced with TestUtil v. 2.0.

 

Note: You will see the numbers recorded as “Verify Directory Summary Results” fluctuate since the Chronicle covers multiple weeks while development was in progress.

 

 

The Verification Chronicle

 

Run #1 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 103 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1605 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1556 Successful Verification(s); 33 Warning(s); 16 Glitch(es); 3 Caution(s)

****************************************************************************************************

 

Run #1 Log Observation(s):

Fortune5 exceptions extend from a corporate J2EE Platform Abstraction;  The exceptions are self-logging (and self-emailing when declaratively configured).  Therefore, a side-effect of TestUtil instantiating Fortune5 application exceptions was numerous stack traces cluttering the log - when exceptions don’t have matching accessor methods requiring verification anyway!

 

Run #1 Response:

The following representative entries were made to the testutil-config.xml descriptor document causing Fortune5 exception classes to be excluded from TestUtil verification.

 

      <Element aClassName="com.obfuscated.exceptions.Fortune5CheckedException"

            cautionOrSkip="skip">true</Element>

      <Element aClassName="com.obfuscated.exceptions.Fortune5RuntimeException"

            cautionOrSkip=" skip ">true</Element>

      <Element aClassName="com.obfuscated.exceptions.DuplicateKeyException"

            cautionOrSkip=" skip ">true</Element>

      <Element aClassName="com.obfuscated.exceptions.ExternalProblemException"

            cautionOrSkip=" skip ">true</Element>

      <Element aClassName="com.obfuscated.exceptions.NoInstancesFoundException"

            cautionOrSkip=" skip ">true</Element>

 

Note: If a specific Fortune5 exception contained a matching accessor pair, a custom-coded unit test could be created.

 

Note: With the introduction of TestUtil v. 2.0 a Javadoc tag could be used instead of editing the optional testutil-config.xml descriptor document. 

 

          /**

           * @author MDT (MarvinToll@gtcGroup.com)

           * @since v. 2.0

           * @excludeClass skip

           */

 

public class ExcludeClassUsingJavadocTagBO extends BaseTestBO {

 

// Methods here.

          }

 

Run #2 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 108 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1605 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1556 Successful Verification(s); 33 Warning(s); 16 Glitch(es); 3 Caution(s)

****************************************************************************************************

 

Run #2 Log Observation(s):

Fortune5 JSP tags extend javax.servlet.jsp.tagext.TagSupport.  It turns out TagSupport has setValue() and getValue() methods which are not TestUtil verifiable.

 

Run #2 Response:

At this point a choice exists; should the entire class be excluded or just the offending method?  A quick perusal of application custom tags indicate a general absence of getter/setter combinations.  So, perhaps it makes sense to exclude the classes entirely.  Now a second choice exists; should the exclusion be recorded as the default “caution” or a “skip” on the “Verify Directory Summary Results”?  The default is chosen since it provides greater ongoing visibility for the exclusion decision – should the decision need to be revisited.

 

The following representative entries were made to the testutil-config.xml descriptor document causing Fortune5 JSP tag classes to be ignored for TestUtil verification.

 

      <Element aClassName="com.obfuscated.tags.Fortune5NotAuthorizedTag"

            cautionOrSkip="caution">true</Element>

      <Element aClassName="com.obfuscated.tags.Fortune5IsAuthorizedTag"

            cautionOrSkip="caution">true</Element>

      <Element aClassName="com.obfuscated.tags.Fortune5GetValueTag"

            cautionOrSkip="caution">true</Element>

 

Note: A side-effect of this exercise was the removal of an obsolete tag from the code base.

Note: If a specific Fortune5 tag contained a matching accessor pair, a custom-coded unit test could be created.

 

Note: With the introduction of TestUtil v. 2.0 a (simple) Javadoc tag could be used instead of editing the optional testutil-config.xml descriptor document. 

 

          /**

           * @author MDT (MarvinToll@gtcGroup.com)

           * @since v. 2.0

           * @excludeClassFromTestUtilVerification

           */

 

public class ExcludeClassUsingJavadocTagBO extends BaseTestBO {

 

// Methods here.

 

          }

 

Run #3 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1584 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1541 Successful Verification(s); 30 Warning(s); 13 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #3 Log Observation(s):

Fortune5 has two (2) occurrences of transforming attributes from upper to lower case within accessor methods.  This is considered a correct implementation by the development team.

 

      Glitch [# 1]:  Setter = [setGlobalIdText()];  Getter = [getGlobalIdText()]

      Randomly set [S163540668] value does not match returned [s163540668] value.

 

Run #3 Response:

The following representative entries were made to the testutil-config.xml descriptor document causing Fortune5 method pairs to be excluded from verification.

 

      <Configuration name="exclude.method.pair.by.setter">

            <Element aMutableClassName="com.obfuscated.formbean.FunctionalForm"

                  theSetterMethodName="setGlobalIdText">true</Element>

            <Element aMutableClassName="com.obfuscated.formbean.PatternForm"

                  theSetterMethodName="setGlobalIdText">true</Element>

      </Configuration>

 

Since exclusion of methods result in a TestUtil “warning” (instead of a “glitch”), the unit test method was modified to assert the two warnings.

 

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false, "", true, 2);

    }

 

Note: Verification of excluded method pairs, if desired, requires creating custom-coded unit tests.

 

Note: With the introduction of TestUtil v. 2.0 a “setter” Javadoc tag may indicate exclusion instead of the optional testutil-config.xml descriptor document. 

 

          /**

           * @param globalIdText

           * @excludeSetter

           */

          public void setGlobalIdText(String globalIdText) {

                    this.globalIdText = globalIdText.toLowerCase();

          }

 

 

Run #4 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1582 Successful Verification(s); 2 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1541 Successful Verification(s); 32 Warning(s); 11 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #4 Log Observation(s):

Fortune5 has seven (7) occurrences of transformation logic associated with date processing.  This is considered a correct implementation by the development team.

 

      Glitch [# 1]:  Setter = [setStringReleaseDate()];  Getter = [getStringReleaseDate()]

      The method [setStringReleaseDate] could not be invoked [java.lang.reflect.InvocationTargetException] with [java.lang.String] parameter type.

 

Run #4 Response:

The following representative entry was made to the testutil-config.xml descriptor document causing Fortune5 method pairs to be excluded from verification.

 

      <Configuration name="exclude.method.pair.by.setter">

<Element aMutableClassName="com.obfuscated.bo.LeadershipBO"

                  theSetterMethodName="setStringReleaseDate">true</Element>

 

            etc. etc.

 

      </Configuration>  

 

Since exclusion of methods result in a TestUtil “warning” (instead of a “glitch”), the unit test method was modified to assert the additional seven (7) warnings – for a total of nine (9) warnings.

 

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false, "", true, 9);

    }

 

Note: Discovery of these seven (7) identical occurrences yielded a refactoring opportunity for removal of duplicate code.

 

Note: With the introduction of TestUtil v. 2.0 a setter Javadoc tag may indicate exclusion instead of the optional testutil-config.xml descriptor document. 

 

    /**

     * @param stringReleaseDate

     * @excludeSetterFromTestUtilVerification

     */

    public void setStringReleaseDate(String stringReleaseDate) {

       

        // String release date is manipulated.

        stringReleaseDate = AppDateUtil.manipulateDate(stringReleaseDate);

    }

 

Run #5 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1575 Successful Verification(s); 9 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1541 Successful Verification(s); 39 Warning(s); 4 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #5 Log Observation(s):

Fortune5 has four (4) occurrences of miscellaneous transformation logic applied in “getters”.  This is considered a correct implementation by the development team.

 

      Glitch [# 1]:  Setter = [setPositionTaskBOList()];  Getter = [getPositionTaskBOList()]

      The method [getPositionTaskBOList] could not be invoked [java.lang.reflect.InvocationTargetException] with [n/a] parameter type.

 

      Glitch [# 1]:  Setter = [setStringDisplayOrder()];  Getter = [getStringDisplayOrder()]

      The method [setStringDisplayOrder] could not be invoked [java.lang.reflect.InvocationTargetException] with [java.lang.String] parameter type.

 

      Glitch [# 1]:  Setter = [setStageBOList()];  Getter = [getStageBOList()]

      The method [getStageBOList] could not be invoked [java.lang.reflect.InvocationTargetException] with [n/a] parameter type.

 

      Glitch [# 1]:  Setter = [setActiveEmployeeBOList()];  Getter = [getActiveEmployeeBOList()]

      The method [getActiveEmployeeBOList] could not be invoked [java.lang.reflect.InvocationTargetException] with [n/a] parameter

 

 

Run #5 Response:

The following four (4) entries were made to the testutil-config.xml descriptor document causing Fortune5 method pairs to be excluded from verification.

 

      <Configuration name="exclude.method.pair.by.setter">

            <Element aMutableClassName="com.obfuscated.bo.PositionBO"

                  theSetterMethodName="setPositionTaskBOList">true</Element>

            <Element aMutableClassName="com.obfuscated.bo.CompetencyBO"

                  theSetterMethodName="setStringDisplayOrder">true</Element>

            <Element aMutableClassName="com.obfuscated.bo.ScaleBO"

                  theSetterMethodName="setStageBOList">true</Element>

            <Element aMutableClassName="com.obfuscated.bo.EmployeePositionBO"

                  theSetterMethodName="setActiveEmployeeBOList">true</Element>

      </Configuration>  

 

Since exclusion of methods results in a TestUtil “warning” (instead of a “glitch”), the unit test method was modified to assert the additional four (4) warnings – for a total of thirteen (13) warnings.

 

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false, "", true, 13);

    }

 

Note: The @excludeSetter Javadoc tag could be used instead of editing the optional testutil-config.xml descriptor document.

 

Run #6 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1575 Successful Verification(s); 13 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1545 Successful Verification(s); 43 Warning(s); 0 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #6 Synchronization of Source Code:

The Fortune5 code base continues to mature – prompting a resynchronization with the source code management system.

 

Run #7 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1590 Successful Verification(s); 13 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 1552 Successful Verification(s); 45 Warning(s); 6 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Note: In case you were wondering about the “Successful Verification(s)” calculation - the math works like this:

 

·        Anticipated: 1590 + 13 (Warnings) = 1603 total matching pairs subject to verification

·        Results: 1552 + 45 (Warnings) + 6 (Glitches) = 1603 total matching pairs subject to verification

·        “Cautions” and “Skips” refer to classes and are not included in method calculations 

 

Run #7 Log Observation(s):

After synchronization, three (3) classes could not be instantiated with reflection for verification.  Two of the classes require an HttpServletRequest constructor parameter and will necessitate a custom-coded unit test.

 

      * Caution [# 1]: Instantiation [com.obfuscated.forms.DevFocusViewHelper] failure.

      * Caution [# 2]: Instantiation [com.obfuscated.util.AuthorizationPlugin] failure.

      * Caution [# 3]: Instantiation [com.obfuscated.base.BaseAuthorizationPlugin] failure.

 

Run #7 Response:

The following two entries were made to the testutil-config.xml descriptor document causing Fortune5 authorization classes to be ignored for TestUtil verification.  It turns out the DevFocusViewHelper class was implemented inconsistently with the architectural patterns of the project and requires refactoring - the appropriate developer was notified.

 

      <Element aClassName="com.obfuscated.util.AuthorizationPlugin"

            cautionOrSkip="caution">true</Element>

      <Element aClassName="com.obfuscated.base.BaseAuthorizationPlugin"

            cautionOrSkip="caution">true</Element>

 

The testAllAccessors() method remains unchanged and one unanticipated “caution” will result.  The unit test will not pass (run green) until the DevFocusViewHelper class is refactored and the number of anticipated “cautions” match the result.

 

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false, "", true, 13, 0, 5);

    }

 

Note: The @excludeSetter Javadoc tag could be used instead of editing the optional testutil-config.xml descriptor document.

 

 

Run #8 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1590 Successful Verification(s); 13 Warning(s); 0 Glitch(es); 5 Caution(s)

* -----> Results: 1552 Successful Verification(s); 45 Warning(s); 6 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #8 Log Observation(s):

After the last source code synchronization, six (6) new “glitches” appeared.

 

      Glitch [# 1]:  Setter = [setPositionCompetencyBOListForDisplay()];  Getter = [getPositionCompetencyBOListForDisplay()]

 

      Glitch [# 2]:  Setter = [setPositionDetailBOListForDisplay()];  Getter = [getPositionDetailBOListForDisplay()]

 

      Glitch [# 1]:  Setter = [setConcentrationHeadingList()];  Getter = [getConcentrationHeadingList()]

 

      Glitch [# 1]:  Setter = [setEmployeeDevRO()];  Getter = [getEmployeeDevRO()]  ß Three occurrences.

 

Run #8 Response:

The three (3) occurrences relating to EmployeeDevRO were a side-effect of obsolete debug statements.  The applicable developer was contacted and the debug statements subsequently removed.  The following three (3) entries were made to the testutil-config.xml descriptor document causing Fortune5 method pairs to be excluded from verification.

 

      <Configuration name="exclude.method.pair.by.setter">

            <Element aMutableClassName="com.obfuscated.bo.PositionBO"

                  theSetterMethodName="setPositionCompetencyBOListForDisplay">true</Element>

            <Element aMutableClassName="com.obfuscated.bo.PositionBO"

                  theSetterMethodName="setPositionDetailBOListForDisplay">true</Element>

            <Element aMutableClassName="com.obfuscated.presentation.forms.PositionListForm"

                  theSetterMethodName="setConcentrationHeadingList">true</Element>

      </Configuration>  

 

Since exclusion of methods result in a TestUtil “warning” (instead of a “glitch”), the unit test method was modified to assert the additional three (3) warnings – for a total of sixteen (16) warnings.

 

    public void testAllAccessors() {

 

        TestUtil.verifyDirectory("\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource", false, "", true, 16, 0, 5);

    }

 

Note: The @excludeSetter Javadoc tag could be used instead of editing the optional testutil-config.xml descriptor document.

 

 

Run #9 Summary Results:

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 106 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 1590 Successful Verification(s); 16 Warning(s); 0 Glitch(es); 5 Caution(s)

* -----> Results: 1555 Successful Verification(s); 48 Warning(s); 0 Glitch(es); 6 Caution(s)

****************************************************************************************************

 

Run #9 Timeout For A Sanity Check:

 

Managing 48 “warnings” is growing cumbersome with one unit test.  The number of “warnings” is an indicator of the volume of transformation logic being coded within accessor methods.  Some architects might discourage the practice of using the verbs “set”, “get” and “is” for methods containing transformation logic.  Regardless of ones philosophical stance on the issue – the immediate tactical reality dictates splitting the single test into multiple categorized by high level package name.  Let’s start with three unit tests.

 

Run #10 Summary Results:

 

// Verification Complete (Green Bar)!

      public void testAllAccessors_Common() {

 

              TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                 false,

                        "com.obfuscated.common");

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 21 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 21 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 21 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

   

      public void testAllAccessors_Administration() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.administration",

                  true,

                  0);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 22 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 544 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 513 Successful Verification(s); 31 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

     

      public void testAllAccessors_Development() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.development",

                  true,

                  0);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 47 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 974 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 959 Successful Verification(s); 15 Warning(s); 0 Glitch(es); 1 Caution(s)

****************************************************************************************************

 

Run #10 Timeout For Sanity Check:

 

It is now evident the majority of warnings (and transformation logic) are coming from the “Administration” package.  Further review of the code base indicates there are four packages under “Administration” that could be further decomposed.  After decomposition – the 46 “warnings” are attributable to three packages.

 

Run #11 Summary Results For Three Remaining “Red Bar” Tests:

     

      public void testAllAccessors_Administration_Common() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.administration.common",

                  true,

                  0);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 22 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 216 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 202 Successful Verification(s); 14 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

     

      public void testAllAccessors_Administration_Presentation() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.administration.presentation",

                  true,

                  0);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 0 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 320 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 303 Successful Verification(s); 17 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

     

      public void testAllAccessors_Development() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.development",

                  true,

                  0);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 47 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 974 Successful Verification(s); 0 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 959 Successful Verification(s); 15 Warning(s); 0 Glitch(es); 1 Caution(s)

****************************************************************************************************

 

Run #11a (development package) Log Observation(s):

Of the fifteen (15) “warnings” in the “development” package, two (2) were method pairs intentionally excluded from verification in the testutil-config.xml descriptor document and thirteen (13) were associated with list processing.

 

      + Verification Warning(s) - com.obfuscated.development.forms.DevelopmentForm +

      Warning [# 1]:  Setter = [setEmployeeSkillBO()];  Getter = [getEmployeeSkillBO()]

      Setter first parameter [int] and getter return type [com.obfuscated.development.bo.EmployeeSkillBO] are not TestUtil verifiable.

 

In the thirteen cases represented above, a collection is “set” – however, the “getter” is used to return a specified element of the collection.  One could argue a more standards-based approach would be to use a “getter” and “setter” for the collection, and a method named similarly to getEmployeeSkillBoElement(int index) for returning an element of the collection.  Unfortunately, the discovery is a bit late in the development cycle for the Consulting Architect to instigate a discussion of this coding practice.

 

Run #11a (development package) Response:

Since all 15 TestUtil “warnings” were accounted for, the unit test method was modified to assert fifteen (15) warnings.

 

      public void testAllAccessors_Development() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.development",

                  true,

                  15);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 47 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 959 Successful Verification(s); 15 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 959 Successful Verification(s); 15 Warning(s); 0 Glitch(es); 1 Caution(s)

****************************************************************************************************

 

Run #11b (administration.presentation package) Log Observation(s):

Five (5) violations of the JavaBeans specification within Struts form beans were detected.  Since accessor methods are invoked reflectively by the Jakarta Commons BeanUtil classes – there is no guarantee which overloaded “setter” is invoked by a JRE.

 

      + Verification Warning(s) - com.obfuscated.administration.presentation.forms.MessageForm +

      Warning [# 1]

      Multiple occurrences of setter [setSelectedBusinessGroup] precludes verification.

 

There are ten (10) occurrences of “setters” whose method signature has no parameter.

 

      + Verification Warning(s) - com.obfuscated.administration.presentation.forms.ManageSkillListForm +

      Warning [# 1]:  Setter = [setSelectedBusinessGroup()];  Getter = [getSelectedBusinessGroup()]

      The setter signature has no parameter and can not be TestUtil verified.

 

Run #11b (administration.presentation package) Response:

The five (5) JavaBeans specification violations were remanded to the development team for resolution.

 

Investigation revealed the ten (10) no-parameter “setters” are invoked in the context of instance initialization - with considerable business logic contained therein.  As a coding (and unit test) recommended practice - one might prefer to have the business logic contained explicitly in the constructor or an initialization method with “setters” serving a strictly accessor role.  Given the belated detection within the project lifecycle and tight deadlines – the Consulting Architect chose not to instigate a discussion of this coding practice.

 

Note: This brings up an interesting discussion point.  Some practitioners promote not testing “simple” accessor methods, while at the same time placing considerable business logic within those methods.  Or said another way, if a “getter” has ten lines of logic (on a team committed to testing) – one might be reluctant to argue an exclusion just because the method name begins with the verb “get”.  If nothing else, TestUtil provides visibility to so-called accessor methods that are replete with (business) logic.

 

The remaining two warnings are additional occurrences of “setting” a collection but “getting” an element in the collection (see 11a above).  So, the number of expected "warnings" are asserted to be twelve (12).  The unit test will fail until the JavaBeans Specification violations are resolved.

 

      public void testAllAccessors_Administration_Presentation() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.administration.presentation",

                  true,

                  12);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 0 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 308 Successful Verification(s); 12 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 303 Successful Verification(s); 17 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

 

Run #11c (administration.common package) Response:

The fourteen (14) “warnings” associated with this package are a result of entries already made to the testutil-config.xml descriptor document causing Fortune5 method pairs to be excluded from verification.

 

// Verification Complete (Green Bar)!

      public void testAllAccessors_Administration_Common() {

 

            TestUtil.verifyDirectory(

                  "\\C:\\Projects\\WSAD\\Obfuscated\\JavaSource",

                  false,

                  "com.obfuscated.administration.common",

                  true,

                  14);

      }

 

****************************************************************************************************

*                 TestUtil v. 2.0 - Verify Directory Summary Results

* -------> Skips: 22 Non-Java files, interfaces, or abstract classes not attempted.

* -> Anticipated: 202 Successful Verification(s); 14 Warning(s); 0 Glitch(es); 0 Caution(s)

* -----> Results: 202 Successful Verification(s); 14 Warning(s); 0 Glitch(es); 0 Caution(s)

****************************************************************************************************

 

 

Lessons Learned – What went well?

It was unintentional that individual developers used verifyMutable() (exclusively) and the Consulting Architect used verifyDirectory() (exclusively).  This occurred inadvertently due to the TestUtil product release cycle in relation to the Fortune5 project development cycle.  In retrospect, the approach seems sound.  Individual developers receive immediate feedback on errors within their coding scope; the Lead Developer or Architect responsible for the health of the entire code base receives a broader perspective on coding practices followed and the amount of logic being placed within accessor methods.

 

Lessons Learned – What could be improved?

Clearly, the Consulting Architect should monitor the code base on a timely basis.  Discovery after five (5) occurrences of JavaBeans specification violations – or ten (10) occurrences of no-parameter “setters” is an indicator of a lack of attention to overall recommended practice adherence and coding consistency.  This is particularly true when development is split between on-shore and off-shore and the opportunity for informal coalescence of coding style is geographically impaired.

 

Closing Thought

It is becoming apparent to the author the notion of automated method testing relies heavily on a shared understanding and consistent coding practice for a patterned object (DAO, Business Object, Application Service Object etc.).  Even the JavaBeans specification at 114 pages does not (unless it was missed :-) address the fundamental real-world stylistic issue of how much transformation and/or functional logic should be placed within accessor methods.  The necessity of aligning developer perspectives and coding practices to the extent required for automated method testing to invoke patterned object unit tests – is a feature rather than an encumbrance.  If application code is consistent enough for automated method testing – it is certainly consistent enough for effective human readability!

 

 

Return to TestUtil

 

Marvin Toll – Updated: May, 2006