| «« iBook Woes | Unit Test Eclipse View »» |
|
About
I'm Ryan Lowe, a Software Engineering graduate living in Ottawa, Canada. I like agile software development and Ruby on Rails.
I write this blog in Canadian English and don't use a spell checker. Typos happen.
Projects
» Full-time Ruby on Rails freelancer
» Full-time with Rails since May 2005 » Former committer for RadRails (now Aptana) » I also have a few Rails side-projects in development: 1. wheretogoinTO.com Toronto nightlife 2. Hey Heads Up! TODO list and sharing 3. Layered Genealogy family history research 4. foos for foosball scoring 5. fanconcert for music fans (on hold) Hiring Rails developers? I can telecommute by the hour from Ottawa, Canada »» Email: rails AT ryanlowe DOT ca
BulletBlog
Now hosted on Hey! Heads Up -- check it out!
Syndication
Pings
Recent
Derek Lowe's (Ryan's older brother) words at Ryan's funeral
blog@ryanlowe.ca no more Forging Email Headers: Good, Bad or Ugly? Sarcastic Dictionary (Part 1 of Many) Tags Hierarchies Twisting Rails is Risky Business Risky Business? My Take on Early Alphas Whoa, it's August 2007 Closing Comments A Postscript to "Growth at the grassroots" »» All Blog Posts
Linkage
del.icio.us/ryanlowe
technorati/ryanlowe.ca/blog Aurora Roy Jim Andrew Trasker Travis Kibbee Karen Dr. Unk Ayana Van Bloggers Joel Spolsky Robert Scoble Tim Bray Dave Winer Raymond Chen James Robertson Ruby/Rails Bloggers rubyonrails.org weblog David Heinemeier Hansson Dave Thomas James Duncan Davidson Mike Clark Jamis Buck Signal vs. Noise Tobias Luetke Amy Hoy: (24)slash7 Jeremy Voorhis Eclipse Bloggers Planet Eclipse EclipseZone Luis de la Rosa Eclipse Foundation Kim Horne Billy Biggs Ian Skerrett Mike Milinkovich Bjorn Freeman-Benson Denis Roy
Archives
|
Java IOException and Code Coverage
Code coverage is pretty cool -- it lets you see how much of your code your unit tests exercise. The only problem is that there are a few strange cases which are hard or impossible to cover. An impossible coverage example is a private constructor with no accessor method. Library classes like java.lang.Math have private constructors because all of the methods are static. It doesn't make sense to have an object of this class so there's no way to get to the constructor for a good reason. Unfortunately coverage tools like jcoverage count the empty constructor as a missed line of coverage. Why do we care about one silly line? Well because from a project management perspective it's a lot better to say "we need to keep 100% code coverage" than it is to say "we need to stay as close to 100% as we can but we accept it's not possible because there are these weird cases...". Always being 100% is a hard and fast, easy to enforce rule -- if the developers are allowed to be less than 100% you'll never be able to keep track of all of the special cases the team had to work around. So covering all of the code is a good thing. So that brings me to my particular example -- the IOException. They are checked exceptions and you have to catch them at some point in your code. When you do, you'll have to cover those catch statements or you'll be less than 100% for code coverage. Throwing an IOException is not an easy thing to do (besides FileNotFoundException**) with regular files because it usually involves some sort of catastrophic I/O error, hence the name. My buddy Andrew reminded me of a great way to induce IOExceptions though: create a new class that subclasses the File class and override some of the read/write operations as necessary so that it always throws an IOException. Bingo, every time you use that dummy file you'll get the exception and cover your code. It's not a real file but it's the closest you can get. After all, you are testing your code and how it handles exceptions, not the File class. Actually, that isn't quite my example -- it involves a bit more. Our fourth year project's Java code is layered, and API calls are made down the layers. Most of the file-related calls look like this: public void upperAPIMethod(String filename) The user interface is above this method in the layering, so I want to throw my own special exception ApplicationException up to it. I don't want my UI dealing with IOExceptions (and others) -- just one type of exception that it can take the message out of and display in a modal dialog box. This method takes a string as input, has no output and throws an ApplicationException. Herein lies the problem: there is no string that will generate that ApplicationException! For black box unit testing, this is a very bad thing. So how could I change my method? public void upperAPIMethod(File fileToSet) Now I can pass my dummy file in and get the ApplicationException out. Great. The only bad part is that each layer (including the UI) needs to know about File objects instead of regular String objects. Is this really a bad thing? **I'm not concerned about FileNotFoundExceptions in this discussion because I catch them before IOException and throw an exception with a different error message -- "file not found" instead of "error reading file" Posted at October 29, 2003 at 11:19 PM ESTLast updated October 29, 2003 at 11:19 PM EST Comments
I'd probably go with the coupling of a File over a string. I am guessing your concern is that you may want to move beyond just files (aka urls / uris) and your upper api methods wouldn't need to change? Maybe? Anywho, that's what refactoring is all about. Do you know of free .net code coverage tools? » Posted by: andrew at October 30, 2003 09:49 AMNot really ... that is the problem with the .NET world: you have to pay for almost everything. » Posted by: Ryan at October 30, 2003 10:29 AMGood idea with for creating the IOExceptions andrew... » Posted by: kris at November 4, 2003 10:40 AMGreat comments guys. Peter FDA » Posted by: Peter at November 11, 2003 02:28 AMCheck out http://workspaces.gotdotnet.com/ncover for a free .net code coverage analysis tool. » Posted by: Peter Waldschmidt at January 18, 2004 09:01 PM |