November 19, 2012

How to test a Custom Exception using custom FEST assertions

Introduction

This is part three of my posts on assertions testing using Fest, JUnit and custom Exceptions. The first post was covering the basics of assertions, then followed up with testing custom Exceptions using JUnit and JUnit's ExpectedException class. At this point you should know that you have a custom Runtime Exception class and you would like to test it using the Fluent API provided by FEST.

Custom Assertions with Fest

This blog post will not go into the details on creating a custom assertion, but the solution posted in the Github project does contain a custom assertion. In addition, please refer to the official site docs.

Building off of the last post, you will see that ExpectedException is a great improvement over the @Test(expected) and Try/Catch techniques, however the ExpectedException object can still be improved by adding in a fluent-style API backed by Fest Assertion project. So, how do you do it? Let's get right to the solution!

Expected Exceptions with FEST and JUnit @Rule

Now that we have an understanding of FEST assertions, JUnit's @Rule functionality and ClickConcept's @ExpectedFailure we can combine the first two to provide fluent-style expected exception behavior while testing the assertion class using @ExpectedFailure annotations.

Testing your custom exception with FEST

Let's begin by creating a new @Rule object "ExpectedException" which extends TestRule. When creating the class, we will expose the construction through a simple factory method to return a new ExpectedException. The default factory will return a base implementation where the functionality is muted in all other cases where exceptions are not desired.

We can start out with the code first, but I will explain that in order to build your own custom Fluent API for FEST, you must re-create the API for the base exception assertion. The fluent API you create will be in addition to the FEST exception assertion class. Fluent API help was derived off of several blogs, but the most informative has been http://www.unquietcode.com/blog/2011/programming/using-generics-to-build-fluent-apis-in-java/.

NOTE: AbstractExpectedException encapsulates the base API for FEST's ExceptionAssertion. The code for this is found at the Github site: https://github.com/mike-ensor/fest-backed-expected-exception


public class ExpectedCustomException extends AbstractExpectedException<ExpectedCustomException> {

    private Integer code;

    public static ExpectedCustomException none() {
        return new ExpectedCustomException();
    }

    /**
     * Checks to see if the CustomException has the specified code
     *
     * @param code int
     * @return AbstractExpectedException
     */
    public AbstractExpectedException hasCode(int code) {
        // method telling class that a custom exception is being asked for
        markExpectedException();
        this.code = code;
        return this;
    }

    @Override
    protected void checkAssertions(Exception e) {
        // check parent's exceptions
        super.checkAssertions(e);

        if (getCode() != null) {
            // FEST Custom Assert object
            CustomExceptionAssert.assertThat(e).hasCode(code);
        }
    }

    private Integer getCode() {
        return code;
    }

}

Analysis

In this example, my CustomException has exposed a "code" to store when the exception was created. In order to test this my custom ExpectedException object must look for the proper code on the CustomException object, in a fluent manor.

