August 2004 - Posts
One of the things that's irked me for quite some time is how, even in a mature TDD environment, the tests that are written never seem to make it past the integration server. Yet vast amounts of time gets spent tracing and fixing the differences between environments that cause glitches in execution. The time it takes to spot these errors and the fact that the installation of bad software has already occured makes it a bit like shutting the stable door after the horse has bolted. To me, it became apparent quite some time ago that tests shouldn't just be a means of validating refactorings and amends locally, they should also be a first line of defence when it comes to deploying to and troubleshooting environments (security factors aside).
So, after a few late nights over the last week, the project I've been working on has been finished - NUnit MSI. This application does pretty much what it says on the tin - it sits in MSI installers as a custom action and runs the tests as part of the installation package, deciding whether or not to continue installation based upon success (and the user's input if so desired). It can be downloaded from: http://www.altervisitor.com/software/NUnitMSI.msi, and here's a screenshot to give you an idea:
Screenshot of NUnit MSI
As well as running from within installers, I personally now use it as a custom build action to give me a "green light" that I've not broken anything, rather than having the heavier-weight NUnit GUI running all the time (although it is still useful for persistent errors and larger projects).
The code for NUnit MSI is based directly on NUnit v2.2 (2.2.0), and makes use of all the behind the scenes logic from that, just re-implementing the UI portion of NUnit. Full instructions are included in the archive, and are summarised (in brief) below. As a parting comment, if you use this, please let me know give me feedback - I'm all for extending it, polishing it, making it work as a VS.NET plugin, etc.
Running the NUnitMSI.exe application without any command line
parameters will look in the folder it resides in for the first file with a
.nunit file extension. This will automatically be loaded and the tests run.
If all the tests succeed, the application will pause for one second then
exit successfully. This is the exact same behaviour if it is added to a
Setup and Deploy project.
More advanced command-line usage takes the form:
NUnitMSI.exe [config.nunit] [/queryerrors]
Giving a relative filepath for "config.nunt" will cause the specified NUnit
project file to be loaded, instead of one being probed for.
The "/queryerrors" parameter will cause a dialog to be shown should errors
be detected, asking the user if they wish to continue with installation
regardless. The default is to NOT show this dialog, and for a failed test
to result in the installation rolling back. However, whenever tests fail,
whether this dialog is shown or not, the GUI does NOT automatically exit -
it remains open to allow the user to inspect the errors in more detail.
Usage example: "NUnitMSI.exe ../tests.nunit /queryerrors"
This basic-usage mode allows for NUnit MSI to be integrated with a local
build process as a "post build action", allowing for a succinct graphical
display of the test results, rather than requiring a heavyweight interface
such as the NUnit GUI, or having to parse the output of the command line
NOTE: once the tests have completed, pressing "F10" on the form will cause
them to run again. This is not documented in the GUI, but is useful when
running the application as an alternative to the standard NUnit GUI
NOTE: If the application does not have a ".nunit" file specified, and it
cannot locate one in the execution directory, it will exit automatically
with a status code of "-3". Other status codes are:
-1: Tests failed
-2: Invalid ".nunit" file specified
I wrote a bit of a monologue in an e-mail to some of the developers at work the other day about documenting code. I've never been a great fan of huge swathes of inline comments splitting up what's only 4 or 5 lines of self-explanatory code, so when the mantra of "code should be self documenting" came along, I didn't really have much of a reaction to it. But I've been thinking about that, and I came up with the following conclusion, which was the opening line of my e-mail:
When have you ever bought a professional product that didn't come with a manual?
By this, I'm not just talking software product, I'm inculding hi-fis, coffee makers, and so on. I'm still of the opinion that code within the body of a method should be self documenting. Personally, I probably write 1 line of comments for every 10-15 lines of code. And it's usually just a "section heading". However, there are occasions where we all have to write obtuse code; using logical bit-shifts in some CPU-cycle critical operation rather than do standard calculations, marshal some parameter differently because of a bug in a system being integrated with, and so on. Such things clearly need descriptions of why a choice has been made. This still only amounts to one single-line comment every few methods or so, but it means that self-documenting code is simply something to aim for that will never quite be achieved.
My real bug-bear has been with XML-documentation of code - the fact that developers seem to use the "code should be self documenting" mantra to protect them from having to document the public interfaces that others have to program against; which really isn't code-commenting at all. When was the last day working in Visual Studio .NET, you didn't make some use of MSDN? Whether it's Intellisense, hitting F1 on a method, or searching for a class in the MSDN Library? That documentation's all there because of XML comments. To me, putting a system into a live environment in a financial institution with no technical documentation for it is unprofessional - plain amateur, if you will. Yes, the code should be self documenting, but what about the purpose of each method? Details on where it's called from? The permissible values of parameters? Details on why something's changed from a previous version? What the code is specifically not supposed to support? How it deals with concurrency and locking issues?
This isn't about "commenting the code" - it's about when teams in an enterprise are moving between projects on a regular cycle, or when support is outsourced, or when your code is externally exposed for others to consume - it is aboslutely critical that documentation of this is produced in such circumstances. It just happens that one of the best tools for doing this, and allowing integration with other documentation/the development environment is NDoc. And it just happens that this works by having you insert the documentation into the code. Is this a coincidence? Not likely, if code and documentation are maintained separately, they will no doubt diverge, but having errors in the build process when doing continuous integration means there are no excuses for a system becoming unsupportable/opaque.
Thinking about it, it's in a developer's best interests, despite the extra time, effort, and clutter of the class (I really wish there was a neater way of handling this in .NET, such as a comment-behind file, as suggested). How many developers complain that they've become tied to a project, limiting their progression, all because of the entrenched knowledge of the intricacies, or the speed with which they can develop on it? When I ever get down to developing code nowadays, I now religiously document every class and public property/method, along with any non-obvious private members (i.e. ones that are hacked and I need reminding to come back to) - it's common courtesy both to myself and anyone else that ever comes across it.
Final thought: How long would it have taken you to learn .NET if none of the MSDN documentation had been present? What would the cost of that have been?
I use NUnit. A lot. Almost every time I hit compile, in fact. And I'm not a big fan of the command line version; there's a certain feel-good factor from seeing all of the orbs turn green. But this is where my problem lies with NUnit - although it's technically great, the interface just looks really clunky. Half of the problem is that it doesn't support Windows Themes - the controls neither have their FlatStyle set to System nor has the call to EnableVisualStyles been made. The rest of the problem is just to do with small tweaks around changing text to images, replacing the red/amber/green orbs with prettier ones, and so on.
So, as I've got an idea for another NUnit related project anyway, I decided to get to grips with the source code for it by refreshing the UI. Below are before and after pictures, and the updated files for running it yourself are here:
As I've not changed any real code, only the UI of the EXE (and a UI DLL), this archive simply contains two files to overwrite those that already exist in your NUnit folder. All your current existing projects, links, etc. should continue to work. Note that this is an update to the latest version at the time of writing - v2.2 (v2.2.0) , and will only work with this version.
If you like/don't like this update, please get in touch, as I'll be mailing the NUnit guys themselves over the next couple of days to see if we can't get the proper project updated.
Within the next couple of days I should have finished the NUnit-based tool I'm writing, too, which should be well worth the download...
Original NUnit 2.2 GUI
Updated NUnit 2.2 GUI
One problem that's always been apparent in .NET projects is applying changes in application configuration during deployment. There's a longer article I'm going to write shortly on managing differing configurations between environments in the enterprise. But for now, I've come up with a small utility that overcomes one glaring omission with .NET Setup & Deploy projects - taking settings entered within the installation wizard and applying them to the application being deployed. Whilst you can capture settings from the "User Interface Editor" screens quite nicely, and the web.config/app.config is a pretty good way of storing settings in smaller applications, there's no built-in way of combining the two. Obviously, in a larger application, a more structured way of storing data is needed than the .config files, and another deployment product such as those by Wise and InstallShield is more appropriate, but that still leaves the majority applications where the built-in VS.NET support chosen falls short of requirements.
So, as I had a small project to do for a colleague that needed a semi-professional installer, I came up with a WinForms application that would take configuration changes captured as part of the installer as part of it's command-line arguments (as name=value pairs), apply them, then close down, allowing for it to be added as a custom action in the installer. It supports a couple of other things, too - merging two config files, running without a UI, etc. It's available for download at http://www.altervisitor.com/software/NetConfigUpdater.msi, and is freely useable/distributable as long as the author credits remain intact. Usage instructions are included as part of the MSI. Feel free to post feature requests on the comments to this entry, and use the mailing form to send any bugs found back to me.
.NET Configuration Updater screenshot