<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1279661702843226144</id><updated>2011-04-21T16:33:36.416-07:00</updated><category term='JUnit4ClassRunner'/><category term='dynamic proxy'/><category term='JUnit'/><category term='BlockJunit4ClassRunner'/><category term='Java'/><category term='RunAfters'/><category term='Excel'/><title type='text'>Drum Roll!</title><subtitle type='html'>My thoughts on things that I have recently learnt that I consider drum roll worthy</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://douglassliz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1279661702843226144/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://douglassliz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Liz Douglass</name><uri>http://www.blogger.com/profile/16751430917791943395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1279661702843226144.post-5397017861075785854</id><published>2008-09-05T23:16:00.001-07:00</published><updated>2008-09-07T17:19:26.768-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BlockJunit4ClassRunner'/><category scheme='http://www.blogger.com/atom/ns#' term='RunAfters'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit4ClassRunner'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit'/><title type='text'>The same, but different</title><content type='html'>Recently I’ve been using JUnit. In keeping with the most up to date libraries, we upgraded our project this week to JUnit 4.4 to JUnit 4.5 and that’s where we encountered a hiccup….&lt;br /&gt;&lt;br /&gt;In our project, we are interested in doing specific things if a test has failed. For the purposes of demonstration, lets suppose that we want to output the test name to the console when a test fails (using a method annotated with @After). How do we know whether a test has failed or not? We can access this information by using a custom test runner that extends the JUnit4ClassRunner (in JUnit 4.4), like this one ...&lt;br /&gt;&lt;pre&gt;public class MyTestRunner&lt;br /&gt;extends JUnit4ClassRunner&lt;br /&gt;{&lt;br /&gt;private static String&lt;br /&gt; failureMessage = null;&lt;br /&gt;&lt;br /&gt;public static String getFailureMessage() {&lt;br /&gt; return failureMessage;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public MyTestRunner(Class klass)&lt;br /&gt; throws InitializationError&lt;br /&gt;{&lt;br /&gt; super(klass);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void run(final RunNotifier notifier) {&lt;br /&gt; failureMessage = "";&lt;br /&gt; notifier.addListener(new FailureListener());&lt;br /&gt; super.run(notifier);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private class FailureListener&lt;br /&gt; extends RunListener {&lt;br /&gt;&lt;br /&gt; public void testFailure&lt;br /&gt;    (Failure failure) throws Exception {&lt;br /&gt;    failureMessage = failure.getTestHeader();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;Our runner (above) overrides the run method (only) so that we can add a FailureListener to the RunNotifier. As per the observer pattern, our notifier will call the testFailure method if the test fails, thereby setting the failureMessage. We can access the failure message from our @After method like this...&lt;br /&gt;&lt;pre&gt;@RunWith(MyTestRunner.class)&lt;br /&gt;public class MyClassTest&lt;br /&gt;{&lt;br /&gt;@After&lt;br /&gt;public void printRunStatusMessage()&lt;br /&gt;{&lt;br /&gt;if (!MyTestRunner.getFailureMessage().equals(""))&lt;br /&gt; System.out.println(MyTestRunner.getFailureMessage());&lt;br /&gt;else&lt;br /&gt; System.out.println("Test did not fail");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Test&lt;br /&gt;public void shouldAssertTruth() throws Exception&lt;br /&gt;{&lt;br /&gt;assertEquals(true, false);&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;Note that our test class is annotated with @RunWith(MyTestRunner.class) - meaning that we are running the tests using our custom runner. If we go ahead and run the shouldAssertTruth test we get this line printing to the console "shouldAssertTruth(com.thoughtworks.blogdemo.test.MyClassTest)". Ta da!&lt;br /&gt;&lt;br /&gt;In the migration to JUnit 4.5, we discovered that JUnit4ClassRunner is now deprecated. It has been replaced with the new BlockJUnit4ClassRunner. According to &lt;a href="http://junit.sourceforge.net/javadoc_40/index.html"&gt;the JUnit API documentation&lt;/a&gt; the BlockJunit4ClassRunner "should have exactly  the same behavior as the old test class runner (&lt;code&gt;JUnit4ClassRunner&lt;/code&gt;)". By simply substituting the old runner class with the new one and re-executing the shouldAssertTruth test we get (drumroll) "Test did not fail" output to the console... hmm, that's not expected....&lt;br /&gt;&lt;br /&gt;In JUnit 4.4 there are calls to an addFailure method scattered throughout the code that executes the @Before, @Test and @After annotated methods for each test. This is what the addFailure method looks like:&lt;br /&gt;&lt;pre&gt;protected void addFailure(Throwable e) {&lt;br /&gt;fNotifier.fireTestFailure&lt;br /&gt; (new Failure(fDescription, e));&lt;br /&gt;}&lt;/pre&gt;This method lets us know immediately when a test has failed and is the reason why our custom runner worked so well. In JUnit 4.5 we now have the concept of Statements, and without going into detail about them, JUnit now has a RunAfters class. This class is used when we want to run a test and execute its associated @After methods. The class looks like this...&lt;br /&gt;&lt;pre&gt;public class RunAfters extends Statement {&lt;br /&gt;private final Statement fNext;&lt;br /&gt;private final Object fTarget;&lt;br /&gt;private final List&lt;frameworkmethod&gt; fAfters;&lt;br /&gt;&lt;br /&gt;public RunAfters(Statement next,&lt;br /&gt;   List&lt;frameworkmethod&gt; afters,&lt;br /&gt;   Object target) {&lt;br /&gt;fNext= next;&lt;br /&gt;fAfters= afters;&lt;br /&gt;fTarget= target;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void evaluate() throws Throwable {&lt;br /&gt;List&lt;throwable&gt; fErrors = new ArrayList&lt;throwable&gt;();&lt;br /&gt;fErrors.clear();&lt;br /&gt;try {&lt;br /&gt;  fNext.evaluate();&lt;br /&gt;} catch (Throwable e) {&lt;br /&gt;fErrors.add(e);&lt;br /&gt;} finally {&lt;br /&gt;  for (FrameworkMethod each : fAfters)&lt;br /&gt;try {&lt;br /&gt;    each.invokeExplosively(fTarget);&lt;br /&gt;  } catch (Throwable e) {&lt;br /&gt;fErrors.add(e);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;if (fErrors.isEmpty())&lt;br /&gt;  return;&lt;br /&gt;if (fErrors.size() == 1)&lt;br /&gt;  throw fErrors.get(0);&lt;br /&gt;throw new MultipleFailureException(fErrors);&lt;br /&gt;}&lt;br /&gt;}&lt;/throwable&gt;&lt;/throwable&gt;&lt;/frameworkmethod&gt;&lt;/frameworkmethod&gt;&lt;/pre&gt;We can see in the evaluate method that any errors that are thrown during the executing of the test are collected in fErrors. fErrors is used at the end of the evaluate method to create and throw a new MultipleFailureException, which will notify our FailureListener. The crucial part for us is that despite an error being thrown during the execution of a test, the @After method will &lt;span style="font-weight: bold;"&gt;always&lt;/span&gt; be attempted in the finally block, and at that point we are blissfully unaware that the test has failed. Hmph.&lt;br /&gt;&lt;br /&gt;Our solution, the quickest one to restore functionality (and not use anything deprecated), has been to create a custom RunAfters class that notifies our FailureListener of any errors in the catch block (see above). It seems less than ideal to have to do this, especially since the changes to the RunAfters class are so minor. Perhaps the next JUnit version will do something else...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1279661702843226144-5397017861075785854?l=douglassliz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglassliz.blogspot.com/feeds/5397017861075785854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1279661702843226144&amp;postID=5397017861075785854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1279661702843226144/posts/default/5397017861075785854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1279661702843226144/posts/default/5397017861075785854'/><link rel='alternate' type='text/html' href='http://douglassliz.blogspot.com/2008/09/same-but-different.html' title='The same, but different'/><author><name>Liz Douglass</name><uri>http://www.blogger.com/profile/16751430917791943395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1279661702843226144.post-7159153021485120765</id><published>2008-08-30T22:09:00.000-07:00</published><updated>2008-09-02T00:43:41.433-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='dynamic proxy'/><title type='text'>Small things amuse small…. hmph, well anyway….</title><content type='html'>&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;My first four months in the software industry has been a really exciting challenge. There is a lot to get up to speed with and it’s changing a&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;ll the time. One thing that really impresses me about the people that I get to work with is that they ar&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;e all eager to learn, as am I. What is a little daunting is that I often find myself in conversations where I know absolutely nothing about the technology that the other person is talking about(!), simply because I haven’t been exposed to it before. For the most part though I feel like a kid in a candy store wanting to get my sticky little fingers into all the amazing colourful jars.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;Two things that I’ve recently found out about are dynamic proxies and (drum roll) pixel rulers! I did probably get a little too excited about the latter, but hey, that’s me. My colleague su&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;ggested the dynamic proxy implementation and it turned out really neat….&lt;/span&gt;  &lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;In our application we are reading some data from an MS Excel file. The Excel file is very simple: it has a column lis&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;ting the names of parameters and an adjacent column listing the values for each of those parameters. We’re using &lt;a href="http://jexcelapi.sourceforge.net/"&gt;J&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;a href="http://jexcelapi.sourceforge.net/"&gt;ExcelAPI&lt;/a&gt; to read the parameter values. Each of the parameter names matches up to a method name on our interface, which looks something like this:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public interface Parameters&lt;br /&gt;{&lt;br /&gt;    String parameterA();&lt;br /&gt;&lt;br /&gt;    String parameterB();&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:arial;"&gt;Our first attempt at providing access to the value for each parameter was:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class ExcelParameters implements Parameters&lt;br /&gt;{&lt;br /&gt;    private ExcelReader reader = new ExcelReader();&lt;br /&gt;&lt;br /&gt;    public String parameterA() {&lt;br /&gt;         return reader.readParameter("parameterA");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String parameterB() {&lt;br /&gt;         return reader.readParameter("parameterB");&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_6cbYVIs08Xs/SLovKGMSMiI/AAAAAAAAAAs/7MC0ysfKdYo/s1600-h/Picture+5.png"&gt; &lt;/a&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Obviously this solution was neither elegant nor easy to maintain.  All we were really after was a way to return the value of the parameter corresponding to the method name (which is also the parameter name) from Excel. Enter the dynamic proxy…&lt;/span&gt;  &lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;There is a lot of material available describing the implementation dynami&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;c proxies in Java, including &lt;a href="http://userpages.umbc.edu/%7Etarr/dp/lectures/DynProxies-2pp.pdf"&gt;this article&lt;/a&gt;. Our dynamic proxy use is unconventional because, unlike in the normal use case, we never invoke the called method on an actual implementation of the Parameters interface. Instead we simply get the name of the called method and look up the corresponding parameter value in Excel:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_6cbYVIs08Xs/SLo235jp4RI/AAAAAAAAAA8/HKKAZN-hPtU/s1600-h/Picture+7.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_6cbYVIs08Xs/SLo235jp4RI/AAAAAAAAAA8/HKKAZN-hPtU/s400/Picture+7.png" alt="" id="BLOGGER_PHOTO_ID_5240561450370064658" border="0" /&gt;&lt;/a&gt;&lt;span style=";font-family:arial;font-size:100%;"  &gt;&lt;br /&gt;The big advantage of this approach is that we never need an implementation of our Parameters interface – the proxy does this for us automatically. Our proxy is an implementation of the java.lang.reflect.Proxy class and looks like this:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public static Parameters getExcelRepository () {&lt;br /&gt;    ClassLoader cl = Parameters.class.getClassLoader();&lt;br /&gt;    Parameters proxy =&lt;br /&gt;         (Parameters) Proxy.newProxyInstance(cl,&lt;br /&gt;         new Class [] {Parameters.class},&lt;br /&gt;         new ExcelParameterHandler());&lt;br /&gt;    return proxy;&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;And the invocation handler that actually looks up the Excel sheet looks like this:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class ExcelParameterHandler&lt;br /&gt;   implements InvocationHandler&lt;br /&gt;{&lt;br /&gt;    private ExcelReader reader = new ExcelReader();&lt;br /&gt;&lt;br /&gt;    public Object invoke(Object proxy,&lt;br /&gt;                 Method method, Object[] args)&lt;br /&gt;                 throws Exception&lt;br /&gt;    {&lt;br /&gt;       return reader.readParameter(method.getName());&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;And here is how we can use it:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Test&lt;br /&gt;public void shouldBeAbleToReadParametersFromExcel()&lt;br /&gt;  throws Exception&lt;br /&gt;{&lt;br /&gt;    Parameters excelParameters =&lt;br /&gt;        ParameterRepository.getExcelRepository();&lt;br /&gt;    assertEquals("value for ParameterA",&lt;br /&gt;        excelParameters.ParameterA());&lt;br /&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Voila!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1279661702843226144-7159153021485120765?l=douglassliz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://douglassliz.blogspot.com/feeds/7159153021485120765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1279661702843226144&amp;postID=7159153021485120765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1279661702843226144/posts/default/7159153021485120765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1279661702843226144/posts/default/7159153021485120765'/><link rel='alternate' type='text/html' href='http://douglassliz.blogspot.com/2008/08/small-things-amuse-small-hmph-well.html' title='Small things amuse small…. hmph, well anyway….'/><author><name>Liz Douglass</name><uri>http://www.blogger.com/profile/16751430917791943395</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_6cbYVIs08Xs/SLo235jp4RI/AAAAAAAAAA8/HKKAZN-hPtU/s72-c/Picture+7.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