Here is an example test case to explain how to use your new fluent API Custom Exception test. Take note of the third test case to see the Fluent API in use! (NOTE: Full test cases are available on my github account.

public class CustomExceptionTest {

    @Rule
    public ExpectedCustomException exception =
            ExpectedCustomException.none();

    @Rule
    public ExpectedTestFailureWatcher expectedTestFailureWatcher =
            ExpectedTestFailureWatcher.instance();

    @Test
    public void hasCode_worksAsExpected() {
        exception.hasCode(123);
        throw new CustomException("Message", 123);
    }

    @Test
    @ExpectedFailure
    public void getCode_fails() {
        exception.hasCode(456);
        throw new CustomException("Message", 123);
    }

    @Test
    @ExpectedFailure
    public void getMessageAndCode_codeFailsFirst() {
        exception.hasCode(456).hasMessage("Message");
        throw new CustomException("Message", 123);
    }

}

Summary

Thank you to those of you who have read through this little series covering assertions, how to test exceptions (both the exception flow and custom exceptions) and then on to testing your custom exceptions using FEST assertions. Please come back to my blog in the near future where I will have a REST API checklist to look over when architecting your next REST API.

Those who are reading this blog are most likely a small subset of the software development community, but if you are not, and you find the idea of a fluent-API really cool (as I do), please check out the FEST assertion library. If you are new to test driven development, please take up the practice and try applying to your code immediately. If all developers used TDD as a general practice, the level in quality would grow world wide!

September 25, 2012

Testing Custom Exceptions w/ JUnit's ExpectedException and @Rule


Exception Testing

Why test exception flows? Just like with all of your code, test coverage writes a contract between your code and the business functionality that the code is supposed to produce leaving you with a living documentation of the code along with the added ability to stress the functionality early and often. I won't go into the many benefits of testing instead I will focus on just Exception Testing.

There are many ways to test an exception flow thrown from a piece of code. Lets say that you have a guarded method that requires an argument to be not null. How would you test that condition? How do you keep JUnit from reporting a failure when the exception is thrown? This blog covers a few different methods culminating with JUnit's ExpectedException implemented with JUnit's @Rule functionality.


The "old" way

In a not so distant past the process to test an exception required a dense amount of boilerplate code in which you would start a try/catch block, report a failure if your code did not produce the expected behavior and then catch the exception looking for the specific type. Here is an example:

public class MyObjTest {

    @Test
    public void getNameWithNullValue() {

        try {
            MyObj obj = new MyObj();
            myObj.setName(null);
            
            fail("This should have thrown an exception");

        } catch (IllegalArgumentException e) {
            assertThat(e.getMessage().equals("Name must not be null"));
        }
    }
}

As you can see from this old example, many of the lines in the test case are just to support the lack of functionality present to specifically test exception handling. One good point to make for the try/catch method is the ability to test the specific message and any custom fields on the expected exception. We will explore this a bit further down with JUnit's ExpectedException and @Rule annotation.


JUnit adds expected exceptions

JUnit responded back to the users need for exception handling by adding a @Test annotation field "expected". The intention is that the entire test case will pass if the type of exception thrown matched the exception class present in the annotation.

public class MyObjTest {

    @Test(expected = IllegalArgumentException.class)
    public void getNameWithNullValue() {
        MyObj obj = new MyObj();
        myObj.setName(null);
    }
}

As you can see from the newer example, there is quite a bit less boiler plate code and the test is very concise, however, there are a few flaws. The main flaw is that the test condition is too broad. Suppose you have two variables in a signature and both cannot be null, then how do you know which variable the IllegalArgumentException was thrown for? What happens when you have extended a Throwable and need to check for the presence of a field? Keep these in mind as you read further, solutions will follow.


JUnit @Rule and ExpectedException

If you look at the previous example you might see that you are expecting an IllegalArgumentException to be thrown, but what if you have a custom exception? What if you want to make sure that the message contains a specific error code or message? This is where JUnit really excelled by providing a JUnit @Rule object specifically tailored to exception testing. If you are unfamiliar with JUnit @Rule, read the docs here.


ExpectedException

JUnit provides a JUnit class ExpectedException intended to be used as a @Rule. The ExpectedException allows for your test to declare that an exception is expected and gives you some basic built in functionality to clearly express the expected behavior. Unlike the @Test(expected) annotation feature, ExpectedException class allows you to test for specific error messages and custom fields via the Hamcrest matchers library.

An example of JUnit's ExpectedException

import org.junit.rules.ExpectedException;

public class MyObjTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void getNameWithNullValue() {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Name must not be null");

        MyObj obj = new MyObj();
        obj.setName(null);
    }
}

As I eluded to above, the framework allows you to test for specific messages ensuring that the exception being thrown is the case that the test is specifically looking for. This is very helpful when the nullability of multiple arguments is in question.


Custom Fields

Arguably the most useful feature of the ExpectedException framework is the ability to use Hamcrest matchers to test your custom/extended exceptions. For example, you have a custom/extended exception that is to be thrown in a method and inside the exception has an "errorCode". How do you test that functionality without introducing the boiler plate code from the try/catch block listed above? How about a custom Matcher!

This code is available at: https://github.com/mike-ensor/custom-exception-testing


Solution: First the test case

import org.junit.rules.ExpectedException;

public class MyObjTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void someMethodThatThrowsCustomException() {
        thrown.expect(CustomException.class);
        thrown.expect(CustomMatcher.hasCode("110501"));

        MyObj obj = new MyObj();
        obj.methodThatThrowsCustomException();
    }
}

Solution: Custom matcher

import com.thepixlounge.exceptions.CustomException;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class CustomMatcher extends TypeSafeMatcher<CustomException> {

    public static BusinessMatcher hasCode(String item) {
        return new BusinessMatcher(item);
    }

    private String foundErrorCode;
    private final String expectedErrorCode;

    private CustomMatcher(String expectedErrorCode) {
        this.expectedErrorCode = expectedErrorCode;
    }

    @Override
    protected boolean matchesSafely(final CustomException exception) {
        foundErrorCode = exception.getErrorCode();
        return foundErrorCode.equalsIgnoreCase(expectedErrorCode);
    }

    @Override
    public void describeTo(Description description) {
        description.appendValue(foundErrorCode)
                .appendText(" was not found instead of ")
                .appendValue(expectedErrorCode);
    }
}

NOTE: Please visit https://github.com/mike-ensor/custom-exception-testing to get a copy of a working Hamcrest Matcher, JUnit @Rule and ExpectedException.

And there you have it, a quick overview of different ways to test Exceptions thrown by your code along with the ability to test for specific messages and fields from within custom exception classes. Please be specific with your test cases and try to target the exact case you have setup for your test, remember, tests can save you from introducing side-effect bugs!

