I’m writing some integration tests around the .NET PetShop, which has no tests whatsoever. Since the architecture is tightly coupled, you can’t really start writing unit tests effectively. You have to start applying Michael Feather’s techniques for breaking dependencies. Before doing that, I want some smoke tests around the application. That’s where WatiN comes in. I am writing integration tests at the browser level. These tests are slow because you’re exercising the full stack – browser to web server to database. You need at least some of these full stack tests in every application. A good heuristic (for a large application) is a few dozen full stack integration tests, a few hundred presenter/controller integration tests, and a few thousand unit tests. (Smaller applications would probably be a dozen full stack integration, 50 presenter/controller integration, and a few hundred unit tests.) Enough testing theory… I wrote the following unit test:
[Test]
public void CanLoadHomePage() {
using(var ie = new IE(“http://localhost:9999”)) {
Assert.AreEqual(“Welcome to .NET Pet Shop Evolved”, ie.Title);
}
}
When I ran the test (using Gallio‘s awesome ReSharper 4 Unit Test Runner support for MbUnit), Internet Explorer appeared, but I got a failed unit test:
and this stack trace (reproduced in text form from the image for Google’s indexing benefit):
WatiN.Core.Exceptions.TimeoutException: Timeout while waiting for main document becoming available
at WatiN.Core.WaitForComplete.ThrowExceptionWhenTimeout(String timeoutMessage)
at WatiN.Core.WaitForComplete.WaitWhileMainDocumentNotAvailable(DomContainer domContainer)
at WatiN.Core.WaitForComplete.WaitForCompleteOrTimeout()
at WatiN.Core.IEWaitForComplete.DoWait()
at WatiN.Core.DomContainer.WaitForComplete(IWait waitForComplete)
at WatiN.Core.IE.WaitForComplete()
at WatiN.Core.IE.CreateNewIEAndGoToUri(Uri uri, LogonDialogHandler logonDialogHandler, Boolean createInNewProcess)
at WatiN.Core.IE..ctor(String url)
at WatiNTests.HomePageTests.CanLoadHomePage
Alrighty then. A TimeoutException and the Internet Explorer* instance was left stranded on my desktop. Taking a look at WatiN’s FAQ, I find this:
Which windows versions are supported?
Windows 2000, Windows XP and Windows 2003. Using WatiN on Vista gives some problems when User Account Control (UAC) is enabled. If you disable UAC almost all WatiN unit tests pass.
Disable UAC to run a testing framework??? Note that I’ve used WatiN on Vista before without disabling UAC. So it had to be some other setting. I noticed that Internet Explorer was running in Protected Mode, which dramatically limits the damage that a hijacked browser can do. Protected Mode runs IE in low integrity mode. (Low integrity processes are dramatically limited in which window messages they can send to higher integrity processes – such as Visual Studio and where they can read/write files.)
Solution
The obvious solution is to turn off IE Protected Mode for the site. Easiest way to do this? Add the site to your trusted sites list.
Survey says!
So rather than turning off UAC or Protected Mode in IE completely, you can just add the site under test to your trusted sites list and WatiN works.
For the Paranoid
The astute among you may be wondering if I haven’t opened up a security vulnerability by adding http://localhost to my trusted sites list. Let’s put it this way… If some l33t haxor can drop files on your box and start a webserver, they have already pwned your box. They don’t need you to navigate to a local site with unprotected IE to infect you more.
* For the curious, I rarely use IE, mostly just for certain Microsoft sites that are still IE only. Heck, I’ve been running RCs of FireFox 3 for awhile and upgraded to the RTM version yesterday when it was released. If you haven’t tried FireFox 3, you really need to. Gmail is oodles faster in FF3 than IE or FF2. You might wonder why I’m using IE with WatiN… WatiN only started supporting FireFox as of WatiN v2, which is currently in CTP. Historically WatiN (and WatiR) have relied on IE’s COM automation API to interact with the browser, which is also why WatiN/R doesn’t provide a way of getting HTTP status codes – because the COM API doesn’t expose them!