Bloggin'bout Ivonna

Notes on new performance enhancements in Ivonna 2.1 

Saturday, February 06, 2010 7:30:44 AM

Ivonna 2.1 is due this weekend, and while I've been testing the final bits, I noticed a bug which cannot be fixed without changing the overall architecture, so I decided to leave it and be clear about it.

One of the most annoying things about Ivonna was her bad performance on startup. Every time I needed to run a test, the Asp.Net engine cleared the temp folder and recompiled the whole site. It would take up to several minutes, depending on the number of pages. So, in the 2.1 release, I decided to stub the whole thing. The startup time dropped to several seconds, which is sort of acceptable (note that each test itself takes much less time to run).

Everything went fine until I put some code in an App_Code class, and Ivonna couldn't load it. It turned out that no changes in the App_Code folder could be recognized by the test. However, changes in the codebehind are recognized.

The workaround is, whenever you make a change to or create an App_Code class, be sure to delete the temporary site folder, which is usually under the C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\ folder.

Ivonna 2.0.4 is out 

Sunday, December 13, 2009 6:52:04 AM

Compatible the the Isolator 5.4.5.

The big news is that you can now download Isolator and Ivonna in a single zip from the TypeMock page.

Ivonna 2.0.3 is out 

Saturday, November 07, 2009 5:14:25 PM

Just to catch up with the TypeMock Isolator development. I should have released this weeks ago, but.. no, really no excuse here.

The only improvement is adding the TestSession.SetUser method. Before that, you had to write something like

session.User = new GenericPrincipal(...)

Now:

session.SetUser("ulu", "admin");

Enjoy!

Ivonna 2.0.2 is out 

Wednesday, October 21, 2009 4:42:37 PM

You can get it at the download page, as always. Not much breakthroughs this time, but three handy spies that will simplify yor tests a bit.

Next will be the 2.1 release, with long-awaited AJAX support (page methods and maybe something else), and at last some optimization efforts.

Until next time..

Solving the performance issue 

Saturday, October 03, 2009 6:35:59 AM

One of the biggest problems about Ivonna is its performance. On medium sites, the first request to a page can take up to several minutes. The following requests are quite fast, however, which makes Ivonna more efficient than client-side tools when running big integration suites. However, doing the fast red-green-refactor cycles is.. not as fast as it should be.

After some investigation, I discovered that the the Asp.Net engine recompiles the web site when it receives the first request. Even if the site itself hasn't changed. A few more hours of digging (with the help of the excellent CThru's TraceAspect) revealed the whole picture:

  1. When the runtime creates a new AppDomain for the site, it recalculates the hash and compares it to the previous value.
  2. Since the test assembly has changed (even if it hasn't, since it's been copied to the bin folder, the timestamp has changed), the hash is different.
  3. The runtime clears the temp directory.
  4. On first request, it recompiles the site.

There are two tricks that can help us here. The first is pretty sraightforward: install a RAM drive and point the temp directory there:

<compilation debug="true" strict="false" explicit="true" tempDirectory="R:\temp"

The second is more esoteric: in the compilation tag, put  optimizeCompilations="true". This will skip checking the bin (as well as App_Code and resources) folder for modifications. So, sometimes you'd want to recompile -- you can do that by touching one of the aspx pages.

Integration Testing Your ASP.NET MVC Application 

Wednesday, June 17, 2009 3:54:54 AM

As you know, Ivonna supports testing MVC sites. However, the support is.. it works, but you can't do much about it. However, Steve Sanderson (the author of xVal) recently published a post about the MVC testing framework he's developed. It's based on the same idea as Ivonna: it's running in-process. However, since MVC is much more open for extension, this framework doesn't require "hacking" the runtime. It doesn't require TypeMock and, by the way, is completely free. You can read his post here.

I think it makes no sense to add MVC related features to Ivonna, unless this is really needed, so I'll continue the development in other directions.

Swapping a membership provider 

Wednesday, June 10, 2009 7:42:02 AM

It is always a good idea to hide your membership-related activity behind a service, instead of just using the MS provided API. However, I am currently building a prototype, and I wanted to use the built-in controls, which leaves me no choice but use the Membership API.

Turned out it's quite simple, you don't even have to create an aspect:

Dim section As MembershipSection = _
   ConfigurationManager.GetSection("system.web/membership")
section.Providers.Add(New ProviderSettings("InMemory", _
    "Tests.Membership.InMemoryMembershipProvider"))
section.DefaultProvider = "InMemory"

Here I add my custom provider to the configuration and set it as default.

Of course, this simplicity shouldn't fool you that this is a good idea in general.

Version 2: Dependency Injection and unit testing for Asp.Net 

Thursday, June 04, 2009 6:52:47 AM

Today I released the 2.0.1 version, but before I explain the new features, I wanted to say a couple of words about the whole 2.* idea.

When you do "regular" unit testing, you often need to redesign your class so that the collaborators are not instantiated but rather "injected". After that, you can inject a mocked version of some collaborator via the constructor, for example.

Unfortunately, we don't have that luxury when testing Asp.Net views, be it WebForms or MVC. We usually call something like "Default.aspx", or "Products/List", leaving no opportunity for DI. So, what can we do?

If we look at desktop applications, there's always a top-level code that is responsible for all wireup. It's either the Main function, or the config file. It's not covered by the unit tests, but rather unit tests tend to "swap" it for some mockup. And while they can bypass it by just calling the lower-level classes, we can also bypass it -- using TypeMock!

Here comes the solution for Ivonna: make it possible to change the production top-level code for test counterparts. Including the web.config file, HttpModules, and the HttpApplication class. This is the main idea for the version 2.*.

Here's what we have in the version 2.0.1:

  • We can modify the configuration, including, but not limited to, app settings and connection strings.
  • In case this is not enough, we can swap the entire web.config file for, say, test.config. Should be in the root directory of the Web, but I think this is a temporary limitation.
  • We can manipulate the HttpModules collection. Ok, actually, it's module types. This feature was implemented for the 2.0.0 and is already superceded by the writable configuration introduced in 2.0.1
  • In 2.0.2, we'll be able to plug into the point at which the HttpApplication is initialized, and modify some of its properties, including the Modules collection. Note, however, that this instance will be probably alive in the tests that follow.

Download it here.

testing Asp.Net MVC sites with Ivonna 

Sunday, May 17, 2009 4:21:30 PM

While Asp.Net MVC architecture is widely praised for its testability, it is seldom mentioned that the Views are still untestable. It is believed that you don't need to test your views since they are "dumb", and it's just too hard anyway. However, string-based ViewData and unevitable foreach pieces make the View fragile, and you just can't leave it untested.

While you can't have a Page instance with all its structured beauty, you can still test your MVC views with Ivonna. Remember, however, that the usual session.GetPage() won't work: you have to use something like session.ProcessRequest(new WebRequest("LogOn")), for example. Then use response.BodyAsString to get the raw HTML output, or other WebResponse to check for redirects or response status.

While this is all possible with client-side frameworks, the mere fact that we are in-process makes it possible to mock stuff. For example, you can mock the Controller, or the Model, or, say the membership provider.

BUG: LicenseException: This copy has expired 

Thursday, April 30, 2009 5:43:05 AM

If you are seeing this message, it is possible that you just don't have sufficient rights to read a certain registry key. This issue has been reported on a Windows 7 64bit box. To fix it, either run Visual Studio (or your test runner) as an admin, or relax the permissions for the following key:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\TypeMock\TypeMock.NET\Packs\Ivonna

Copyright 2008 by me