September 18, 2012

Brief Overview of Java Assertions

What are asserts?

An assertion is a predicate (a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. [wikipedia]

Traditional asserts

Traditional testing frameworks started with the built in keyword assert.

An example of the keyword assert:

assert <condition> value

Assert has a few drawbacks including stopping the test execution and lengthy and hard to describe assert statements.

Second generation assertions

Along comes JUnit's assert framework. Built on top of the assert keyword, JUnit provided developers the ability to be more descriptive about the testing statements.

An example of JUnit's asserts:
// asserts that the condition must be true
assertTrue("This should be true", "abc".equalsIgnoreCase("ABC"));
// asserts that the object must not be null
assertNotNull(new MyObject());
//...
assertFalse(false == true);
//
assertNull(null);
// etc...

While there are some improvements on readability and usability to the basic assert keyword provided by JUnit, they share some of the same drawbacks in that many developers just use the "assertTrue()", "assertEquals()" and "assertFalse()" methods still providing a very cryptic assertion statement.

Third generation assertions

In an effort to guide developers into writing test assertions that are more readable and usable the Hamcrest library was created which switched the philosophy from many assert functions to just one basic function. The fundamental thought is that the assert is the same but the conditions will change. Hamcrest was built using the concepts of BDD (behavior driven design) where the test assertion is closer to that of a sentence.

An example of hamcrest assertions

@Test
public void showoffSomeHamcrestAssertsAndMatchers() {
    // asserts that string "abc" is "ABC" ignoring case
    assertThat("abc", is(equalToIgnoringCase("ABC")));
    assertThat(myObject.getFirst(), is("Mike!"));
    assertThat(myObject.getAddress(), is(notNullValue));
}

Hamcrest is a great improvement on top of the JUnit framework providing a flexible and readable testing platform. Hamcrest + JUnit is a comprehensive testing framework and when combined with Mockito (or other mocking framework) can provide a very descriptive and thorough unit testing solution. One of the drawbacks to using Hamcrest is that while descriptive, multiple assertions must be made to ensure that a test case has been covered. Many TDD purest agree that a test case should contain one and only one assertion, but how is this possible with a complex object? (purest will say refactoring, but oftentimes this is not feasible)

Fourth generation frameworks

And finally we come to the present with the latest assertion frameworks. Fest Assertion framework takes off where Hamcrest stopped providing a fluent style assertion framework giving the developer the ability to test objects with a single assertion.

An example of Fest assertions

@Test
public void getAddressOnStreet() {
    List<Address> addresses = addressDAO.liveOnStreet("main");
    assertThat(addresses).hasSize(10).contains(address1, address2);
    assertThat(stringObj).hasSize(7).isEqualToIgnoringCase("abcdefg");
}

As you can see, FEST exceptions provide a cleaner approach to assertions. FEST is very extensible and easy to use.

Conclusion

Assertions are a key tool in a professional developer's toolbox in which to stress test their code. This post is a part in a series with the culmination being a fluent style ExpectedException mechanism, backed by Fest, in which to add better clarity to your test cases when exceptions are being introduced. Feel free to read the lead up to this post; Allowing known failing JUnit Tests to pass test cases.

NOTE: This blog is providing an overview on assertion frameworks it should be noted that there are various other second and third generation testing frameworks that strive to provide better clarity and usability for testing including notables such as TestNG and JTest

September 9, 2012

Allowing JUnit Tests to Pass Test Case on Failures


Why create a mechanism to expect a test failure?

There comes a time when one would want and expect a JUnit @Test case fail. Though this is pretty rare, it happens. I had the need to detect when a JUnit Test fails and then, if expected, to pass instead of fail. The specific case was that I was testing a piece of code that could throw an Assert error inside of a call of the object. The code was written to be an enhancement to the popular new Fest Assertions framework, so in order to test the functionality, one would expect test cases to fail on purpose.


A Solution

Jump to the Code
One possible solution is to utilize the functionality provided by a JUnit @Rule in conjunction with a custom marker in the form of an annotation.


Why use a @Rule?

@Rule objects provide an AOP-like interface to a test class and each test cases. Rules are reset prior to each test case being run and they expose the workings of the test case in the style of an @Around AspectJ advice would.

Required code elements

  • @Rule object to check the status of each @Test case
  • @ExpectedFailure custom marker annotation
  • Test cases proving code works!
  • Optional specific exception to be thrown if annotated test case does not fail

NOTE: working code is available on my github page and has been added to Maven Central. Feel free to Fork the project and submit a pull request

Maven Usage

<dependency>
    <groupId>com.clickconcepts.junit</groupId>
    <artifactId>expected-failure</artifactId>
    <version>0.0.9</version>
</dependency>

Example Usage

In this example, the "exception" object is a Fest assertion enhanced ExpectedException (look for my next post to expose this functionality). The expected exception will make assertions and in order to test those, the test case must be marked as @ExpectedFailure

public class ExceptionAssertTest {

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Rule
    public ExpectedTestFailureWatcher watcher = ExpectedTestFailureWatcher.instance();

    @Test
    @ExpectedFailure("The matcher should fail becasue exception is not a SimpleException")
    public void assertSimpleExceptionAssert_exceptionIsOfType() {
        // expected exception will be of type "SimpleException"
        exception.instanceOf(SimpleException.class);
        // throw something other than SimpleException...expect failure
        throw new RuntimeException("this is an exception");
    }
}

Implementation of Solution

Reminder, the latest code is available on my github page.

@Rule code (ExpectedTestFailureWatcher.java)

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
// YEAH Guava!!
import static com.google.common.base.Strings.isNullOrEmpty;

public class ExpectedTestFailureWatcher implements TestRule {

    /**
     * Static factory to an instance of this watcher
     *
     * @return New instance of this watcher
     */
    public static ExpectedTestFailureWatcher instance() {
        return new ExpectedTestFailureWatcher();
    }

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                boolean expectedToFail = description.getAnnotation(ExpectedFailure.class) != null;
                boolean failed = false;
                try {
                    // allow test case to execute
                    base.evaluate();
                } catch (Throwable exception) {
                    failed = true;
                    if (!expectedToFail) {
                        throw exception; // did not expect to fail and failed...fail
                    }
                }
                // placed outside of catch
                if (expectedToFail && !failed) {
                    throw new ExpectedTestFailureException(getUnFulfilledFailedMessage(description));
                }
            }

            /**
             * Extracts detailed message about why test failed
             * @param description
             * @return
             */
            private String getUnFulfilledFailedMessage(Description description) {
                String reason = null;
                if (description.getAnnotation(ExpectedFailure.class) != null) {
                    reason = description.getAnnotation(ExpectedFailure.class).reason();
                }
                if (isNullOrEmpty(reason)) {
                    reason = "Should have failed but didn't";
                }
                return reason;
            }
        };
    }
}

