Monday, July 08, 2013

Thoughts on unit testing

comment on Programmer's StackExchange has started me thinking again about a question I posted a few years ago on the topic of unit testing.  The responses I received surprised me by how strongly and unyieldingly they were in favor of unit testing, some to the point of being offensive.  Looking back I can now see why that happened.

At the time I posted the question I was concerned I was missing out on an important aspect of being a developer.  I heard lots of talk about the importance of unit testing and the promise that test-driven development would take my code to an otherwise unachievable level of quality.

One cannot argue with the benefits of unit tests.  The safety net against regression. The documentation of intended behavior.  The method of fixing a bug by first adding a unit test to expose the bug, and then seeing the unit test turn green when you've fixed it.  How better to stamp out a bug?!  Who wouldn't want to have those assurances about their code?

But at the end of the day, I've always put one thing above all else: Getting the job done.  

My job at the time was writing line-of-business apps for a small company.  I was one of only a few developers and my customers were literally down the hall.  I didn't "ship" anything.  But I delivered lots of software to my fellow employees and often responded very quickly to add new features or new applications that would help them do their jobs.  Speed was crucial and my software was on a constant release cycle.  It is not the model scenario that is often highlighted in software development articles and books.

I had heard a lot of talk about trying to reach 100% test coverage and following TDD's write-tests-first-then-code approach (the red-green-repeat method.)  With the work I was doing those ideals just didn't make sense.  My gut told me so, but I went looking for validation anyway.

I asked "when is it appropriate to not unit test", and in hindsight that was too vague.  In my mind I was thinking along the lines of when is it appropriate to not fully invest in unit tests to the degree that TDD recommends or to worry about 100% test coverage.  I drew a line in the sand as if it were all or nothing, and naturally I sparked many heated responses. Furthermore, my question led to a blurred line between TDD and unit testing, which only led to more confusion.

The resounding answer was that of course I should unit test, and unit test everything.  Even Uncle Bob Martin chimed in with an all-or-nothing response detailing the benefits of TDD and 100% test coverage. He's absolutely right about the benefits, but his answer, and others in the same vein, misses the mark.  It is not black and white.  There's a lot of gray area here and many factors to consider, and there isn't one right answer to this question that fits all situations.

What did I take from all this? 

After working for a few years on a shipping product, my opinion is that we all should make unit tests part of our developer's toolbox. If you aren't doing it now, try it out. Use it in a real project. Get a test project setup, get used to running it regularly, and start by writing a few tests against an easily testable part of your code.  Get familiar with how they work.

Then see where things lead from there.  Erase this notion that you need 100% test coverage.  Don't worry about writing tests first.  Start small.  Maybe you get 10% coverage, but it's a heavily used 10% that is called from multiple clients.  Maybe you get really into testing and you get 80% test coverage but that last 20% is too difficult to make testable.  It's OK.

The best response I received, and good advice I'd give to anyone else is "...You don't have to test everything. Just the relevant things." from S.Lott. That woke me up to the idea that this isn't a plug-and-play solution and you have to decide for yourself how much to do.

Also, give TDD a try for a week.  Make yourself think about what you are writing to the point where you can write a unit test against it, and then write the code.  That's a great exercise even if you don't completely buy into TDD.  If it leads you to follow TDD regularly, great!  Don't feel bad if it doesn't work for you.

Keep in mind why you are doing it -- you're trading time now for better quality and stability in the long run. Whether you'll reap the benefits of that depends on what you are working on.

If you work with a lot of UI code you may come to the same conclusion as me, which is that there's usually too much friction to make this useful. So I don't write unit tests against that code. Instead I focused on writing them in a different layer where my application talks to a REST API.  It was a natural fit for unit testing, and it has simplified bug fixing and given me peace of mind that that code won't break in the future.

Tuesday, July 26, 2011

Calculating working days between two dates with Javascript

Here’s a script that will calculate the number of working days between two Date objects in Javascript.  I had a hard time finding an accurate one online so I wrote one myself – please use with caution as it has not been rigorously tested.

Note that the calculation considers the difference between today and today to equal 1.  I’m using this to present the number of days left before an event, and in my case on the day of the event it makes sense to see “1 day” instead of “0 days.”  

