The Artima Developer Community
Sponsored Link

Oh Boy! Another Testing Tool!
Building Conformance and Unit Tests with Artima Testkit
by Bill Venners

<<  Page 5 of 8  >>

Advertisement

Writing Test Methods

Test methods may have one of two signatures:

The "..." in "test..." represents any non-zero length string. Some example test method names are testFest, testimonial, and testOfCharacter.

Test methods indicate success by returning, failure by throwing an exception. The Artima Testkit API includes one exception, TestFailedException, whose purpose is to indicate a failed test. Suite.executeTestMethods interprets any exception thrown from a test method, not just TestFailedException, as an indication of failure.

In the body of test methods, you can take advantage of these six methods declared in superclass Suite:

The verify methods check the specified Boolean condition. If the condition is true, verify returns quietly. Else, verify throws TestFailedException. The verify method that takes a String message parameter uses that String for the detail message of the thrown exception.

The fail methods throw TestFailedException invariably. If a String message or Throwable cause is provided, the fail method uses these as the detail message and cause for the thrown TestFailedException.

Test methods generally do not catch TestFailedException. Instead, they complete abruptly with the exception, thereby indicating failure. The calling method, usually Suite.executeTestMethods, catches the exception and reports the failure to the Reporter. The Reporter in turn passes the information in some manner along to the user.

As an example, here's the testIsLocaleSupported method of class LocalesSuite from the Serviceui CTK:

    public void testIsLocaleSupported() {

        verify(!one.isLocaleSupported(Locale.JAPANESE),
            "one.isLocaleSupported() should return false for Locale.JAPANESE");
        verify(!three.isLocaleSupported(Locale.JAPANESE),
            "three.isLocaleSupported() should return false for Locale.JAPANESE");
        verify(!four.isLocaleSupported(Locale.JAPANESE),
            "four.isLocaleSupported() should return false for Locale.JAPANESE");
        verify(!five.isLocaleSupported(Locale.JAPANESE),
            "five.isLocaleSupported() should return false for Locale.JAPANESE");

        try {
            one.isLocaleSupported(null);
            fail("one.isLocaleSupported() should throw NullPointerException when passed null");
        }
        catch (NullPointerException e) {
            // This is supposed to happen, so just keep going
        }

        verify(three.isLocaleSupported(Locale.ENGLISH),
            "three.isLocaleSupported() should return true for Locale.ENGLISH");
        verify(four.isLocaleSupported(Locale.ENGLISH),
            "four.isLocaleSupported() should return true for Locale.ENGLISH");
        verify(four.isLocaleSupported(Locale.UK),
            "four.isLocaleSupported() should return true for Locale.UK");
        verify(five.isLocaleSupported(Locale.ENGLISH),
            "five.isLocaleSupported() should return true for Locale.ENGLISH");
        verify(five.isLocaleSupported(Locale.UK),
            "five.isLocaleSupported() should return true for Locale.UK");
    }

Inside the testIsLocaleSupported method, I call isLocaleSupported (the target of this test method) several times on various objects from the fixture, making sure it either returns the correct result or throws the expected exception. For example, none of the five Locales objects in the fixture contain the Locale.JAPANESE locale. isLocaleSupported(Locales.JAPANESE) should therefore return false when invoked on any of the locales objects in the fixture. The first verify statement in the method checks to make sure that the empty Locales object referenced from the one instance variable returns false:

        verify(!one.isLocaleSupported(Locale.JAPANESE),
            "one.isLocaleSupported() should return false for Locale.JAPANESE");

In addition, the specification of isLocalesSupported(Locale locale) states that the method should throw NullPointerException if null is passed in its locale parameter. The following code ensures this behavior works according to the specification:

        try {
            one.isLocaleSupported(null);
            fail("one.isLocaleSupported() should throw NullPointerException when passed null");
        }
        catch (NullPointerException e) {
            // This is supposed to happen, so just keep going
        }

The previous code snippet shows one use of the fail method. If one.isLocaleSupporter(null) throws NullPointerException as expected, it will be caught by the empty catch clause and the test method will continue. But if one.isLocaleSupporter(null) returns normally, instead of throwing a NullPointerException as required, the fail method will be invoked resulting in a TestFailedException. If a different exception besides NullPointerException is thrown, then the entire testIsLocaleSupported method will complete abruptly with that exception. The calling method (normally executeTestMethods) will catch any exception and report the failure to the Reporter.

For those familiar with JUnit, Testkit's TestFailedException corresponds to JUnit's AssertionFailedError. Testkit's two verify methods correspond to the JUnit's multitudinous assert methods declared in class Assert. Unlike JUnit, Testkit does not differentiate between "failures" and "errors." JUnit calls any thrown AssertionFailedError a failure, any other thrown exception an error. In Testkit, a test either succeeds or fails. If the test fails, the user can inspect information about the failure to better understand how to correct the problem.

<<  Page 5 of 8  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use