@ExpectedFailure custom annotation (ExpectedFailure.java)

import java.lang.annotation.*;

/**
 * Initially this is just a marker annotation to be used by a JUnit4 Test case in conjunction
 * with ExpectedTestFailure @Rule to indicate that a test is supposed to be failing
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface ExpectedFailure {
    // TODO: enhance by adding specific information about what type of failure expected
    //Class assertType() default Throwable.class;

    /**
     * Text based reason for marking test as ExpectedFailure
     * @return String
     */
    String reason() default "";
}

Custom Exception (Optional, you can easily just throw RuntimeException or existing custom exception)

public class ExpectedTestFailureException extends Throwable {
    public ExpectedTestFailureException(String message) {
        super(message);
    }
}

Can't one exploit the ability to mark a failure as expected?

With great power comes great responsibility, it is advised that you do not mark a test as being @ExpectedFailure if you do not understand exactly why the test if failing. It is recommended that this testing method be implemented with care. DO NOT use the @ExpectedFailure annotation as an alternative to @Ignore

Possible future enhancements could include ways to specify the specific assertion or the specific message asserted during the test case execution.

Known issues

In this current state, the @ExpectedFailure annotation can cover up additional assertions and until the future enhancements have been put into place, it is advised to use this methodology wisely.

March 19, 2012

Maven 3 Site Docs Part 1: Basic Site Documentation

What is documentation?

Documentation
The process of documenting knowledge

Documentation for software developers are documents that describe how to run or use the artifact/project. Typically documentation provides any exposed settings, their uses and default values. In addition information about integration, entry and exit points such as JMS queues, JMX MBeans, DataSource objects and/or JNDI variables in order to run and use the artifact. There are many programs and standards to produce this level of documentation including MS word, Sharepoint, doxygen, Latex, Wiki, markdown, textile, etc.

Outside of artifact specific documentation team leads, architects and project managers usually ask for JavaDocs to be included. JavaDocs, if combined with Maven provide more documentation for your IDE and better information for the consumers of your artifact. Other important documentation includes testing reports, test coverage, static analysis tools, dependencies of your artifact, change log and issue management such as Jira or Bugzilla.

Why create docs?

The best reason to care about documentation is to provide information for external developers and team members outside of the project's development environment. Documentation can be utilized inside of IDEs as well and face it, how many times do you wish you had sources and/or JavaDocs for a dependency when you were programming or to send back an email with the site docs so someone can be self-served rather than take your time.

Problems with traditional documentation

The largest complaint with traditional documentation is that it becomes stale over time. Time is never allocated in a project&dagger to provide or update documentation and stale docs can lead a developer or team down many wrong paths leading to hours or days of misinformation lead rabbit holes.

