<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-10879650</atom:id><lastBuildDate>Wed, 30 Jan 2008 17:56:01 +0000</lastBuildDate><title>Share and Enjoy</title><description/><link>http://shareandenjoy.saff.net/</link><managingEditor>David Saff</managingEditor><generator>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-3791860246960251329</guid><pubDate>Wed, 30 Jan 2008 16:03:00 +0000</pubDate><atom:updated>2008-01-30T08:04:59.747-08:00</atom:updated><title>Meet me at the Green Bar</title><description>Blogging here has been fun, but I wanted a nicer place to talk without blogger.com hanging around all the time.  So, from now on, meet me at the &lt;a href="http://greenbar.saff.net"&gt;Green Bar&lt;/a&gt;.</description><link>http://shareandenjoy.saff.net/2008/01/meet-me-at-green-bar.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-7794639679460765557</guid><pubDate>Wed, 09 May 2007 15:11:00 +0000</pubDate><atom:updated>2007-05-09T08:16:08.143-07:00</atom:updated><title>TDD in academia: a brief review</title><description>The new millenium has seen growing academic interest in test-driven development.  Here, I'll review the papers I've seen so far, as a starting point for further research, a reference for on-line discussions, and a source for resolving bar bets.  I've squashed some interesting nuances in each study regarding the exact processes compared, and I'm happy to revise if any reader feels I've mis-quoted or over-simplified.&lt;br /&gt;&lt;br /&gt;First, a couple studies, both using students, have found either no significant difference, or just slight improvement, in quality and productivity from using TDD.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;     &lt;a href="http://ieeexplore.ieee.org/xpl/abs_free.jsp?arNumber=1049202" title="Muller and Hagner"&gt;Muller and Hagner&lt;/a&gt; found that TDD does not accelerate the implementation, and the resulting programs are not more reliable, but TDD developers end up with better program understanding.    &lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;     &lt;a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1248153" title="Pancur, Ciglaric, Trampus, and Vidmar"&gt;Pancur, Ciglaric, Trampus, and Vidmar&lt;/a&gt; found that a TDD student group scored slightly, but not significantly, worse in several quality measures than a non-TDD group.   &lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;Laurie Williams' group at North Carolina State has conducted several studies of TDD using professional programmers.&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;     &lt;a href="http://collaboration.csc.ncsu.edu/laurie/Papers/TDDpaperv8.pdf" title="George and Williams"&gt;George and Williams &lt;/a&gt;find that TDD developers took 16% more time, but passed 18% more independently-created tests.  They also find that non-TDD teams almost never wrote any tests.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     &lt;a href="http://portal.acm.org/citation.cfm?id=776892" title="Maximilien and Williams"&gt;Maximilien and Williams&lt;/a&gt; performed a case study at IBM that showed a TDD project had half the defect rate of a similar non-TDD project, and, again, non-TDD developers never wrote tests.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     &lt;a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1251029" title="Williams, Maximilien, and Youk"&gt;Williams, Maximilien, and Youk&lt;/a&gt; performed a case study showing a 40% reduction in defects in a TDD project compared to a similar non-TDD project, with similar overall productivity.   &lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;Other groups have also found productivity and quality gains from using TDD.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;     &lt;a href="http://iit-iti.nrc-cnrc.gc.ca/iit-publications-iti/docs/NRC-47445.pdf" title="Erdogmus"&gt;Erdogmus&lt;/a&gt; find that quality increased linearly with the number of programmer tests, that students who wrote more tests were more productive, and that TDD students write more tests.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     &lt;a href="http://research.microsoft.com/manuvir/papers/isese-fp17288-Bhat.pdf" title="Bhat and Nagappan"&gt;Bhat and Nagappan&lt;/a&gt; found that a TDD project had twice the quality of a non-TDD project, and actually wrote tests, although writing the tests required 15% more time.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     &lt;a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1357925" title="Geras, Smith, and Miller"&gt;Geras, Smith, and Miller&lt;/a&gt; found no productivity difference between TDD and non-TDD teams, but did find fewer unplanned test failures on the TDD team.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     &lt;a href="http://www.acm.org/src/subpages/gf_entries_06/DavidJanzen_src_gf06.pdf" title="Janzen"&gt;Janzen&lt;/a&gt; found that a TDD team produced code that scored higher on many code metrics than non-TDD teams, and developed more features in the same time, with a similar defect rate.  Again, half of the non-TDD developers never found time to write tests.   &lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;Many of these papers are well-summarized by &lt;a href="http://www.csc.calpoly.edu/%7Edjanzen/pubs/tddcomputer.pdf" title="Janzen and Saiedian"&gt;Janzen and Saiedian&lt;/a&gt;, in a survey paper that takes a positive view of TDD and predicts growing acceptance.  Janzen and Saiedian also suggest &lt;a href="http://portal.acm.org/citation.cfm?id=1121419" title="test-driven learning"&gt;test-driven learning&lt;/a&gt;, an application of TDD to the software engineering classroom.&lt;br /&gt;&lt;br /&gt;To draw some tentative conclusions:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;     For students only, although some student groups can gain productivity and quality from using TDD, it can at worst be no better than a disciplined, non-TDD approach.&lt;br /&gt;  &lt;/li&gt;   &lt;li&gt;     All studies on professional developers show productivity or quality gains from using TDD.   &lt;/li&gt;   &lt;li&gt;     In some cases, TDD teams took longer, but produced higher-quality code.  Considering that the cost of finding a bug in QA and sending it back to the developers for fixing is greater than fixing it in the first place, I consider this an unqualified win for TDD.   &lt;/li&gt;   &lt;li&gt;     In many cases, although all developers were encouraged to write tests, only TDD teams did.  A suite of reliable unit tests has benefits beyond initial development, for catching regressions in functionality and design and as documentation to maintainers, but these benefits were not directly measured in any of the studies above.   &lt;/li&gt; &lt;/ul&gt;</description><link>http://shareandenjoy.saff.net/2007/05/article-new-millenium-has-seen-growing.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-3731856826851496553</guid><pubDate>Tue, 08 May 2007 19:54:00 +0000</pubDate><atom:updated>2007-05-09T08:19:39.455-07:00</atom:updated><title>Exploring with JUnit Factory: 103 points in the first frame</title><description>In my &lt;a href="http://shareandenjoy.saff.net/2007/04/exploring-with-junit-factory-103-points.html"&gt;last post&lt;/a&gt;, we shook out a Theory about the number of bowls and frames in a game of bowling:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first,&lt;br /&gt;   Bowl second) {&lt;br /&gt;  assumeNotNull(game, first, second);&lt;br /&gt;  assumeThat(game.isAtBeginning(), is(true));&lt;br /&gt;  assumeThat(game.getPlayers().size(), is(1));&lt;br /&gt;  assumeThat(first.isStrike(), is(false));&lt;br /&gt;  assumeThat(second.completesSpareAfter(first), is(false));&lt;br /&gt;&lt;br /&gt;  for (int frame = 0; frame &lt; 10; frame++) {&lt;br /&gt;   game.bowl(first);&lt;br /&gt;   game.bowl(second);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  assertThat(game.isGameOver(), is(true));&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We used JUnitFactory to find some missing datapoints and missing assumptions, and got to the point where all JUnitFactory could find were parameters that either failed the assumptions or passed the tests, which is good.&lt;br /&gt;&lt;br /&gt;At this point, we should think about the next functionality to test.  I have almost a dozen methods that I've stubbed with fake answers, but before I completely forget about this Theory, I check the test that JUnit Factory has produced to test the "passing" path through this Theory:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    public void testShouldBeTenFramesWithTwoRollsInEach() throws Throwable {&lt;br /&gt;        Game STARTING_GAME = BowlingTests.STARTING_GAME;&lt;br /&gt;        BowlingTests bowlingTests = new BowlingTests();&lt;br /&gt;        bowlingTests.shouldBeTenFramesWithTwoRollsInEach(STARTING_GAME, BowlingTests.THREE, new Bowl(100));&lt;br /&gt;        assertNotNull("bowlingTests.assume", getPrivateField(bowlingTests, "assume"));&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, bust my buffers, where did JUnit Factory come up with the idea to bowl 100 pins with one ball?  I'll have to look at its league records to see if there's been similar grade inflation.  This is not the perfect test we'd like to see--no Bowl should exist with over 100 pins.  I could fix this directly in the code, but we need a failing test first.  Our current Theory would pass with 100 as a datapoint--what I need is a new Theory.&lt;br /&gt;&lt;br /&gt;It's tempting to test that the Bowl constructor throws an exception whenever a pinCount over 10 is passed to it.  However, testing for exceptions can be obfuscated, and it's not what I necessarily want to say--I want to say that no Bowl exists with more than 10 pins bowled:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Theory&lt;br /&gt;public void maximumPinCountIsTen(Bowl bowl) {&lt;br /&gt;   assumeNotNull(bowl);&lt;br /&gt;   assertThat(bowl.pinCount(), lessThanOrEqualTo(10));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is easily passed by having &lt;tt&gt;pinCount()&lt;/tt&gt; always return, say, 5.  I am being deliberately difficult here, employing what Kent Beck calls "Fake it till you make it".  The correct implementation of &lt;tt&gt;pinCount&lt;/tt&gt; (return the pins passed in the constructor) is obvious, but it's worth our time to notice that our current tests don't distinguish between the obviously right and obviously wrong implementations.&lt;br /&gt;&lt;br /&gt;The reason we can get away with a fake return from &lt;tt&gt;pinCount&lt;/tt&gt; is that all we've required of the method is that it return something less than or equal to 10.  Let's add another Theory about the normal behavior of &lt;tt&gt;pinCount&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void pinCountMatchesConstructorParameter(int pinCount) {&lt;br /&gt;  assertThat(new Bowl(pinCount).pinCount(), is(pinCount));&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To make this pass, we can now put in the obvious definition of &lt;tt&gt;pinCount&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; private final int pinCount;&lt;br /&gt;&lt;br /&gt; public Bowl(int pinCount) {&lt;br /&gt;  this.pinCount = pinCount;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int pinCount() {&lt;br /&gt;  return pinCount;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now all of our theories pass on our current data points.  Let's look for other datapoints using JUnit Factory.  We get this excellent test (from now on, I'll edit out all of the unimportant bits of the test, leaving the name and invocation&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    public void testMaximumPinCountIsTenThrowsAssertionError() throws Throwable {&lt;br /&gt;       bowlingTests.maximumPinCountIsTen(new Bowl(100));&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is what we were hoping for.  Our theories now catch a 100-point Bowl as an error.  Before going further, I need to add this as a data point:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public static ONE_HUNDRED_BOWL = new Bowl(100);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now &lt;tt&gt;maximumPinCountIsTen&lt;/tt&gt; fails.  To fix this, I'll prevent the construction of Bowls that have more than 10 pins:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public Bowl(int pinCount) {&lt;br /&gt;  if (pinCount &gt; 10)&lt;br /&gt;   throw new IllegalArgumentException("At most 10 pins in one bowl");&lt;br /&gt;  this.pinCount = pinCount;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, everything falls apart.  When trying to create an instance of &lt;tt&gt;BowlingTests&lt;/tt&gt;, the line&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public static ONE_HUNDRED_BOWL = new Bowl(100);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;causes construction to fail with an IllegalArgumentException, so no tests get run.  We could remove the data point, but if we were ever to regress and forget to check arguments to the &lt;tt&gt;Bowl&lt;/tt&gt; constructor, this is a test that will remind us.  Popper will allow us to wrap the datapoint in a method, annotated with &lt;tt&gt;@DataPoint&lt;/tt&gt;.  Any &lt;tt&gt;@DataPoint&lt;/tt&gt; method that throws an exception is simply ignored, so we can keep this data point around in case it's ever needed again:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @DataPoint public Bowl oneHundredBowl() { return new Bowl(100); }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running the tests now, we get an IllegalArgumentException on &lt;tt&gt;pinCountMatchesConstructorParameter&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void pinCountMatchesConstructorParameter(int pinCount) {&lt;br /&gt;  assertThat(new Bowl(pinCount).pinCount(), is(pinCount));&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Since any integer can be passed in, some of those integers will cause IllegalArgumentExceptions.  However, these integers are invalid parameters.  I could explicitly check that all ints coming in are between 0 and 10, but that would duplicate the logic that the constructor itself should be doing.  Instead, I'll recognize that an IllegalArgumentException is a signal that the parameter is invalid:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void pinCountMatchesConstructorParameter(int pinCount) {&lt;br /&gt;  try {&lt;br /&gt;   assertThat(new Bowl(pinCount).pinCount(), is(pinCount));&lt;br /&gt;  } catch (IllegalArgumentException e) {&lt;br /&gt;   assumeNoException(e);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here, &lt;tt&gt;assumeNoException&lt;/tt&gt; turns an otherwise fatal exception into an assumption failure.&lt;br /&gt;&lt;br /&gt;Now, we run the tests again to find out that we haven't supplied any valid integers as parameters to the &lt;tt&gt;Bowl&lt;/tt&gt; constructor.  We can easily come up with one ourselves, but let's overuse JUnit Factory instead.  We generate tests, and JUnit Factory chooses the data point 0 to test &lt;tt&gt;pinCountMatchesConstructorParameter&lt;/tt&gt;.  We add that data point to our TheoryContainer, and find that:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Our tests pass.&lt;br /&gt;&lt;li&gt;JUnit Factory can only find tests for normal returns and InvalidTheoryParameterExceptions, which is good.&lt;br /&gt;&lt;li&gt;All the normal-return tests use sensible parameters.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Now, I'm finally ready to move on to my next bit of functionality, but I'll let this series on bowling with Popper and JUnit Factory draw to a close.  For those of you following along at home, here's the &lt;a href="http://popper.tigris.org/BowlingTests.java"&gt;final source&lt;/a&gt; of our Theory class.  Some things to note:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;We took incredibly small steps here.  Most of the times that we invoked JUnit Factory, it found things we could have found ourselves.  But since this is still a new habit for me, taking it slow gives me confidence I'm not missing anything&lt;br /&gt;&lt;li&gt;Unlike in test-only-driven development, I expect that sometimes old theories will fail as I'm incrementally solving new ones and adding new data points.  This is the theories doing their job.  This initial theory was very precise about how the number of bowls in a frame corresponds to whether the first bowl is a strike, but says nothing about how to determine what a strike is.  When I make the definition of "strike" more precise, I may also need to add more precision to my Bowl-counting algorithm to adjust to that.  In test-only-driven development, this might require me to write a new test for the new data.  In test-and-theory-driven development, the new test springs forth as a new data point or definition applied to an old theory.&lt;br /&gt;&lt;li&gt;Popper and JUnit Factory are still evolving, and there's a lot of room for improvement in how they work together.  If you have suggestions of how to make this process easier, please &lt;a href="mailto:saff@mit.edu"&gt;mail me&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;This is just one example of how we can "mash-up" data from a characterization service like JUnit Factory in order to promote quality.  Other examples could include picking out lines of code that are difficult for JUnit Factory to cover, in order to suggest design improvements, or looking for patterns in exception-catching tests in order to suggest better patterns of error recovery.  The sky's the limit.&lt;br /&gt;&lt;/ul&gt;</description><link>http://shareandenjoy.saff.net/2007/04/103-points.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-3928051655034005230</guid><pubDate>Tue, 01 May 2007 17:56:00 +0000</pubDate><atom:updated>2007-05-01T10:08:27.028-07:00</atom:updated><title>Exploring with JUnit Factory: not null, I assume</title><description>In my &lt;a href="http://shareandenjoy.saff.net/2007/04/popper-and-junitfactory.html"&gt;last post&lt;/a&gt;, we used Popper to create a Theory about scoring a bowling game.  The end result boiled down to roughly this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@RunWith(Theories.class)&lt;br /&gt;public class BowlingTests extends TheoryContainer {&lt;br /&gt; public static Game STARTING_GAME = new Game();&lt;br /&gt; public static Bowl THREE = new Bowl(3);&lt;br /&gt; public static Bowl FOUR = new Bowl(4);&lt;br /&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first,&lt;br /&gt;   Bowl second) {&lt;br /&gt;  assumeThat(game.isAtBeginning(), is(true));&lt;br /&gt;  assumeThat(game.getPlayers().size(), is(1));&lt;br /&gt;  assumeThat(first.isStrike(), is(false));&lt;br /&gt;  assumeThat(second.completesSpareAfter(first), is(false));&lt;br /&gt;&lt;br /&gt;  for (int frame = 0; frame &lt; 10; frame++) {&lt;br /&gt;   game.bowl(first);&lt;br /&gt;   game.bowl(second);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  assertThat(game.isGameOver(), is(true));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I believe Theories are useful for any Java developer.  However, so far, I've been concentrating on &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;test-driven development&lt;/a&gt; (TDD).  The heartbeat of TDD with Tests and Theories is similar to that with just Tests, with one essential difference. &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Use automated or manual &lt;em&gt;exploration&lt;/em&gt; to find any data points that invalidate the current Theories.  If such a data point exists, add it to the currently accepted data points.  Otherwise, write a focused Test or Theory for the next bit of functionality needed.  At the end of this step, a Test or Theory should fail.&lt;br /&gt;&lt;li&gt;Change the code so that all current Tests and Theories pass.&lt;br /&gt;&lt;li&gt;Refactor to the best design that passes the current tests and theories.&lt;br /&gt;&lt;li&gt;Repeat.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;We've already done step 1--since there were no Theories, I wrote a new one, above, about ten frames with two rolls.  I'll do step 2 off-screen...&lt;br /&gt;&lt;br /&gt;There.  I've written the simplest code I can think of to pass this theory--we can hard-code most of the boolean answers, especially making sure that &lt;tt&gt;isGameOver&lt;/tt&gt; always returns true.  Running the test in Eclipse tells me it passes for all of the parameters I've considered (all three of them).  However, what about the infinite number of parameters I haven't considered?  I can stare at the code and consider other options, or I can just ask &lt;a href="http://www.junitfactory.com"&gt;JUnit Factory&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;JUnit Factory is a free service accessed through a free Eclipse plug-in.  Its primary purpose is to generate &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=198296"&gt;characterization tests&lt;/a&gt; for domain classes.  It uses static analysis, dynamic analysis, and tuned heuristics in an attempt to characterize the current behavior of your classes, especially in unanticipated circumstances.&lt;br /&gt;&lt;br /&gt;By turning the powerful eye of JUnit Factory on a TheoryContainer, I can see automatically if there are any inputs to my theory that pass the assumptions, but fail the assertions.  I've already downloaded the plug-in, and I've made sure I meet these prerequisites:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;I'm okay with Agitar storing my code on their server, and it's legal for them to do so.&lt;br /&gt;&lt;li&gt;I don't have any &lt;tt&gt;@Test&lt;/tt&gt; annotations on my methods in my test class.  JUnit Factory is very clever in refusing to generate tests for any class that looks itself like a test.  I've suggested this is over-restrictive, but the limitation is in place for now.  (If you use &lt;a href="http://popper.tigris.org"&gt;Popper&lt;/a&gt; like I do, you have Tests and Theories mixed up together.  As a stop-gap measure, you can use the &lt;tt&gt;@Theory&lt;/tt&gt; annotation on a method without parameters to indicate that it should be run as a standard JUnit test, but without alerting the little censors who live inside the JUnit Factory server.)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I focus my editor on &lt;tt&gt;BowlingTests&lt;/tt&gt; push Shift-F9, and in about 30 seconds, I get my &lt;a href="http://popper.tigris.org/BowlingTestsAgitarTest_1.java"&gt;first set of characterization tests&lt;/a&gt;.  Remember that these are tests of the methods of my TheoryContainer, not of the Game or Bowl class themselves.  When scanning these tests, I'm looking only for parameters and outcomes, not the assertions themselves, which are unlikely to be interesting--all of my Theory methods, remember, return &lt;tt&gt;void&lt;/tt&gt;.  There's usually a few that indicate proper returns from my Theory methods, and a few indicating exceptional returns.  Scanning the outline, I see:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEach()&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEachThrowsNullPointerException()&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEachThrowsNullPointerException1()&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEachThrowsNullPointerException2()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So JUnitFactory found at least one way to make the Theory pass, and three ways to make it throw a NullPointerException.  Since my tests pass with my current data points, there must be new data points I need to include to find these exceptional behaviors.  Let's look at the first NullPointerException test:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;    &lt;br /&gt;public void testShouldBeTenFramesWithTwoRollsInEachThrowsNullPointerException() throws Throwable {&lt;br /&gt;        BowlingTests bowlingTests = new BowlingTests();&lt;br /&gt;        try {&lt;br /&gt;            bowlingTests.shouldBeTenFramesWithTwoRollsInEach(new Game(), BowlingTests.THREE, null);&lt;br /&gt;            fail("Expected NullPointerException to be thrown");&lt;br /&gt;        } catch (NullPointerException ex) {&lt;br /&gt;            assertNull("ex.getMessage()", ex.getMessage());&lt;br /&gt;            assertThrownBy(BowlingTests.class, ex);&lt;br /&gt;            assertNotNull("bowlingTests.assume", getPrivateField(bowlingTests, "assume"));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is annoying--JUnitFactory is passing a null Bowl to my theory.  Of course, my Theory currently claims that it accepts any value of type Bowl, and null fits that description.  The other two NullPointerException tests make use of another null Bowl, and a null Game.  &lt;br /&gt;&lt;br /&gt;In order to deal with this new information, we add the two new data points to our TheoryContainer:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public static Game STARTING_GAME = new Game();&lt;br /&gt; public static Game NULL_GAME = null;&lt;br /&gt; &lt;br /&gt; public static Bowl THREE = new Bowl(3);&lt;br /&gt; public static Bowl FOUR = new Bowl(4);&lt;br /&gt; public static Bowl NULL_BOWL = null;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running the test, it fails with a NullPointerException, as expected.  Now, the theory needs to be updated to assume that the parameters are not null.  Using just Popper, we can simply use an attribute of the &lt;tt&gt;@Theory&lt;/tt&gt; annotation, &lt;tt&gt;@Theory(nullsAccepted=false)&lt;/tt&gt;.  Unfortunately, JUnitFactory does not understand this attribute, so instead, we'll have to explicitly add the assumptions:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first,&lt;br /&gt;   Bowl second) {&lt;br /&gt;  assumeThat(game, isNotNull());&lt;br /&gt;  assumeThat(first, isNotNull());&lt;br /&gt;  assumeThat(second, isNotNull());&lt;br /&gt;&lt;br /&gt;  // ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a common pattern when using Popper together with JUnit Factory.  In order to make it as painless as possible, you can use a shorthand from Popper 0.5:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; @Theory&lt;br /&gt; public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first,&lt;br /&gt;   Bowl second) {&lt;br /&gt;  assumeNotNull(game, first, second);&lt;br /&gt;&lt;br /&gt;  // ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, generating the tests, we see the following methods:&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEach()&lt;br /&gt;testShouldBeTenFramesWithTwoRollsInEachThrowsInvalidTheoryParameterException()&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;This is what we want to see: sometimes the parameters are invalid, but these are caught by our assumptions.  Anything getting past our assumptions is passing the test.  Excellent.&lt;br /&gt;&lt;br /&gt;This may feel like a lot of work for a simple skeleton.  However, this work will be paid off as we move forward--this Theory actually says a lot about bowling games, and as we make &lt;tt&gt;Game&lt;/tt&gt; and &lt;tt&gt;Bowl&lt;/tt&gt; more sophisticated, this Theory will be waiting to catch any weirdness introduced.&lt;br /&gt;&lt;br /&gt;And, in the future, I may publish an Eclipse plug-in that will better manage this "mash-up" of Theories and JUnit Factory, for example, by automatically inserting &lt;tt&gt;assumeNotNull&lt;/tt&gt; where desirable.</description><link>http://shareandenjoy.saff.net/2007/04/exploring-with-junit-factory-103-points.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-8244041089988974490</guid><pubDate>Fri, 27 Apr 2007 20:44:00 +0000</pubDate><atom:updated>2007-04-27T10:53:16.122-07:00</atom:updated><title>Bowling with Popper style</title><description>A few months ago, I released the first version of &lt;a href="http://popper.tigris.org"&gt;Popper&lt;/a&gt;, an extension to JUnit that allows you to supplement &lt;span style="font-style: italic;"&gt;Tests&lt;/span&gt; (statements about how one particular object acts on one set of inputs) with &lt;span style="font-style: italic;"&gt;Theories &lt;/span&gt;(statements about how all objects meeting certain criteria act on all inputs meeting other criteria).  Popper has grown up to version 0.4, and I'd like &lt;span style="font-style: italic;"&gt;you&lt;/span&gt; to try it out.  Yes, you.&lt;br /&gt;&lt;br /&gt;The big idea here is being even more precise about what you test, and how you communicate it.  Tests written in a JUnit style end up saying both more and less than the developer knows--Theories help you say exactly what you know.&lt;br /&gt;&lt;br /&gt;As an example, let's work through the a unit test Kevin Lawrence has &lt;a href="http://www.developertesting.com/archives/month200703/20070312-000399.html"&gt;suggested&lt;/a&gt; for a bowling scorer.  The first requirement Kevin considers is &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;//  2.1.1 A game of tenpins consists of ten frames. A player delivers two balls in each of the first&lt;br /&gt;//  nine frames unless a strike is scored. In the tenth frame, a player delivers three balls if a&lt;br /&gt;//  strike or spare is scored. Every frame must be completed by each player bowling in regular&lt;br /&gt;//  order.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here's Kevin's test:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void shouldBeTenFramesWithTwoRollsInEach() {&lt;br /&gt;    for(int frame = 0; frame &lt; 10; frame++){&lt;br /&gt;      game.bowl(3);&lt;br /&gt;      game.bowl(4);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    assertThat(game.isGameOver(), is(true));&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Kevin's using &lt;a href="http://code.google.com/p/hamcrest/"&gt;Hamcrest&lt;/a&gt;, a matcher library that allows the convenient &lt;a href="http://www.artima.com/forums/flat.jsp?forum=155&amp;thread=109515"&gt;assertThat&lt;/a&gt;  syntax.  This is good, because we will too.&lt;br /&gt;&lt;br /&gt;This test talks about a fixture field &lt;tt&gt;game&lt;/tt&gt;, which is initialized as such:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class GameTest {&lt;br /&gt;  private Game game;&lt;br /&gt;&lt;br /&gt;  @Before&lt;br /&gt;  public void createGame() {&lt;br /&gt;    game = new Game();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is a fairly well-written JUnit test setup, and it will correctly catch a number of bugs.  However, as a communication tool to a future maintainer, it falls short:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; The requirement talks about each player bowling in regular order--does the default constructor of Game produce a single-player game?&lt;br /&gt;&lt;li&gt; Does the property of having twenty bowls left only apply right after construction, or to Games in other states?&lt;br /&gt;&lt;li&gt;What's special about 3 and 4?  Would any other numbers do?  Just those particular numbers?&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;When writing a theory, the strategy is to remove specifics that are not important to the behavior under consideration, and use the object's own protocol to fill in the details that are left out.  First, we can remove the invocation of the default constructor from the understanding of the test--what's important is not the constructor call, but the state the game is in at the beginning of the sequence, and the number of players.  We do this by making &lt;tt&gt;game&lt;/tt&gt; a parameter of the method, which is now a Theory, and making assumptions about its current state:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  @Theory&lt;br /&gt;  public void shouldBeTenFramesWithTwoRollsInEach(Game game) {&lt;br /&gt;    assumeThat(game.isAtBeginning(), is(true));&lt;br /&gt;    assumeThat(game.getPlayers().size(), is(1));&lt;br /&gt;    &lt;br /&gt;    for(int frame = 0; frame &lt; 10; frame++){&lt;br /&gt;      game.bowl(3);&lt;br /&gt;      game.bowl(4);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    assertThat(game.isGameOver(), is(true));&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the future, it may be possible to have Games that are are "at the beginning", but don't result directly from constructor calls--for example, a Game loaded from an intermediate "save-game" file.  This Theory will automatically apply to those Games, as well.  &lt;br /&gt;&lt;br /&gt;Next, what's special about 3 and 4?  Well, they're just two numbers that indicate that neither a strike nor spare was bowled:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  @Theory&lt;br /&gt;  public void shouldBeTenFramesWithTwoRollsInEach(Game game, int firstBowl, int secondBowl) {&lt;br /&gt;    assumeThat(game.isAtBeginning(), is(true));&lt;br /&gt;    assumeThat(game.getPlayers().size(), is(1));&lt;br /&gt;    assumeThat(firstBowl, lessThan(10));&lt;br /&gt;    assumeThat(firstBowl + secondBowl, lessThan(10));&lt;br /&gt;&lt;br /&gt;    for(int frame = 0; frame &lt; 10; frame++){&lt;br /&gt;      game.bowl(firstBowl);&lt;br /&gt;      game.bowl(secondBowl);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    assertThat(game.isGameOver(), is(true));&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(Actually, we're missing the fact here that spares in the first nine frames also lead to two bowls--the original test left that fact out, and I choose to do the same in this Theory).&lt;br /&gt;&lt;br /&gt;The line &lt;tt&gt;assumeThat(firstBowl + secondBowl, lessThan(10))&lt;/tt&gt; bothers me.  It doesn't match up with the concept of "spare" from the requirements, and it likely duplicates logic that will end up in the domain soon enough.  Therefore:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  @Theory&lt;br /&gt;  public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first, Bowl second) {&lt;br /&gt;    assumeThat(game.isAtBeginning(), is(true));&lt;br /&gt;    assumeThat(game.getPlayers().size(), is(1));&lt;br /&gt;    assumeThat(first.isStrike(), is(false));&lt;br /&gt;    assumeThat(second.completesSpareAfter(first), is(false));&lt;br /&gt;&lt;br /&gt;    for(int frame = 0; frame &lt; 10; frame++){&lt;br /&gt;      game.bowl(first);&lt;br /&gt;      game.bowl(second);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    assertThat(game.isGameOver(), is(true));&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, we've removed unhelpful particulars, and added some helpful domain concepts and explicit assumptions.  How does this Theory get run?  There's two answers.  We can use this theory for &lt;em&gt;validation&lt;/em&gt; (Does every parameter combination we've considered in the past still work?), or &lt;em&gt;exploration&lt;/em&gt; (Is there any new parameter combination that passes the assumptions, but fails the assertions?).&lt;br /&gt;&lt;br /&gt;For validation, the Theory method must be declared on a subclass of TheoryContainer, which causes it to be run with a custom JUnit runner.  By default, the subclass is also expected to declare as constants any valid parameter values that are currently believed to pass the theory:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@RunWith(Theories.class)&lt;br /&gt;public class BowlingTheories extends TheoryContainer {&lt;br /&gt;  public static Game STARTING_GAME = new Game();&lt;br /&gt;  public static Bowl GUTTER_BALL = new Bowl(0);&lt;br /&gt;  public static Bowl STRIKE_BALL = new Bowl(10);&lt;br /&gt;  public static Bowl THREE = new Bowl(3);&lt;br /&gt;  public static Bowl FOUR = new Bowl(4);&lt;br /&gt;&lt;br /&gt;  @Theory&lt;br /&gt;  public void shouldBeTenFramesWithTwoRollsInEach(Game game, Bowl first, Bowl second) { &lt;br /&gt;    // as above ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The custom runner will try every possible combination of parameters from the set given, but it will not try anything outside that set.&lt;br /&gt;&lt;br /&gt;Once I'm satisfied that my code passes the Theory for all the parameters I can think of myself, I'm ready for some automated exploration, to search for parameters that I haven't thought of.  However, if your code is free from &lt;a href="http://www.junitfactory.com/faq.jsp"&gt;legal entanglements&lt;/a&gt;, &lt;a href="http://www.junitfactory.com/"&gt;JUnit Factory&lt;/a&gt;, from &lt;a href="http://www.agitar.com"&gt;Agitar&lt;/a&gt;, works very well for exploration.  More on that in the next post.  Right now, here's some fun things to try:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Download the &lt;a href="http://popper.tigris.org/servlets/ProjectDocumentList"&gt;latest version of Popper&lt;/a&gt;, and give it a try&lt;br /&gt;&lt;li&gt;Mail &lt;a href="mailto:saff@mit.edu"&gt;me&lt;/a&gt; with feedback, or if you'd like to participate in a case study, with a hands-on tutorial&lt;br /&gt;&lt;li&gt;Read &lt;a href="http://shareandenjoy.saff.net/2006/12/new-paper-practice-of-theories.html"&gt;our paper&lt;/a&gt; on the background of the Theories idea.&lt;br /&gt;&lt;/ul&gt;</description><link>http://shareandenjoy.saff.net/2007/04/popper-and-junitfactory.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-2836844414384686355</guid><pubDate>Thu, 26 Apr 2007 21:42:00 +0000</pubDate><atom:updated>2007-04-26T11:42:42.150-07:00</atom:updated><title>assertThrownException</title><description>In my &lt;a href="http://shareandenjoy.saff.net/2006/12/interface-imposterization.html"&gt;previous post&lt;/a&gt;, I described imposterization, a pattern for which I'm finding new uses.  What can imposterization do for us?  Let's look at testing for thrown exceptions. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;In JUnit 3, this is the standard way of testing that a method throws an exception:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;public void testIndexOutOfBounds() {&lt;br /&gt; try {&lt;br /&gt;   new ArrayList&lt;string&gt;().get(0);&lt;br /&gt;   fail("Should have thrown exception");&lt;br /&gt; } catch (IndexOutOfBoundsException e) {&lt;br /&gt;   assertEquals("Index: 0, Size: 0", e.getMessage());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When creating JUnit 4, Kent and Erich recognized that this was a very commonly repeated pattern, and created an annotation-based way of testing for a thrown exception:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Test(expected=IndexOutOfBoundsException.class)&lt;br /&gt;public void indexOutOfBounds() {&lt;br /&gt; new ArrayList&lt;string&gt;().get(0);&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There are advantages to each approach.  The explicit try/catch block looks more like the expected client code, and allows assertions about more than just the type of the thrown exception.  However, as with any repetition, an experienced user starts to glaze over the details of the test, and can miss important mistakes, such as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void testIndexOutOfBounds() {&lt;br /&gt; try {&lt;br /&gt;   new ArrayList&lt;string&gt;().get(0);&lt;br /&gt;   // OOPS!  Now the test will pass even with no exception!&lt;br /&gt;   // fail("Should have thrown exception");&lt;br /&gt; } catch (IndexOutOfBoundsException e) {&lt;br /&gt;   assertEquals("Index: 0, Size: 0", e.getMessage());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With imposterization, we can get the succinctness of the annotation-based approach while allowing arbitrary assertions about the thrown exception:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Test public void indexOutOfBounds() {&lt;br /&gt; IndexOutOfBoundsException e = new IndexOutOfBoundsException("Index: 0, Size: 0");&lt;br /&gt; List&lt;string&gt; emptyList = new ArrayList&lt;string&gt;();&lt;br /&gt; assertThrownException(is(e)).when(emptyList).get(0);&lt;br /&gt;}&lt;br /&gt;&lt;/string&gt;&lt;/string&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This now looks even less like expected client code, but it almost reads like English, and provides a one-line statement of the behavior I expect.  Here, I'm using imposterization as a technique for building a mini-language, just as jMock 2 does for setting expectations.  This kind of imposterization I might call &lt;em&gt;syntactic&lt;/em&gt; imposterization: the impostor only appears in the test code, in order to refer to methods of the interface.  I could then use the term &lt;em&gt;semantic&lt;/em&gt; imposterization for uses in which the impostor is used in the same context that an original implementor would be used--for example, a mock object, or a capturing decorator from test factoring.&lt;br /&gt;&lt;br /&gt;The expression &lt;tt&gt;is(e)&lt;/tt&gt; uses Matchers from the &lt;a href="http://code.google.com/p/hamcrest/"&gt;hamcrest&lt;/a&gt; project, giving me a lot of power to express properties of the exception that's thrown.&lt;br /&gt;&lt;br /&gt;When developing a mini-language using syntactic imposterization, it can be tricky to make the interface comprehensible.  It would be wonderful to be able to say:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; assertThat(exceptionThrownBy(emptyList.get(0)), is(equalTo(e)));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This would use the &lt;a href="http://joe.truemesh.com/blog/000511.html"&gt;assertThat&lt;/a&gt; statement made famous by Joe Walnes, which I love, but unfortunately, the expressions that I'd like to talk about often have void return values, making it impossible to compile the above statement.  Therefore, the verb must always go to the end, resulting in statements that sometimes read a little more like German, or perhaps &lt;a href="http://www.starwars.com/databank/character/yoda/"&gt;Yoda&lt;/a&gt;.  There's three ways I've noticed so far to get around this problem without making my natural language brain hurt too much:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Dick and Jane&lt;/b&gt; style: in this style, I create a mutable object that remembers the methods called on it, and repeat the noun to finish the thought:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;MethodCall mc = new MethodCall();&lt;br /&gt;mc.calls(emptyList).get(0);&lt;br /&gt;assertThat(mc, will(throwException(is(e))));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Fragment&lt;/b&gt; style: this is like Dick and Jane, only the noun is implicitly stored in global state or the host object, making the statements stateful.  This is how JMock captures expectations:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;call(emptyList).get(0);&lt;br /&gt;assertThrownException(is(e));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Subordinate clause&lt;/b&gt; style: this style, already shown in the first code example, puts the result before the verb, allowing everything to take place in one statement, if perhaps a little backwards:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;assertThrownException(is(equalTo(e))).when(emptyList).get(0);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Currently, I'm mixing the types of syntax imposterization in my tests, for asserting on thrown exceptions, as above; for identifying methods to be operated upon by my custom test framework:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;FunctionPointer function = new FunctionPointer();&lt;br /&gt;function.pointsAt(this).getStringReturnsA(null);&lt;br /&gt;Object[] stubs = oldPopulator.stubsFor(function);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;for identifying prerequisite tests:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;onlyIfPassing(StubValueTableTest.class).cantAddSameValueTwice();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and for generating custom matchers based on observer method calls:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public static Matcher&lt;iviewreference&gt; hasId(final String id) {&lt;br /&gt;ViewReferencePropertyMatcher matcher = new ViewReferencePropertyMatcher();&lt;br /&gt;matcher.mustMatch(id).getId();&lt;br /&gt;return matcher;&lt;br /&gt;}&lt;br /&gt;&lt;/iviewreference&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However, I plan to try to coalesce a couple of these uses.  I'm currently in the overuse phase* of syntax imposterization, and looking to bring my code back to its most readable state.&lt;br /&gt;&lt;br /&gt;* Thanks to Martin Fowler for &lt;a href="http://www.martinfowler.com/articles/rake.html"&gt;identifying&lt;/a&gt; this phase.</description><link>http://shareandenjoy.saff.net/2006/12/assertthrownexception_20.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-8182494023115932625</guid><pubDate>Wed, 20 Dec 2006 14:37:00 +0000</pubDate><atom:updated>2006-12-26T14:16:11.056-08:00</atom:updated><title>Interface imposterization</title><description>I learn all sorts of things from &lt;a href="http://jmock.org/"&gt;jMock&lt;/a&gt;.  From jMock 1, I was infected with the idea of a fluent interface for creating mocks, and the power of Constraint objects.  Lately, I've been playing with jMock 2, and it's had me thinking even more deeply about a pattern I'm for the moment calling &lt;span style="font-style: italic;"&gt;interface imposterization&lt;/span&gt;.*&lt;br /&gt;&lt;br /&gt;To explain imposterization, I'd like to make a distinction between two kinds of subtypes of a given type (for this discussion, let's consider implementations of a Java interface).  An &lt;span style="font-style: italic;"&gt;implementor&lt;/span&gt; of an interface satisfies all of the documented and implied contracts for that interface.  An &lt;span style="font-style: italic;"&gt;impostor&lt;/span&gt; of an interface is also an implementation, as far as the object runtime is concerned, but is free to violate the interface contracts, in order to learn or assert or learn a property about the code that uses it.&lt;br /&gt;&lt;br /&gt;If you've run across &lt;a href="http://www-128.ibm.com/developerworks/library/j-mocktest.html"&gt;mock objects in unit testing&lt;/a&gt;, then you've already seen one instance of imposterization.  Consider constructing a mock for a BankAccount interface, in order to test a woefully primitive transaction processor, using jMock 1 syntax:&lt;br /&gt;&lt;pre&gt;interface BankAccount {&lt;br /&gt; void deposit(int amount);&lt;br /&gt; void withdraw(int amount);&lt;br /&gt; int getBalance();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Test public void readDeposit() {&lt;br /&gt; BankAccount account = mock(BankAccount.class);&lt;br /&gt; account.expects(once()).method("deposit").with(eq(1000));&lt;br /&gt; TransactionReader reader = new TransactionReader(account);&lt;br /&gt; reader.readLine("deposit 1000");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Here, &lt;tt&gt;account&lt;/tt&gt; is an impostor of the BankAccount interface.  It's not really a proper implementor, because there are all kinds of contracts, perhaps documented, and perhaps implied, that our mock BankAccount breaks.  For one thing, it probably throws an expectation exception when &lt;tt&gt;getBalance()&lt;/tt&gt; is called, something that no proper implementation of BankAccount would do.  But we're not trying to create a general-purpose implementation--the point of our imposterization is to learn something about the &lt;tt&gt;readLine&lt;/tt&gt; method: does it interact in the right way with &lt;tt&gt;account&lt;/tt&gt;?&lt;br /&gt;&lt;br /&gt;jMock 2 also uses imposterization to set expectations on mock objects.  Here's the same test in jMock 2 syntax:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Test public void readDeposit() {&lt;br /&gt; BankAccount account = mock(BankAccount.class);&lt;br /&gt; expects(new InAnyOrder() {{&lt;br /&gt;   one(account).deposit(1000);&lt;br /&gt; }});&lt;br /&gt; TransactionReader reader = new TransactionReader(account);&lt;br /&gt; reader.readLine("deposit 1000");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Here, the result of &lt;tt&gt;one(account)&lt;/tt&gt; is a different impostor, which records a method call (&lt;tt&gt;.deposit(1000)&lt;/tt&gt;) as a method call expected to be called later in the test.   &lt;tt&gt;one(account)&lt;/tt&gt; doesn't make any pretense of being a real &lt;tt&gt;BankAccount&lt;/tt&gt;.  From the point of view of the intent of object-oriented design, this is almost pure evil.  But it is useful, because it reduces the "meta-noise" of the test.  Rather than having to invent a new language to talk &lt;span style="font-style: italic;"&gt;about&lt;/span&gt; a method invocation, we can use regular Java to just invoke the method itself.**&lt;br /&gt;&lt;br /&gt;Impostors are not a new idea to me--my thesis work on &lt;a href="http://pag.csail.mit.edu/pubs/test-factoring-ase2005-abstract.html"&gt;test factoring&lt;/a&gt; involves creating "capturing decorators" to record invocations, and mocks to replay them--both kinds of impostors that we saw above.  This is done automatically to create unit tests from arbitrary program executions, and run them after program changes, without the developer having to really know what's going on under the hood.  &lt;br /&gt;&lt;br /&gt;The new idea from jMock 2 is that plain-Java interfaces for creating impostors can be quite elegant and succinct.  Knowing this, more and more problems begin to suggest imposterization to me.  In my next post, I'll talk about using impostors to simplify testing exception-throwing methods, and later, we'll look at using impostors to automatically generate stubs for verifying &lt;a href="http://shareandenjoy.saff.net/2006/12/new-paper-practice-of-theories.html"&gt;Theories&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;* The name imposterization comes from the interface Imposteriser in jMock 2.  However, I won't claim that the jMock authors had exactly the same idea of what imposterization means, and I'll just have to agree to disagree about the -ize vs. -ise ending, thanks to &lt;a href="http://en.wikipedia.org/wiki/A_Dictionary_of_the_English_Language"&gt;Samuel Johnson&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;** The idea of using an interface impostor to record mock object expectations has been around in EasyMock (and perhaps other frameworks) for a while.  The benefits of this syntax are not without costs--I have always been uncomfortable with EasyMock's two-phase mock objects, which first capture and then replay, with a global method call in the middle to switch state.   That smells to me of a missed abstraction. jMock 2 also, it turns out, uses two-phase mocks under the covers, but the interface at least encourages thinking about the recording phase differently, since developers call &lt;tt&gt;one(account).deposit(1000)&lt;/tt&gt; instead of directly &lt;tt&gt;account.deposit(1000)&lt;/tt&gt;.  But I still have the same concerns that something is being missed.</description><link>http://shareandenjoy.saff.net/2006/12/interface-imposterization.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-1369319845952405108</guid><pubDate>Thu, 07 Dec 2006 16:49:00 +0000</pubDate><atom:updated>2007-01-31T10:55:09.159-08:00</atom:updated><title>New paper: The Practice of Theories</title><description>I've been enjoying my time working with Agitar to better understand how we think about testing, and how to use those tests to make our tools smarter.  We've recently written a paper on an extension to the idea of unit tests and test-driven development.  Share and enjoy, and please post your thoughts.&lt;br /&gt;&lt;br /&gt;[Copyright notice: &lt;span class="moduleText"&gt;This                     work has been submitted to the IEEE for possible                     publication.       Copyright may be transferred                     without notice, after which this version may                     no longer be accessible.]&lt;/span&gt;&lt;br /&gt;&lt;p style="margin-left: 0.25in;"&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;&lt;span style="font-size:12;"&gt;&lt;a href="http://shareandenjoy.saff.net/tdd-specifications.pdf"&gt;The Practice of Theories&lt;/a&gt;: Adding "For-all" Statements to "There-Exists" Tests  (David Saff, &lt;span id="st" name="st" class="st"&gt;Marat&lt;/span&gt; Boshernitsan) Submitted to &lt;a href="http://www.computer.org/portal/site/software/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"&gt;IEEE Software&lt;/a&gt;, Special Issue on Test-Driven Development. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-left: 0.25in;"&gt;&lt;b&gt;&lt;span style=";font-family:Times New Roman;font-size:100%;"  &gt;&lt;span style="font-weight: bold;font-size:12;" &gt;Abstract:&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; Traditional unit tests in test-driven development compare a few concrete example executions against the developer’s definition of correct behavior. However, a developer knows more about how a program should behave than can be expressed through concrete examples. These general insights can be captured as theories, which precisely express software properties over potentially infinite sets of values. Combining tests with theories allows developers to say what they mean, and guarantee that their code is intuitively correct, with less effort. The consistent format of theories enables automatic tools to generate or discover values that violate these properties, discovering bugs that developers didn't think to test for.&lt;br /&gt;&lt;/p&gt;</description><link>http://shareandenjoy.saff.net/2006/12/new-paper-practice-of-theories.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-271602854405531639</guid><pubDate>Wed, 06 Dec 2006 11:53:00 +0000</pubDate><atom:updated>2006-12-06T03:56:01.498-08:00</atom:updated><title>Hamcrest and generics</title><description>I like using &lt;a href="http://sourceforge.net/projects/hamcrest"&gt;hamcrest&lt;/a&gt; in my tests, but it has depressed me more than once how Java's generic typing rules force hamcrest to make odd typing choices.   I've never investigated thoroughly, however.  Luckily, someone else &lt;a href="http://agileworks.blogspot.com/2006/12/so-much-for-java-generics.html"&gt;has&lt;/a&gt;.</description><link>http://shareandenjoy.saff.net/2006/12/hamcrest-and-generics.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-115513659366481128</guid><pubDate>Wed, 09 Aug 2006 15:13:00 +0000</pubDate><atom:updated>2006-08-09T08:16:33.693-07:00</atom:updated><title>BeforeClass and AfterClass on Suites</title><description>The documentation of JUnit 4 does leave out some feature gems, including this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@RunWith(Suite.class)&lt;br /&gt;@SuiteClasses({ATest.class, BTest.class, CTest.class})&lt;br /&gt;public class MyTests() {&lt;br /&gt;   @BeforeClass public void setupDatabaseBeforeEverything() { ... }&lt;br /&gt;   @AfterClass public void teardownDatabaseAfterEverything() { ... }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will run&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;setupDatabaseBeforeEverything&lt;br /&gt;ATest&lt;br /&gt;BTest&lt;br /&gt;CTest&lt;br /&gt;teardownDatabaseAfterEverything&lt;br /&gt;&lt;/pre&gt;</description><link>http://shareandenjoy.saff.net/2006/08/beforeclass-and-afterclass-on-suites.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-115457728137298139</guid><pubDate>Thu, 03 Aug 2006 03:50:00 +0000</pubDate><atom:updated>2006-08-02T20:54:41.373-07:00</atom:updated><title>Meeting JUnit at a party</title><description>[Actually, I'm still car-trip-lagged enough that I actually thought of &lt;span style="font-style: italic;"&gt;two&lt;/span&gt; metaphors for why you might want to try JUnit on a green field project first.  I didn't think this one nearly as well, but it's interesting enough that someone might be able to make good on what I'm trying to say...]&lt;br /&gt;&lt;br /&gt;I think there's something deep in the summary message on the &lt;a href="http://sf.net/projects/junit"&gt;JUnit  project page&lt;/a&gt; on SourceForge (I didn't write it, so I can praise it):&lt;br /&gt;&lt;br /&gt;"JUnit is a simple framework for writing and running automated tests. As  a political gesture, it celebrates programmers testing their own  software."  There &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; something political about JUnit.  JUnit has an  agenda.  JUnit wants programmers to be able to test their own software.   When JUnit finds itself in a room with objects that are cleanly  encapsulated, each with its own responsibility, and clear ideas as to  the right and wrong behavior in any given situation, JUnit can let its  hair down, get to work, and have some fun.&lt;br /&gt;&lt;br /&gt;However, there are other things to value than "programmers testing their  own software".  One example that's going on 10 years old is "programmers  quickly producing dynamic database-backed web pages".  At these parties,  code can often be embedded directly into HTML, database connections are  provided by implicit containers, and important functionality is put in  global functions so it's available immediately wherever it's needed.   JUnit goes to these parties, too, but at first, things can be a little  uncomfortable.</description><link>http://shareandenjoy.saff.net/2006/08/meeting-junit-at-party.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-115457699416023468</guid><pubDate>Thu, 03 Aug 2006 03:43:00 +0000</pubDate><atom:updated>2006-08-02T20:49:54.193-07:00</atom:updated><title>Taking JUnit on a first date.</title><description>A &lt;a href="http://groups.yahoo.com/group/junit/message/17266"&gt;recent post &lt;/a&gt;to the JUnit mailing list has me thinking.  I got into JUnit because I really &lt;span style="font-style: italic;"&gt;liked&lt;/span&gt; writing test cases.  But I really respect some people that have been really frustrated with JUnit and decided there are better uses of their time than gung-ho unit testing.  Is there more going on here than personal preference?  I think there might be.&lt;br /&gt;&lt;br /&gt;Have you tried working with JUnit on a simple, non-database-backed, non-web-fronted application?  Perhaps a personal toy, like &lt;a href="%28http://www.xprogramming.com/xpmag/OkSudoku.htm%29"&gt;Sudoku&lt;/a&gt; or &lt;a href="http://junit.sourceforge.net/doc/testinfected/testing.htm"&gt;currency conversion&lt;/a&gt;?  Here is a place JUnit can easily shine--you have a green field to build cleanly encapsulated objects with clear responsibilities.  It's on code like this that I learned to love test-driven development, and JUnit for doing TDD in Java.&lt;br /&gt;&lt;br /&gt;If you try something like that, and you still don't like it, then move on.  I do not recommend slogging away with something that makes you suffer just because someone else said it was a good idea.  (Unless that person's your boss, in which case I'm sorry, and please hang around &lt;a href="http://groups.yahoo.com/group/junit/"&gt;here&lt;/a&gt; for some concrete advice.) Come back to it in a year or so. &lt;br /&gt;&lt;br /&gt;If, however, you do like it, then when you come back to your "real-world" tasks, with database integration, JSP web pages, fuzzy specifications, and everything else that we all know is out there, maybe you'll find ways to make these tasks a little more like the green field "toys" you started with.  Or maybe you'll at least have gained some motivation to spend some more time trying to test some of the harder components.&lt;br /&gt;&lt;br /&gt;I've heard complaints that many of the JUnit tutorial material ignores these "real world" issues, and there's some point to that.  Although it's not necessary for databases and web frameworks to be test-adverse (I think that Ruby on Rails shows this pretty well), many are, and we could do a better job pointing to the excellent concrete resources out there for resolving these conflicts.  On the other hand, gung-ho unit testing is a delicate new relationship.  The fact that a first date happens over candlelight and Chianti doesn't mean the relationship won't eventually survive a 17-hour car trip with two cranky young children.  But first things first, perhaps?</description><link>http://shareandenjoy.saff.net/2006/08/taking-junit-on-first-date.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-114217753377703748</guid><pubDate>Sun, 12 Mar 2006 15:30:00 +0000</pubDate><atom:updated>2006-03-13T05:40:26.500-08:00</atom:updated><title>junit.sourceforge.net updated</title><description>We've updated the homepage and some of the documentation at &lt;a href="http://junit.sourceforge.net"&gt;junit.sourceforge.net&lt;/a&gt;. This should make it easier to distinguish the JUnit 3.8.x documentation from the JUnit 4.x docs. Let me know if anything looks confusing. Share and Enjoy!</description><link>http://shareandenjoy.saff.net/2006/03/junitsourceforgenet-updated.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-114185528526906653</guid><pubDate>Wed, 08 Mar 2006 21:51:00 +0000</pubDate><atom:updated>2006-03-10T08:22:34.390-08:00</atom:updated><title>Getting started with JUnit 3.8.2</title><description>&lt;span style="font-family:times new roman;"&gt;There will be cool things posted here soon about JUnit 4.0, and actually 4.1, which will be released as soon as SourceForge gets its servers back in shape. Trust me. In the meantime, there's another problem I need to address.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;Recently, we released &lt;a href="http://sourceforge.net/forum/forum.php?forum_id=541181"&gt;JUnit 4.0&lt;/a&gt;, which uses annotations (from Java 5), years of added experience (from Kent and Erich), and some new ideas which could never work (from me) to provide the simplest and best unit test development framework out there. Seriously. Try it. It's very compatible: JUnit 4 tests can be run by JUnit 3 runners, and JUnit 3 tests can be run by JUnit 4 runners.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;However, it turns out that&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol style="font-family: times new roman;"&gt;   &lt;li&gt;Kent and Erich had put time into a more incremental release after JUnit 3.8.1.&lt;/li&gt;   &lt;li&gt;Not every developer and manager in the world is ready for Java 5, even if it allows them to use the simplest and best unit test development framework out there.&lt;/li&gt; &lt;/ol&gt;&lt;span style="font-family:times new roman;"&gt; So, we released &lt;a href="http://sourceforge.net/forum/forum.php?forum_id=547331"&gt;JUnit 3.8.2&lt;/a&gt;, and the world is good. However, this creates an awkward situation. We now have two versions of JUnit out there, but only one body of online documentation. So most online resources are either applicable only to JUnit 4 (The FAQ, for example), or mostly to JUnit 3 (junit.sourceforge.net, for example, although everything said there also applies to the JUnit-3-compatible part of JUnit 4).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;This situation will persist until more effort can be put into reviewing and clarifying the documentation. In the meantime, I'll try to post snippets of useful information here. For example, here's how to get started with JUnit 3.8.2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol style="font-family: times new roman;"&gt;   &lt;li&gt;&lt;a href="http://sf.net/projects/junit"&gt;Download it&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;   &lt;li&gt;Unzip it&lt;/li&gt;   &lt;li&gt;From the junit3.8.2 directory, run the tests by running&lt;/li&gt; &lt;/ol&gt; &lt;span style="font-family:courier new;"&gt;java -classpath .;junit.jar junit.textui.TestRunner junit.samples.AllTests&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;Share and enjoy!&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;</description><link>http://shareandenjoy.saff.net/2006/03/getting-started-with-junit-382.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-112003408739218830</guid><pubDate>Wed, 29 Jun 2005 08:32:00 +0000</pubDate><atom:updated>2005-06-29T01:35:08.270-07:00</atom:updated><title>Continuous Testing and Cruise Control</title><description>I'm currently the primary developer of the &lt;a href="http://pag.csail.mit.edu/continuoustesting"&gt;Continuous Testing plug-in for Eclipse&lt;/a&gt;. I've been asked several times to explain the difference between continuous testing and the CruiseControl tool for continuous integration. Here's how I explained it recently:&lt;br /&gt;&lt;br /&gt;What is the difference between continuous testing and cruise control?&lt;br /&gt;&lt;br /&gt;Cruise control is a software package that implements the process of  continuous integration.  In &lt;a href="http://www.martinfowler.com/articles/continuousIntegration.html"&gt;the most famous article on the subject&lt;/a&gt;, Martin Fowler calls continuous integration"a fully automated build and test process that allows a team to build and test their software many times a day," and discusses how the CruiseControl framework was built and used at ThoughtWorks to aid in continuous integration. The idea is that once the build and test process is automated, the best way to make sure that it's run "many times a day", and to get the benefits of doing so, is to make an automated daemon responsible for running through the process on every check-in to the repository.&lt;br /&gt;&lt;br /&gt;At another point in the same article, Fowler states "Developers typically run some subset of the unit tests with every compile as they are writing the software. This actually speeds up the development work since the tests help to find any logic errors in the code you're working on. Then, rather than debugging, you can look at the changes since you last ran the tests. Those changes should be small and thus it's a lot easier to find the bug." The idea of continuous testing is that the best way to make sure that the unit tests are run "with every compile", and to get the benefits of doing so, is to make an automated daemon responsible for doing so.&lt;br /&gt;&lt;br /&gt;In short, continuous integration and continuous testing are both good ideas that require either developer discipline or automated support.&lt;br /&gt;CruiseControl automates continuous integration to catch errors quickly:&lt;br /&gt;- for an entire team&lt;br /&gt;- on a shared server&lt;br /&gt;- several times a day&lt;br /&gt;&lt;br /&gt;Our plug-in automates continuous testing to catch errors quickly:&lt;br /&gt;- for a single developer&lt;br /&gt;- on the developer's workstation&lt;br /&gt;- several times an hour, or more</description><link>http://shareandenjoy.saff.net/2005/06/continuous-testing-and-cruise-control.html</link><author>David Saff</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-10879650.post-110857982407997438</guid><pubDate>Wed, 16 Feb 2005 18:44:00 +0000</pubDate><atom:updated>2006-03-10T08:36:32.343-08:00</atom:updated><title>Wooba Wooba?</title><description>Just in case you find this currently-unpublicized blog, an explanation of the name. In a Sesame Street sketch of long ago, a child asks Super Grover to her make her computer work. Grover's suggestions get more and more preposterous, ending with the suggestion that he hop up and down on one foot while saying "Wooba wooba". Eventually the girl figures out that the computer needs to be plugged in.&lt;br /&gt;&lt;br /&gt;Hence, my tech-stuff blog.&lt;br /&gt;&lt;br /&gt;[Editor's note, 2006 March 10: I've changed the name to Share and Enjoy.  No offense meant to Super Grover, but I couldn't help tinkering.]</description><link>http://shareandenjoy.saff.net/2005/02/wooba-wooba.html</link><author>David Saff</author></item></channel></rss>