Monday, September 30, 2013

When to Create a SetUp Method

I recall from back when the Earth was cooling and I was spending a of time in Seattle (read: "living there") that there was a lot of advice flying around about the forces surrounding designing individual tests.

A particular point of interest was when to factor stuff out into a setup method.  One camp said "never factor something into a setup method until it's needed by more than one test."  Another camp said "factor stuff out into a setup method as soon as you reasonably can."

At the time, I didn't really care so I just went along with my friends.  Now I think I do care.  I've noticed that factoring certain things out into a set up method improves the readability of a test, even when there is only one.

That, to me, settles the "when" question by obviating it and uncovering a much more interesting question: what should you factor out into a set-up method?

I've noticed that, for me, there are two kinds of set-up needed: context stuff and test-specific stuff.  The context stuff is obvious.  The test-specific stuff is interesting.

For a human, there is no information in a context-setting line of code.  It is still informative to a compiler, which is why you need it, but a person trying to understand an API would easily fill in the blanks if he never saw that line of code.  The only real effect such a line of code has on a human-reader is to make a test less-readable by adding noise.  An example of context-setting set-up is instantiating the class being tested.

By contrast, the test-specific line of code is very interesting to a human.  It explains what is happening or why it is happening.  Examples of test-specific code would be invoking a method on the class under test or asserting on the results of such an invocation.

Let's look at two examples.

Here's a test with all the set-up in the test method to prevent a preemptive refactor:

[Test]
public void UnderOrdinaryCircumstancesPassesThroughToCore()
{
  var core = new Mock<PathFinder>();
  var specialEdge = new Mock<PathFinderEdge>();
  var specialEdgeFinder =
    SpecialFirstEdgePathFinder.GetInstance(core.Object, specialEdge.Object);
  var origin = Design.Element.GetInstance(null, null, null);
  var keyPath = new[] { Any.Symbol, Any.Symbol };
  var elementPath = new[] {
    Design.Element.GetInstance(null, null, null),
    Design.Element.GetInstance(null, null, null), };
  core.Setup(c => c.Navigate(origin, keyPath)).Returns(elementPath);

  var actual = specialEdgeFinder.Navigate(origin, keyPath).ToArray();

  Assert.That(actual, Is.EqualTo(elementPath));
}

Here's a test with all the set-up in the test method to prevent a preemptive refactor:

[Test]
public void UnderOrdinaryCircumstancesPassesThroughToCore()
{
  var keyPath = new[] { Any.Symbol, Any.Symbol };
  var elementPath = new[] {
    Design.Element.GetInstance(null, null, null),
    Design.Element.GetInstance(null, null, null), };
  core.Setup(c => c.Navigate(origin, keyPath)).Returns(elementPath);

  var actual = specialEdgeFinder.Navigate(origin, keyPath).ToArray();

  Assert.That(actual, Is.EqualTo(elementPath));
}

The two tests specify the exact same thing.  The only difference, in my mind, is how they read.  To me, the latter is a lot more clear than the former.

The process that works for me is as follows:
  1. Write the test with no set-up to discover what the test should be
  2. Make the test pass
  3. In the refactoring phase, move all the "clutter" to a context-setting setup method
I'm open to other arguments but this is working for me now.

Sunday, September 29, 2013

I want to put together a little club of Trikke riders

It's getting close to the end of the riding season in Central Oregon.  I still like to ride in the winter time when the roads are clear.  There's got to be at least one more Trikke rider somewhere in the Bend area.  If that's you and you want a riding partner for some chilly afternoon runs of 3-10 miles somewhere in Bend, let me know.

Tuesday, August 27, 2013

Code Retreat for JavaScript and Ruby Developers

I'm thinking of putting together a little meetup where I can help developers who prefer Ruby and JavaScript improve their focus and discipline.  Both languages have critical flaws in them that make it harder to adhere to object-oriented principles and, as a result, developers who choose these languages must require a far greater amount of concentration in order to do a good job.

To that end, I'd like to announce my plan to create a JavaScript and Ruby Developer Concentration Camp.

Any takers?

Thursday, July 25, 2013

So Long, Old Friends

This is the complaint I submitted to Starbucks and my final communique with them, I suppose.

I terminated the auto-reload on my card because of the changeover to La Boulange.  Of course, it doesn't bother me that you added their products to your offering - what reasonable person would be bothered by that?  However, in so doing, you took away all the good food items. 
Worse, there was basically no warning.  We just walked in one day and, boom, there was all this new stuff.  Then we tasted it and it was much, much, much worse than what you had before.  The chocolate croissant was pretty much inedible and the cookie I tried on my next visit was exactly inedible.  I threw it in the trash, which is where I feel it should have been placed before finding its way into your display case. 
Starbucks was a big part of my life.  It was a little ritual in which my wife and I have regularly engaged.  That ritual has been defiled, now, and I no longer partake.  Right now, it is difficult to imagine ever going back to a Starbucks.  Even if you got rid of La Boulange, I feel so betrayed that I'm not sure I would consider coming back. 
Goodbye.
Everybody who hates the La Boulange changeover, which is probably most of the people who think for themselves, should boycott Starbucks.  It won't change their behavior.  They're so big and have so many people snowed into believing this is a good thing that there's no way they'll pivot on this.  What it might do is amass together enough demand to create a supply-vacuum, sucking a new entity into existence that can fill the role that Starbucks once did.

Friday, June 28, 2013

Ender's Game

I'm certainly not the first one to this party.  I remember one of my childhood friends being very excited by this book long ago.  I was skeptical at the time, as I am always skeptical about basically everything.

When the movie was announced, I resolved to read the book before I watched it.  Now, I'm reticent to watch the movie.  Unlike the case of The Great Gatsby, it's not because I was bored by the book.  Quite the contrary, I thought the book was so good that I cannot imagine the movie living up to it.