Integration tests problems
I have run into an interesting problem today. I want to build a set of integration tests that exercise my UI. The problem is that I want my integration tests to:
- Talk to a test DB
- Setup all the data on their own
- Invoke the UI to do operation on the data they just entered.
- Verify the results
- Be debuggable
This basically means that for the duration of the unit test, I need to modify the connection string for the web site. The problem is that I need to restore it after the tests have run, which bring about the issue of failing tests and what state they would leave the site.
Any ideas how to solve this problem?
Comments
I've spoken to Marc-André Cournoyer about this problem, and what he does is to run a nant task to change the web.config containing the connection string before and after the test run. This is the approach I have adopted for Monorail testing because I have nothing better to suggest.
The way I've done it in the past is to make the mechanism the application uses for pulling a connection string come from an IoC tool (StructureMap/Castle/etc.).
In the test setup use some sort of code (don't know what the Castle equivalent is) like:
DefaultConnectionStringProvider provider = new DefaultConnectionStringProvider("connection string");
// inject this rigged provider as the default
ObjectFactory.InjectStub(typeof(IConnectionStringProvider), provider);
At my previous job we had a FitNesse fixture that we would use to set the connection string for one of the big bang tests suites in the setup:
!|EnvironmentFixture|
|The connection string is|whatever the connection string is|
I simply avoid storing a connection string in the web.config. I store the SQL Server instance and database names. If I ever need to change the way that we connect to the database, I'll change the code.
How do you change the username/password, move between SSPI authentication to SQL auth? Handle moves of a server, etc?
In our web services integration tests we follow the next approach:
Configuration iuConfig = GetConfig(@"......\RVIO.IU\web.config");
Configuration testsConfig = GetConfig(@"......\RVIO.Tests\app.config");
ConfigurationSection section = iuConfig.GetSection("nhibernate");
_oldRawXml = section.SectionInformation.GetRawXml();
section.SectionInformation.SetRawXml(
iuConfig.Save();
Configuration config = GetConfig(@"......\RVIO.IU\web.config");
ConfigurationSection section = config.GetSection("nhibernate");
section.SectionInformation.SetRawXml(_oldRawXml);
config.Save();
It is a quick and dirty solution (not as elegant as I would like), but it works for us.
I'm not so familar with the way that ASP.NET works (do all my stuff with Windows.Forms) so I don't know how much of this will apply, but for what it's worth ...
On a project I'm leading at work, applications access all the database functionality through a static class like this:
List<Person> allPeople = InventoryDatabase.Person.FindAll();
To break this down:
InventoryDatabase is the static class;
Person is a static property, returning an instance of IPersonRepository that provides an implementation of FindAll();
If no implementation is active when the static class is invoked, details are looked up from the app.config file and an appropriate instance is dynamically created.
The trick that allows for testing is that there's a way to provide an implementation, instead of only allowing one to be loaded from config.
When our tests run (we use FIT, see fit.c2.com) they begin by providing an in-memory implementation that is prepopulated as required.
At the moment, the in-memory implementations are written by hand (this is to keep it simple); My research to-do list includes finding out whether Rhino Mocks can do this more simply.
Hope this is relatively clear!
Keep Smiling,
Bevan.
Hi,
I see that people are trying to make a separation between the database on which you run the tests and the database on which you run the application. In the case of new projects, without legacy data this separation is an overkill.
The main problem with database tests, is that if you have more developers, and they run the tests at the same time, they'll break each other tests, and not separating the database as explained above.
What we do (on ms sql), is copy the database for each develper: ProjectNameDB_Dan, ProjectNameDB_Cristi etc. Syncronizing the structure isn't a problem anymore now that we have ActiveRecord Migrator (Marc Andre's) on place. The problem dissapears and we don't need to chage the configs at runtime.
In some cases we like to run the tests on an in memory database, but the gain in speed (20-40%) is sometimes lost because on MS SQL a bug appears although with SqlLite evrything works, or setting up the test database, eats a lot of our time.
Just my opinion,
I actually have two databases per developer :-)
One for developing and one for the tests.
The idea is that the tests can erase the database and the developer can have persistent data to play with.
Jeremy Miller stole what I was going to say, however he carries a bit more clout than I, so I'll just second his suggestion :)
@Luismi,
I ended up doing something very similar.
Comment preview