You are currently browsing the Philipp Meier's weblog blog archives for March, 2004


marketing
e-mail

Cut the Stacktrace for custom Junit Assertions

It’s often desirable to refactor common assertions into a seperate method when doing unit tests. Junit e.g. does not provide a default method to test if a Collections is empty or contains a certain single element. The straight forward idea of refactoring the assertions into a method works but the stacktrace shown if the method fails is annoying:

public class TestCaseHelper {
    public static void assertContainsOnly(Object item, List result) {
        Assert.assertNotNull(result);
        Assert.assertEquals(1, result.size());
        Assert.assertEquals(item, result.get(0));
}

Failures of this method will give a stacktrace like the following:

junit.framework.AssertionFailedError: expected:<1> but was:<0>
	at TestCaseHelper.assertContainsOnly(TestCaseHelper.java:15)
	at TestCaseHelperDemo.testAssertContainsOnly(TestCaseHelperDemo.java:14)
...

I found this highly annoying because I wanted the topmost frame to be
at TestCaseHelperDemo.testAssertContainsOnly(TestCaseHelperDemo.java:14)
and I want to provide a custom message to the set of three assertions.

The solutions lies in mangling the exceptions stackstrace. java.lang.Exception provides a method setStackTrace since 1.4 which is very usefull for this:

public class TestCaseHelper {
    public static void assertContainsOnly(Object item, List result) {
        try {
            Assert.assertNotNull(result);
            Assert.assertEquals(1, result.size());
            Assert.assertEquals(item, result.get(0));
        } catch (AssertionFailedError x) {
            String message = "Expected exacly one item in List. Expected <" + item + ">";
            throwMangledException(message);
        }
    }

    private static void throwMangledException(String message) {
        AssertionFailedError e = new AssertionFailedError(message);
        e.fillInStackTrace();
        StackTraceElement[] stackTrace = e.getStackTrace();
        final int FRAMES_TO_POP = 2;
        StackTraceElement[] newStackTrace = new StackTraceElement[stackTrace.length-FRAMES_TO_POP];
        System.arraycopy(stackTrace, FRAMES_TO_POP, newStackTrace, 0, newStackTrace.length);
        e.setStackTrace(newStackTrace);
        throw e;
    }
}

The trick is to get a stacktrace by invoking fillInStackStrace, to pop the topmost frame and to throw a new Exception with the mangled stacktrace. The stacktrace reported now is reduced to what I’m interested in:

junit.framework.AssertionFailedError: Expected exacly one item in List. Expected <java.lang.Object@1f5d386>
	at de.projectparcel.junit.TestCaseHelperDemo.testAssertContainsOnly(TestCaseHelperDemo.java:14)
...
api

Introduction to the new reporting capabilities of Perl 6

Damian Conway writes quite extensively about generating reports using Perl 6 in perl.com: Exegesis 7 [Feb. 27, 2004].

I really would like to generate reports like the following in java, too:

print form
        :interleave, <<EOFORMAT,
            Name:             Biography:
              {[[[[[[[[[[[[}    {[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[}
                                {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
            Status:             {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
              {[[[[[[[[[[[[}    {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
                                {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
            Comments:           {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
              {[[[[[[[[[[[}     {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}
            EOFORMAT
        $name,
        $biography,
        $status,
        $comments;

And get:

Name:             Biography:                            
      William           William Shakespeare was born on    
      Shakespeare       April 23, 1564 in Strathford-upon- 
                        Avon, England; he was third of     
    Status:             eight children from Father John    
      Deceased (1564    Shakespeare and Mother Mary Arden. 
      -1616)            Shakespeare began his education at 
                        the age of seven when he probably  
    Comments:           attended the Strathford grammar    
      Theories          school. The school provided        
      abound as to      Shakespeare with his formal        
      the true          education. The students chiefly    
      author of his     studied Latin rhetoric, logic, and 
      plays. The        literature. His knowledge and      
      prime             imagination may have come from his 
      alternative       reading of ancient authors and     
      candidates        poetry. In November 1582,          
      being Sir         Shakespeare received a license to  
      Francis           marry Anne Hathaway. At the time of
      Bacon,            their marriage, Shakespeare was 18 
      Christopher       years old and Anne was 26. They had
      Marlowe, or       three children, the oldest Susanna,
      Edward de         and twins- a boy, Hamneth, and a   
      Vere              girl, Judith. Before his death on
                        April 23 1616, William Shakespeare
                        had written thirty-seven plays. He
                        is generally considered the greatest
                        playwright the world has ever known
                        and has always been the world's most
                        popular author.

(These examples are stolen quoted from the article referenced above.)

about
research
faq
Bear
about