† Agile, SCRUM and Lean processes should allow time to be built-in to handle technical debt like documentation, even thought it is called the "necessary evil". Read more here

Secondly, developers are the ones who are askedforced to maintain the documentation and typically developers are not great in the writing department and unless segments of the documentation process are automated, developers are people and we forget.

Last major problem with traditional documentation is that it is typically not automated and is an extra step during the build/release cycle. Any process in the build cycle that is not automated and tested will break down at some point. Humans are great at abstract thinking, not repetitive processes.

Solution to the problems

As stated above, the main problems are developers maintaining all documentation and documentation that is either built outside of the immediate environment or is not automated. This is where Maven's site documentation comes in. Maven was built with the understanding that documentation needs to be automated and has been progressively improved throughout updates to the maven project.

The most common case for Maven site docs is to deploy generated documentation to an external web server via SCP, FTP, WebDAV or SFTP. The site plugin takes use of Apache's Wagon library for secure transfer of docs. Most of the time the site docs are generated during the release† or deploy phases and generate on the verify phase.

† Release isn't a phase in maven, it is a plugin, but it is considered a best practice when publishing versioned artifacts to a maven repository

Maven 3 vs Maven 2

Maven decided to change the way that reports were collected and generated in between the Maven 2 and Maven 3 releases. In Maven 2, the POM would have a section called >reports< where plugins that handled ReportSet would be handled. In Maven 3, there is now a plugin that handles and collates the ReportSets instead of Maven handling it. The plugin is called maven-project-info-reports-plugin and documentation can be found here.

Sources for this series of blog post

I have provided a link to a fully functional multi-module maven project that publishes to both http://mike-ensor.github.com/multi-module-site-doc-project/index.html and locally to ${env.HOME}/sitedocs/${project.artifactId}.

https://github.com/mike-ensor/multi-module-site-doc-project.

Maven 3 Site Docs

There are two important elements with respect to site docs for Maven. Plugins, which generate ReportSet elements and Site Doc/Descriptors.

Plugins

Plugins are an important part of the documentation process and will typically run throughout the maven build lifecycle generating artifacts for the plugin phase that generates the ReportSet. A good example would be the maven-checkstyle-plugin. The plugin is typically bound to the process-resources or packakge phases so that developers know they have a checkstyle violation early in the build lifecycle. The plugin generates a checkstyle.xml document that is then used in the site phase by the maven-project-info-reports-plugin to generate a checkstyle report page.

Maven Site Plugin

The maven-site-plugin is the main plugin that is used to crate all site documentation. Each plugin that produces and/or consumes a ReportSet will need to be configured inside of the <reportPlugins> section. NOTE: This is where the Wagon plugin is set as a dependency. The Site plugin will use the <distributionManagement><site> line to determine where the site docs are to be published (SCM, WebDAV, SFTP, etc)

<plugin>
 <artifactId>maven-site-plugin</artifactId>
 <version>${plugin.maven-site.version}</version>
 <dependencies>
  <dependency><!-- add support for ssh/scp -->
   <groupId>org.apache.maven.wagon</groupId>
   <artifactId>wagon-ssh</artifactId>
   <version>${plugin.wagon-ssh.version}</version>
  </dependency>
 </dependencies>
 <configuration>
  <attach>true</attach>
  <reportPlugins>
   <plugin>
   ...
   ... Plugins go here
   ....
   </plugin>
  </reportPlugins>
  <attach>true</attach>
 </configuration>
</plugin>

Maven Project Info Report Plugin

The maven-project-info-report-plugin is the main plugin used by the maven-site-plugin that Maven 3 utilizes to collate and produce the common site reporting docs for the artifact

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-project-info-reports-plugin</artifactId>
    <configuration>
        <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
        <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
    </configuration>
    <!-- simpler configuration without
        reportSets available for usual cases -->
    <!-- distribution-management,
        index, dependencies, help,
        issue-tracking, plugins,
        cim, license, dependency-management,
        mailing-list, project-team,
        dependency-convergence,
        scm, plugin-management,
        modules, summary -->
    <reports>
        <report>summary</report>
        <report>dependencies</report>
        <report>project-team</report>
        <report>issue-tracking</report>
        <report>scm</report>
        <report>cim</report>
        <report>modules</report>
        <report>plugins</report>
    </reports>
</plugin>

Take a quick look at the types of reports that are automatically generated using the maven-project-info-reports-plugin. Many of these automatically generated reports provide additional information on top of the redundant information provided by the below listed plugins.

List of automatically provided reports
  • distribution-management
  • index
  • dependencies
  • help
  • issue-tracking
  • plugins
  • cim
  • license
  • dependency-management
  • mailing-list
  • project-team
  • dependency-convergence
  • scm
  • plugin-management
  • modules
  • summary

