Monday, March 28, 2011

Easily Updating A Release With Fedora...

At home I have a perimeter server that runs Fedora. It's a machine I rarely think about, sitting on the fringe of my home network. I never SSH into it and instead only hit it for Subversion or Git repositories I have there for personal use.

So today I was working and, for some reason, decided to go an update the installed packages and do some general housekeeping on the box. And while on I realized it was a release behind, running F13 while F14 is the latest (and F15 just went to Alpha).

I decided to upgrade it to F14 with an in-place upgrade using the following steps.

First things first. Go to multiuser mode and disable X:


init 3 

Install rpmconf (if you don't already have it):

yum install rpmconf -y

Clean up any configuration files with:

rpmconf -a --frontend=vimdiff

Upgrade the SSL certificates on F13:

rpm --import

Update Yum itself:

yum upgrade yum

Reset all yum cached package lists:

yum clean all

Now do a full distro sync:

yum --releasever=14 distro-sync

This is the longest part of the whole process since it's going to pull down every single upgrade for your system. For me it was on the order of about 900 packages.

When that finishes, you want to then make sure that all Base group packages are installed:

yum groupupdate Base

Now prepare your system for a full reboot:

/sbin/grub-install BOOTDEVICE
cd /etc/rc.d/init.d; for f in *; do /sbin/chkconfig $f resetpriorities; done
package-cleanup --orphans

Now you can reboot your system and have a fully working, running F14 (in this case) system.

Sunday, March 27, 2011

Straight But Not Narrow...

I saw a video this morning that brought back some memories.

I had a pin that I'd bought years before that which read "Straight But Not Narrow". The pin was always on my old denim jacket at the time and I wish I knew what had happened to it. It probably went the way of that denim jacket and was donated.

The message, though, hasn't changed in all these years. I'm straight, but I'm not narrow minded.

Saturday, March 12, 2011

Should A Unit Test Contain Only One Assertion?

In a previous post I wrote about questioning grades and a unit test assignment for a class I'm taking this semester. In this post I'm going to write about one of the items mentioned in the feedback I received, which was:

Test methods should contain only one assertion. This way, if a test fails then the program will be more helpful to say exactly which assertion failed (and therefore what the circumstances were that caused the failure).
I completely reject this assertion for two reasons: 1) a well written unit test framework should tell you exactly which assertion failed when there are more than one in a unit test and 2) having a single assertion per test makes the tests more fragile and increases the likelihood that the tests themselves will be flawed.

The first reason is fairly obvious. Since all runtime environments provide stack traces on exceptions, there's no reason why a unit testing framework can't display one on a failed assertion. So the framework can easily tell you which assertion within a single test failed. Therefore there's no reason to hav ea single assertion in a test since the stack trace can take you directly to the failure. And, additionally, mode IDEs will let you jump directly to the line so you can verify the failure and fix the cause.

So a single assertion per test method is not more helpful in finding the cause of a failure.

The second reason is the more serious of the two since I believe it leads to bad coding practices. That idea that unit tests should be limited to a single assertion per test assumes that a unit test is only verifying one specific post-condition. Take, for example, an object cloning operation:

