Web tests, unit tests, the ASP.NET Development Server, and Code Coverage
If you're using Windows Server 2008 and UAC, you may have had some difficulty getting the code coverage data on an IIS web application. There's something called "Session 0" isolation that's there to protect your web server from unauthorized access. I'd set up most of my web applications as "HTTP" applications instead of using "File System" web applications, and I'd done my debugging and testing. In my runs, I typically see "Empty results generated".
An alternative is to use the built in ASP.NET Development Server. When you're putting web or unit tests together, though, you'll need to fill in the "UrlToTest" attribute, or you'll need to parameterize your web server and set it up for the ASP.NET development server.
How to set up the web server is described in http://msdn.microsoft.com/en-us/library/ms184806.aspx, but I just didn't get it. After emailing with one of our engineers, I found out how it works. Once I knew what was going on, I found a number of links that helped describe this approach:
- I Wish I Knew Now What I Knew Then » Unit Testing Web Applications in VSTS
- Unit Test ASP.NET Pages with Team Build
- Dot Net Core
- Alan's Development Blog - December, 2007
- Confusion with UrlToTest Attribute - MSDN Forums
- Re Problem with UrlToTest - Web service Unit testing - MSDN Forums
- More on Unit Testing TestContext - Md. Adil Akhter's Weblogs
- Anutthara's WebLog
On either the web tests or the unit tests, you'll need to make sure that your web site is set up as a "File System"-based project. When you select the web site project, the properties will give you the option to use the developer web server, set the virtual path, use dynamic ports, and whether to start while debugging. Otherwise, you'll need to manually start the ASP.NET development server (e.g. from the command line).
For the web tests, you click on "parameterize web servers", edit the one you want (click the "Edit" button on the right), and set it up as an ASP.NET development server. You'll get a dialog like:
Just set the path as the path to the site (unlike the "/" in the image above). The test runner will configure the test with the correct root URL and port. You can also use an environment variable for the path so that the web site can run as part of a team build.
There is something almost magical that happens when you're running a unit test. You configure the AspDevelopmentServerHost attribute with the path and the application root, and you configure the UrlToTest with the URL (http://localhost:1234/adventureworks), and you run the test. The first attribute will start the development server on a random, unoccupied port. The port in UrlToTest can be any legal port--the test runner will replace the port you provide with the port the development server is actually using. You can fill in the host type by going to the "Test View" window and choosing an "ASP.NET" host type. For the other attributes, you'll have to type in the editor. You'll also need "using Microsoft.VisualStudio.TestTools.UnitTesting.Web" in your header. Your unit test method will look something like:
public void TestMethod()
You can use %PathToWebRoot% instead of the path above the application--that will help with Team Build.
At the end, you get code coverage when you run your test, and you can share these test configurations with other developers and testers without having to change the ports.
- If you use the unit test wizard from a class within a web project, Visual Studio will automatically populate the unit test method attributes for you--it stretches out a nice safety net for you. The places where you'll need to do this yourself are where you have pre-existing unit tests or where you create them from a project that isn't a web project.
- I was having problems with some unit tests. I would see a popup error dialog titled "ASP.NET Development Server", that indicated the port wasn't parse-able, and I would get an error in the test run saying "The test adapter 'WebHostAdapter' threw an exception while running test 'ConstructorTest'. Invalid URI: A port was expected because of there is a colon (':') present but the port could not be parsed." (sic). I went through a number of web searches, regenerated the web.config, turned on debugging and tracing of the test host (system.config instructions in this post), looked in the event log, and went through a bunch of other steps. Finally, I commented out the HostType, UrlToTest, and AspNetDevelopmentHost attributes and discovered that the unit tests called constructors that were throwing an exception that was preventing the ASP.NET development server from launching properly. Yet another example where I need to be careful searching instead of thinking.