Common Plugins

Checkstyle - maven-checkstyle-plugin – Provides static analysis on source files – NOTE: Checkstyle needs to be run during build AND report phases

Example report plugin

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-checkstyle-plugin</artifactId>
 <configuration>
  <skip>${checkstyle.skip}</skip>
  <configLocation>${checkstyle.configUrl}</configLocation>
  <failsOnError>false</failsOnError>
  <enableRulesSummary>true</enableRulesSummary>
  <includeTestSourceDirectory>true</includeTestSourceDirectory>
 </configuration>
</plugin>

NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.

FindBugs - maven-findbugs-plugin – Provides static analysis on source files – Plugin does not need to be run outside of report phase

Example report plugin

<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>findbugs-maven-plugin</artifactId>
 <configuration>
  <skip>${findbugs.skip}</skip>
  <xmlOutput>true</xmlOutput>
 </configuration>
</plugin>

NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.

Cobertura - maven-cobertura-plugin – Provides code coverage during Unit Test (test) phase. NOTE: Must be run during build AND during reporting phases

Example report plugin

<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>cobertura-maven-plugin</artifactId>
 <configuration>
  <skip>${cobertura.skip}</skip>
 </configuration>
</plugin>

NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.

PMD and CPD - maven-pmd-plugin – Provides static analysis (PMD) and code duplication/cut-copy-paste detection for artifact. Read more about the PMD plugin here.

Example report plugin

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-pmd-plugin</artifactId>
 <configuration>
  <skip>${pmd.skip}</skip>
  <targetJdk>${maven.compiler.source}</targetJdk>
  <sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
  <minimumTokens>100</minimumTokens>
  <rulesets>
   <ruleset>${maven-pmd-plugin.configLocation}</ruleset>
  </rulesets>
  <failOnViolation>false</failOnViolation>
 </configuration>
</plugin>

Surefire and Failsafe - maven-surefire-report-plugin – Creates reports based on tests cases for unit tests and optionally integration tests. NOTE, This is a different plugin than the maven-surefire-plugin, this is the report plugin that operates on the ResultSet for both Surefire and Failsafe. Both Surefire and Failsafe must be run during the build for this plugin to generate reports.

Example report plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-report-plugin</artifactId>
    <reportSets>
        <reportSet>
            <id>integration-tests</id>
            <reports>
                <report>report-only</report>
                <report>failsafe-report-only</report>
            </reports>
        </reportSet>
    </reportSets>
</plugin>

JavaDoc - maven-javadoc-plugin – Bundles JavaDocs into the reporting structure. NOTE, this does not need to be run during the standard build, only during the reporting phase

Example report plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <configuration>
        <skip>${javadocs.skip}</skip>
        <failOnError>false</failOnError>
    </configuration>
</plugin>

JXR - maven-jx-plugin – Builds cross-link information for classes. Checkstyle, PMD, FindBugs, JavaDocs and various other plugins can utilize the JXR configuration. NOTE, this plugin must be run at an early place in the Maven lifecycle (suggest process-resources) in addition to the sitedoc plugin section.

Example report plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jxr-plugin</artifactId>
    <configuration>
        <aggregate>true</aggregate>
    </configuration>
</plugin>

Useful Plugins

Other handy plugins to use for site documentation include:

End of Part 1

The next post will cover the developer portion of the documentation; more specifically covering XDoc and APT. The site documentation is robust and the next post will show how to program some of the XDoc portions of the docs by leveraging Velocity templates.

The last part of this blog post will cover multi-module projects. In addition, that post will show how to deploy site-docs to a Github Pages so you can have site docs at http://<username>.github.com/<your-project>.

February 21, 2012

Colorized Maven Output on Mac OSX

Overview

Unlike many other open source build tools (for example, git) Maven does not provide any type of colorized output. Maven's excessive amount of output can be hard to read and you tend to get lost in the sea of text. My current client I've been given a Mac to use and quickly found out that the existing Linux scripts did not work with iTerm. My solution, take the existing Linux scripts and modify for the Mac OSX.

Approach

Since Maven does not have colorized output, the only option is to use "sed" (stream editor) that takes the output of maven, matches strings with regex and then adds in color codes. The terminal does not escape ansi colors during the stream editing phase. The solution is to use the "tput" command along with setab and setaf for the background and foreground respectively.

Example of ANSI colors

echo -e "\033[1;34RED TEXT\[0m"

Example of TPUT colors

echo -e "${`tput setaf 1`}RED TEXT${`tput sgr0`}"

The Script

#!/bin/sh

# Written by Mike Ensor (mike@ensor.cc)
# Copywrite 2012
# Use as needed, modify, have fun!
# This is intended to be used for Maven3 + Mac OSX
#
# To use:
# in your ".bashrc" or ".bash_profile" add the following line:
# source ~//colorize-maven.sh
#