function workingDaysBetweenDates(startDate, endDate) {

// Validate input
if (endDate < startDate)
return 0;

// Calculate days between dates
var millisecondsPerDay = 86400 * 1000; // Day in milliseconds
startDate.setHours(0,0,0,1); // Start just after midnight
endDate.setHours(23,59,59,999); // End just before midnight
var diff = endDate - startDate; // Milliseconds between datetime objects
var days = Math.ceil(diff / millisecondsPerDay);

// Subtract two weekend days for every week in between
var weeks = Math.floor(days / 7);
var days = days - (weeks * 2);

// Handle special cases
var startDay = startDate.getDay();
var endDay = endDate.getDay();

// Remove weekend not previously removed.
if (startDay - endDay > 1)
days = days - 2;

// Remove start day if span starts on Sunday but ends before Saturday
if (startDay == 0 && endDay != 6)
days = days - 1

// Remove end day if span ends on Saturday but starts after Sunday
if (endDay == 6 && startDay != 0)
days = days - 1

return days;
}

Thursday, May 19, 2011

If I have to tell you what to do...

The recent This Developer's Life podcast features the StackOverflow team discussing pressure and how they dealt with the site's unexpected downtime in October 2010. About 31 minutes in, Scott Hanselman interviews Jeff Atwood, and Jeff revealed an eye-opening insight into how he runs his company. Speaking about his team, he remarks:
If I have to tell you what to do...you suck.
He prefaces that statement with an assurance that it's tongue-in-cheek. But there is truth behind that statement. He goes on to say he "unleashes" his team, and expects them to come to him with ideas that he can "simply sign-off on." He maintains the vision and keeps them moving in the correct direction. Unlike a traditional work environment where the boss tells the subordinate what to do, here the team's drive comes from the bottom-up.
I found this fascinating. I want to work that way. Being a solo-developer at my company, I play both roles to a degree, setting the direction for a project while trying to come up with creative ideas to enhance it. But working alone it is hard to validate whether the way I work would fit within a team environment. It is really motivating to have this insight on how this successful company (for which I have a ton of respect) operates.

Wednesday, September 29, 2010

Getting Twitter’s @Anywhere hovercards to work based on URLs

Twitter has a cool script you can add to your site to turn any references to a twitter account into a helpful hovercard that shows the twitter user, some stats, and a Follow button.  It’s subtle and useful, but it could be a little easier to add for developers.

I won’t repeat what is already available on the docs at Twitter, but the gist is if I put @kpespisa in a post, the @anywhere script will find that and turn it into a hyperlink that shows a hovercard when you put your mouse over the link. 

Sadly I noticed there was no simple way to get a hovercard to appear based on the URL of a hyperlink.  If I added a link that says “Follow me on twitter”, it would be nice to have the hovercard appear when I hover over that hyperlink as well. 

Adding a little jQuery gets the job done.  Using this code, you can just set the URL to http://twitter.com/(twitteraccount) and it will create a hovercard for you using the twitter account that is in the URL.

   1: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
   2: <script src="http://platform.twitter.com/anywhere.js?id=AMyKqypXu1r6qmOvc5OZCQ&amp;v=1"></script>
   3: <script type="text/javascript">
   4:     $(document).ready(function() {
   5:         $("a[href^='http://twitter.com']").add("a[href^='http://www.twitter.com']").attr("title", function() {
   6:             return '@' + this.href.substr(this.href.lastIndexOf('/') + 1);
   7:         });
   8:     });
   9:  
  10:     twttr.anywhere(function(T) { 
  11:         T.hovercards(); 
  12:         
  13:         T("a[title^='@']").hovercards({
  14:             username: function(node) {
  15:                 return node.title;
  16:             }
  17:         });
  18:     });
  19: </script>

For example:  Follow me on Twitter!

Thursday, May 06, 2010

DotNetRocks in Boston


This past Monday I went to see the Boston stop of the DotNetRocks road trip, hosted by Carl Franklin and Richard Campbell. The duo put on a good event, bringing in guest Chris Sells for their podcast, as well as a panel of guests to discuss F#.

The portion of the evening I found most interesting was the F# discussion. I didn't expect to get much out of it. I had heard enough of F# to that point to make up my mind that it wasn't for me. I reasoned that if it isn't a language I can completely switch to, I'm better off focusing on VB or C#.

So I was surprised when I heard the F# experts suggest that we use the language to complement our projects rather than use it as an all-purpose language. They encouraged us to use the language for its strengths, such as asynchronous processing and parallelism. One could create an assembly written in F# and include that in a VB project, for example, to handle some heavy computations. We already use a handful of non-core languages in our projects such as HTML, Javascript, LINQ or SQL, so the idea of blending yet another language into our projects is not a foreign concept.

