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
installer.
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
interface;.
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:
0: OK
-1: Tests failed
-2: Invalid ".nunit" file specified