#Predefine all variables
c_black=
c_cyan=
c_magenta=
c_red=
c_white=
c_green=
c_yellow=
c_blue=
c_bg_black=
c_bg_cyan=
c_bg_magenta=
c_bg_red=
c_bg_white=
c_bg_green=
c_bg_yellow=
c_bg_blue=
c_end=
c_bold=

xterm_color() {
 # 0 Black
 # 1 Red
 # 2 Green
 # 3 Yellow
 # 4 Blue
 # 5 Magenta
 # 6 Cyan
 # 7 White

    # Yes, this could be a map
    c_bold=`tput setaf 0`
    c_bg_bold=`tput setab 0`
    c_black=`tput setab 0`
    c_bg_black=`tput setab 0`
    c_cyan=`tput setaf 6`
    c_bg_cyan=`tput setab 6`
    c_magenta=`tput setaf 5`
    c_bg_magenta=`tput setab 5`
    c_red=`tput setaf 1`
    c_bg_red=`tput setab 1`
    c_white=`tput setaf 7`
    c_bg_white=`tput setab 7`
    c_green=`tput setaf 2`
    c_bg_green=`tput setab 2`
    c_yellow=`tput setaf 3`
    c_bg_yellow=`tput setab 3`
    c_blue=`tput setaf 4`
    c_bg_blue=`tput setab 4`
    c_end=`tput sgr0`
}

#This is not used (yet)
ansi_color() {
    c_bold=   '[1m'
    c_blue=   '[1;34m'
    c_black=  '[1;30m'
    c_green=  '[1;32m'
    c_magenta='[1;35m'
    c_red=    '[1;31m'
    c_cyan=   '[1;36m'
    c_end=    '[0m'
}

color_maven() {

    # pick color type
    if [ $TERM = 'xterm-color' ]
    then
        xterm_color
#    elif [ $TERM = 'ansi' ]
#    then
#     ansi_color
 else
     echo "${c_red}WARNING:::Terminal '${TERM}' is not supported at this time. Colorized output will not happen for Maven${c_end}"
 fi

 error=${c_bold}${c_red}
 info=${c_white}
 warn=${c_yellow}
 success=${c_green}
 projectname=${c_bold}${c_cyan}
 skipped=${c_white}
 downloading=${c_magenta}

 $MAVEN_HOME/bin/mvn $* | sed -e "s/(\[INFO\]) Building( .*)/ ${info}\1${projectname}\2 ${c_end}/g" \
  -e "s/(Time elapsed: )([0-9]+[.]*[0-9]*.sec)/${c_cyan}\1${c_white}\2${c_end}/g" \
  -e "s/(Downloading: .*)/${downloading}\1${c_end}/g" \
  -e "s/BUILD FAILURE/${error}BUILD FAILURE${c_end}/g" \
  -e "s/WARNING: ([a-zA-Z0-9.-/\\ :]+)/${warn}WARNING: \1${c_end}/g" \
  -e "s/SEVERE: (.+)/${c_white}${c_bg_red}SEVERE: \1${c_end}/g" \
  -e "s/Caused by: (.+)/${c_white}${c_bg_green}Caused by: \1${c_end}/g" \
  -e "s/Running (.+)/${c_green}Running \1${c_end}/g" \
  -e "s/FAILURE (\[[0-9]+.[:0-9]+s\])/${error}FAILURE \1${c_end}/g" \
  -e "s/SUCCESS (\[[0-9]+.[:0-9]+s\])/${success}SUCCESS \1${c_end}/g" \
  -e "s/(\[INFO.*)/${info}\1${c_end}/g" \
  -e "s/INFO: (.+)/${c_white}INFO: \1${c_end}/g" \
     -e "s/(\[WARN.*)/${warn}\1${c_end}/g" \
     -e "s/(\[ERROR.*)/${error}\1${c_end}/g" \
     -e "s/(<<< FAILURE!)/${error}\1${c_end}/g" \
     -e "s/Tests run: ([0-9]*), Failures: ([0-9]*), Errors: ([0-9]*), Skipped: ([0-9]*)/${c_green}Tests run: \1 ${c_end}, Failures: ${warn}\2 ${c_end}, Errors: ${error}\3 ${c_end}, Skipped:  ${skipped}\4 ${c_end}/g"
}

alias mvn=color_maven

NOTE: This script is intended to be used with Green text on Black background. Adjust the colors as you want to come up with something more personal

Download script from Github

Click here to view Gist on Github

How to install/use

In your ".bashrc" or ".bash_profile" add the following line:

source ~/<path to script>/colorize-maven.sh

January 17, 2012

Mocking with JodaTime's DateTime and Google Guava's Supplier

 

Introduction