The panel suggested we add F# to our repertoire and understand its strengths, and use it where it's beneficial. I'm going to take that advice. Bottom line is if I can replace 50 lines of confusing C# code with 10 lines of elegant F#, I've done myself a service.

A big thank you to Carl and Richard for their hard work in putting this event together, and for entertaining me with their podcasts during my commutes, jogs, walks, and housework.

Tuesday, May 04, 2010

Setting up a Mercurial server on Win2k3 / IIS 6.0

There are several tutorials right now explaining how to setup a Mercurial server in Windows, but most are outdated just enough to make the whole process fail due to recent changes to Mercurial.  I tried a few, but the best one available as of Mercurial 1.5.2 is from Matt Hawley from eWorldUI.net.  His post explains how to set up the server using IIS 7.0, and the process is slightly different in IIS 6.0, as I’ll explain.

First, read his blog post to get a sense of the procedure.  The post is broken into two major sections, Packages Installation, and Configuration.  I followed the Packages Installation section exactly as written, with the exception of downloading the latest source for Mercurial, which is 1.5.2. 

Once you’ve completed the Packages Installation, follow these steps instead to configure IIS 6.0.  Many of these steps are the same as Matt describes, but for convenience I’ve duplicated them here.  All credit for this goes to Matt for getting us 99% of the way there. 

These steps assume you have IIS installed already.

  1. Create a folder to host your Mercurial site.  As Matt suggests, you can use c:\inetpub\hg
  2. Copy the hgwebdir_wsgi.py file from c:\(mercurial source code location)\contrib\win32 to c:\inetpub\hg
  3. Edit hgwebdir_wsgi.py in a text editor and change the two lines as follows:

    hgweb_config = r’c:\inetpub\hg\hgweb.config’
    path_prefix = 0
  4. Open a command prompt and go to the c:\inetpub\hg folder
  5. Run python hgwebdir_wsgi.py.  If python isn’t installed on the system path, you may need to include the path to it and use c:\python26\python hgwebdir_wsgi.py
  6. Create a new text file named hgweb.config in the c:\inetpub\hg folder and add the following.  Here c:\repos is the folder where you will store your repositories.

    [paths]
    / = c:\repos\*
     

    At this point, your folder should look like this:
    image
  7. In IIS Manager, create a new application pool with the name Mercurial.
    image
  8. Create a new website called Mercurial, and set the TCP port to 81 (or any unused port).  Leave the Host header field blank.
    image
  9. Set the path to c:\inetpub\hg and finish the wizard.
    image
  10. Right-click the Mercurial website and choose properties.
  11. On the Home Directory tab, click Configuration, and then click Insert… in the Wildcard application maps section.  Enter the path to the isapi dll (c:\inetpub\hg\_hgwebdir_wsgi.dll) and uncheck verify file exists.
    image
  12. On the ISAPI filters tab, click Add… and enter Mercurial-ISAPI as the filter name and c:\inetpub\hg\_hgwebdir_wsgi.dll as the executable.
    image
  13. Finally, go to the Web Service Extensions in IIS Manager and Add a new Web service extension.  Give it the name Mercurial-ISAPI, and add the required file c:\inetpub\hg\_hgwebdir_wsgi.dll, and check the “Set extension status to Allowed” option.
    image
  14. Finally, browse to http://localhost:81 (or substitute 81 for the port you chose in step 8).  You should now see the Mercurial Repositories page!

    image

Wednesday, February 17, 2010

iPhone Game Rebates

Jon Lam, CEO of the game development company Ph03nix New Media, has started a new program to push iPhone games to the top of the App Store charts. The site, iPhoneGameRebates.com, will highlight a selected app for two weeks, offering a full rebate (up to $1) if you purchase that app and forward your iTunes receipt.
For a limited time, to build up a following, they are offering this program on any app in the App Store. The site is legitimate and I have already received my rebate, which was sent directly to my PayPal account.
How does this work? Essentially the app developers cover the cost of the rebate (meaning they lose the 30% commission taken by Apple), and in return their apps are pushed up the charts. By climbing the charts, the app is more exposed and more people are likely to buy it, thus covering the loss taken during the rebate period.
I'm definitely going to be a fan of this site, and can't wait to see what apps they give away starting next month!