Using Hamcrest assertions

What is Hamcrest?

Hamcrest provides a library of matcher objects (also known as constraints or predicates) allowing 'match' rules to be defined declaratively. One of the uses for matchers is to define custom rules for unit test assertions. Hamcrest has been ported to AS3 by Drew Bourne, and the project is hosted on GitHub at hamcrest-as3.

Hamcrest is included with FlexUnit4 in the libs folder as a Hamcrest.swc file. In case you don't have this please see the download found at the FlexUnit4 download page.

Hamcrest in Tests

Hamcrest is used in combination with a method called assertThat(), providing a mechanism to create composite checks inline, in a simple and clear fashion.

    [Test]    
    public function shouldDemonstrateHamcrestInTests():void {
        var values:Array = [1, 2, 3, 4];
        assertThat(values, array(1, 2, 3, 4));
    }

The major advantage of using assertThat() and the Hamcrest matchers over traditional assertions such as assertTrue(), assertEquals() is the descriptive failure messages when a matcher (or combination of matchers) does not match successfully.

    // fails with the message:
    // Expected: [<1>, <2>, <3>, <4>]
    //   but: was [<1>, <2>, <3>, <7>, <8>, <9>]
    public function shouldDemonstrateHamcrestDescriptions():void {
        var badValues:Array = [1, 2, 3, 7, 8, 9];
        assertThat(badValues, array(1, 2, 3, 4));
    }

Matchers

Hamcrest comes with a library of useful matchers. They are quite powerful since these can be custom tailored to the specific object and condition you're expecting, since assertEquals, assertTrue and assertFalse don't always provide enough granularity to compare something like a Date object. The Hamcrest library currently contains matchers for collections, Date, number, text and Object types. Explanations of these matchers and how to use them can be found at the hamcrest-as3 wiki with explanations and examples of their uses in FlexUnit as well.

Here are some of the most important ones.

  • Core
    • anything - always matches, useful if you don't care what the object under test is
    • describedAs - decorator to adding custom failure description
    • isA - matches a specific type
    • throws - matches if a function throws the given exception
  • Logical
    • allOf - matches if all matchers match, short circuits (like &&)
    • anyOf - matches if any matchers match, short circuits (like ||)
    • not - matches if the wrapped matcher doesn't match and vice versa
  • Object
    • equalTo - compares objects using
    • sameInstance, strictlyEqualTo - compare objects using=
    • hasProperty - checks that a property exists and, optionally, that it matches the provided matcher
    • hasProperties - similar to hasProperty, but accepts a dictionary of properties and their associated matchers
    • instanceOf - test type
    • notNullValue, nullValue - test for null
  • Collections
    • array - test an array's elements against an array of matchers
    • arrayWithSize - match an array's size against a number
    • hasItem, hasItems - test a collection contains elements
    • everyItem - test that a matcher matches every item in an array
  • Number
    • closeTo - test that values are close to a given value
    • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - test ordering
    • between - test that a value is between two given values
  • Text
    • containsString, endsWith, startsWith - test string matching
    • re - text matches a regular expression
  • Date
    • dateAfter, dateAfterOrEqual, dateBefore, dateBeforeOrEqual - date comparisons
    • dateBetween - test that a date is within a given range
    • dateEqual - tests dates for equality

Hamcrest Example

Hamcrest is based on the idea of matchers which match conditions for your assertions.

For example:

[Test]
public function testGreaterThan():void {
   assertThat( 11, greaterThan(3) );
}

[Test]
public function isItInHere():void {
   var someArray:Array = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
   assertThat( someArray, hasItems("b", "c") );
}

In these examples the classes greaterThan and hasItems take in some arguments to determine what matcher to return. greaterThan returns the matcher class IsGreaterThanMatcher.

More information on Hamcrest

  • No labels