public void testClone() {
    Farkle source = new Farkle();
    Farkle result = f1.clone();

    assertEquals(source, result);

In this example there are two assertions being performed: the first one ensures that an object was returned by the clone() method and the second ensures that the returned object fulfills the public contract for the clone() method; i.e., the object returned is identical to the original.

Now, if we were to follow the "one assertion per test" tenet then the above would have to be split into two unit tests:

public void testCloneReturnsAndObject()
public void testCloneReturnsEqualObject()

We've now doubled the number of test methods. However, we haven't done anything more than that. Sure, it can be argued that we have made the tests more specific and that that is itself a good thing. But we are now also required to setup the same test preconditions twice since both tests have to instantiate the same source and run the same method to produce the same post-condition only to test different aspects separately. This violates the concept of DRY and as such is a bad practice.

"Well, why not move the initialization into your setUp() method?"

The answer is this: setUp() (a method specific to JUnit, but each testing framework has its own analog) isn't supposed to setup every single test's preconditions. It's role is to setup the general preconditions for the entire test case itself..

To make setUp do the work for every single test would make it very inefficient. Since it is run before every one of the unit test in the class (in JUnit the setUp() method, or any method annotated with @Before, is called before every single unit test method is invoked). So that's a LOT of wasted set up work if we were to move all preconditions out of the tests themselves.

Additionally, by moving the preconditions out of the test methods we hide what the expected state is for those tests. Now you would have to go to the setup method to see details that should be right there in the test, making it harder than necessary to debug when code stops passing tests. Something easily avoided by keeping the precondition code in the test itself.

So now that I've defined why the preconditions need to stay in the test method itself, that leads us to the final reason why a single assertion per test method is a Bad Thing (tm): the test code itself could easily become invalid.

Imagine a slightly more complicated test, such as one that verifies five different aspects of the result of a method call.This also violates the DRY principle since we're doing the same setup in five different places. We also run the risk of the tests themselves changing as, with refactoring, one test will get updated while another may not. And down the road those differences can result in false negatives or, worse yet, false positives.

Instead, if we keep only the number of assertions as necessary in a unit test, we make the test themselves more expressive, by showing expected preconditions, and more targeted, by checking for expected outcomes.

Requiring tests to contain only a single assertion is a bad practice that leads to writing more code than necessary and either repeating yourself or else writing inefficient, and potentially ineffective, tests.

Always Question Your Grades...

Christene and I always tell our kids to go over tests and make sure the grade you received is the one your deserved. Teachers aren't always perfect and they do make mistakes. And it's not an insult to them to question why points are taken off for a problem: if it was valid then you can learn from it, and if it was invalid you can get it fixed.

This semester I'm taking a distance Java course at State. I posted about our first project a few weeks ago. The projects are split into two parts each: one part where you write the functional code, the other where you write unit tests to validate the code. As a professional developer, I've been using test driven development methodologies for years now. So when I sat down to do this assignment I wrote all of the tests as I wrote the code and ensured my code was at 100% test coverage and accurate.

On the functional portion I received 100%.

But on the unit test portion I only received 86%. So I emailed the TA to ask why I lost 14 points. In the feedback on the assignment it said that two of my 19 tests had failed, and I lost 7 of 10 points for each. But in my development environment no tests fail. I ran them in both Eclipse and also from the command line (the project is managed using Maven) and in both cases everything is perfect.

I'm just not sure how my tests could have failed if the code were working correctly. If anything, the tests ought to only work then if the code were flawed, which it's not.

I haven't heard anything back yet (I only emailed him a little while ago) but I'll post here whatever feedback I get.

Friday, March 4, 2011

Advanced Placement Night

After work last night, Caleb and I drove down to his high school for Advanced Placement Night. He's already taking honors classes and getting straight As, so both the school and Christene and I feel he would benefit from the AP classes.

The presentation was fairly straight forward. Mr. Reid gave a presentation about what the AP courses are and what students should expect, both out of the class and to put into the class.

Students will likely have a few hours additional work per day and required summer projects. But the benefits, college credits during high school, make it worth while.

After the presentation, Caleb and I visit the tables for the AP classes in which he's initially interested (US History, Chemistry, Biology, Calculus and Physics) to get their descriptions. The program also provided him with a road map of what honors classes he'll need to take prior to each of the classes. Then we sat and read, then discussed, the course descriptions.

From what I read it appears that the AP Physics class would cover a first semester Physics class, AP Chemistry would be Chem 1 & 2, AP Calculus would be a full Calculus program, and AP Biology would cover BIO 1 and most of BIO 2.

He's going to be in a good position to enter university given what's available, with most of his first year courses out of the way via AP classes.

Wednesday, March 2, 2011

How can something so simple taste so delicious?

The other night Christene and I had a simple dinner: some toasted italian bread, olive oil, some prosciutto and provolone and some artichoke topping.

The next day I took the left over bread, prosciutto and provolone and made a simple sandwich. I toasted the bread then drizzled olive oil on top. Nothing fancy.

It was awesome!

As the bread soaked up the oil and took on that fruity flavor, the sandwich just kept improving. Nothing fancy about it, certainly. But it had such a depth of flavor and body it transcended its ingredients!