If you're a seasoned unit tester, you've learned to take note when you see any code working with time, concurrency, random, persistence and disc I/O.

The reason for this is that tests can be very brittle and sometimes down-right impossible to test properly. This post will show how to abstract out "time" by injecting a replacement for it in the consumer.  This post will be using Spring 3 as the Dependency Injection container, though Guice, other DI containers or constructor/setters on POJOs would work as well.  I will also ignore Locales since the focus is on the injection of the DateTime, not DateTime itself.

Existing code

You've been handed a piece of code to unit test (or you are creating one and this is your first stab at it).  Our first piece of code, only one class: (This class is a Spring 3.1 controller and the purpose is to return back the current time as a String)

@Controller
@RequestMapping(value = "/time")
@VisibleForTesting
class TimeController {

    @RequestMapping(value = "/current", method = RequestMethod.GET)
    @ResponseBody
    public String showCurrentTime() {
        // BAD!!! Can't test
        DateTime dateTime = new DateTime();
        return DateTimeFormat.forPattern("hh:mm").print(dateTime);
    }
}

Take note that the class does a "new DateTime()" in the class.  Here is the corresponding test class:

What happens when we run the test?  How about assuming we have a very slow machine. You could (and most likely will) end up with your comparison DateTime to be different than the returned DateTime. This is a problem!

First thing to do is to remove the dependency, but how are we going to do this?  If we make the DateTime a field on the class, we will still have the same problem.  Introduce Google Guava's Supplier interface.


Google Guava Supplier

The Supplier interface only has one method, "get()" which will return an instance of whatever the supplier is setup for.  An example, the supplier will return a user's first name if they have logged in, and a default one if they have not:

public class FirstNameSupplier implements Supplier<String> {

    private String value;
    private static final String DEFAULT_NAME = "GUEST";

    public FirstNameSupplier() {
        // Just believe that this goes and gets a User from somewhere
        String firstName = UserUtilities.getUser().getFirstName();
        // more Guava
        if(isNullOrEmpty(firstName)) {
            value = DEFAULT_NAME;
        } else {
            value = firstName;
        }
    }

    @Override
    public String get() {
        return value;
    }
}

To your implementing method, you don't care what the first name is, only that you get one.


Refactoring out DateTime

Let's move on. For a much more real example of using a Supplier (and the point of this post) let's implement a DateTime supplier to give us back the current DateTime. While we're at it, let's also create an interface so that we can create mock implementations for testing:

public interface DateTimeSupplier extends Supplier<DateTime> {
    DateTime get();
}

and an implementation:

public class DateTimeUTCSupplier implements DateTimeSupplier {
    @Override
    public DateTime get() {
        return new DateTime(DateTimeZone.UTC);
    }
}

Now we can take the DateTimeUTCSupplier and inject that into our code that needs the current DateTime as the DateTimeSupplier interface:

@Controller
@RequestMapping(value = "/time")
@VisibleForTesting
class TimeController {

    @Autowired
    @VisibleForTesting
    // Injected DateTimeSupplier
    DateTimeSupplier dateTime;

    @RequestMapping(value = "/current", method = RequestMethod.GET)
    @ResponseBody
    public String showCurrentTime() {
        return DateTimeFormat.forPattern("hh:mm").print(dateTime.get());
    }
}

In order to test this, we'll need to create a MockDateTimeSupplier and have a controller to pass in the specific instance we want to return:

public class MockDateTimeSupplier implements DateTimeSupplier {

    private final DateTime mockedDateTime;

    public MockDateTimeSupplier(DateTime mockedDateTime) {
        this.mockedDateTime = mockedDateTime;
    }

    @Override
    public DateTime get() {
        return mockedDateTime;
    }
}

Notice that the object being saved is passed in via the constructor. This will not get you the current date/time back, but will return back the specific instance you want

and finally our test that exercises (slightly) the TimeController we implemented above:

public class TimeControllerTest {

    private final int HOUR_OF_DAY = 12;
    private final int MINUTE_OF_DAY = 30;

    @Test
    public void testShowCurrentTime() throws Exception {
        TimeController controller = new TimeController();
        // Create the mock DateTimeSupplier with our known DateTime
        controller.dateTime = new MockDateTimeSupplier(new DateTime(2012, 1, 1, HOUR_OF_DAY, MINUTE_OF_DAY, 0, 0));

        // Call our method
        String dateTimeString = controller.showCurrentTime();

        // Using hamcrest for easier to read assertions and condition matchers
        assertThat(dateTimeString, is(String.format("%d:%d", HOUR_OF_DAY, MINUTE_OF_DAY)));
    }

}

Conclusion

This post has shown how to use Google Guava's Supplier interface to abstract out a DateTime object so you can better design your implementations with unit testing in mind! Suppliers are a great way to solve the "just give me something", mind you it's a known type of something.


Good luck!