NH Prof Deep Dive: The Integration Test Architecture

I am getting a lot of requests to explore the actual innards of the NH Prof. I find it surprising, because I didn't think that people wimageould actually be interested in that aspect of the tool.

But since interest was expressed, I'll do my best to satisfy the curiosity.The first topic to discuss is the integration test architecture. One of the things that the profiler is doing is to capture data from a remote process, and I wanted my integration tests to be able to test that scenario, which exposes me to things like synchronization issues, cross process communication and (not incidentally), allows me to test scenarios that looks just like real code.

The integration tests project for NH Prof is not a dll, it is an executable. And when you execute it you can ask it to run a specific scenario (specified using command line parameters).

Let us take an example of such scenario:

public class SelectBlogByIdUsingCriteria : IScenario
{
public void Execute(ISessionFactory factory)
{
using (var session = factory.OpenSession())
using (var tx = session.BeginTransaction())
{
session.CreateCriteria(typeof(Blog))
.Add(Restrictions.IdEq(1))
.List();
tx.Commit();
}
}
}

And now that I have the scenario, we can write a test that uses it. Here is the first test that I wrote using this approach:

[TestFixture]
public class CanGetDataFromSeparateProcess : IntegrationTestBase
{
[Test]
public void SelectBlogById()
{
ExecuteScenarioInDifferentProcessWithDefaultConfig<SelectBlogByIdUsingCriteria>();
var sessionModel = observer.Model.Sessions.First();
StatementModel selectBlogById = (StatementModel)
sessionModel.Statements.Where(x=>x is StatementModel).First();
const string expected = @"SELECT this_.Id as Id\d_\d_,
this_.Title as Title\d_\d_,
this_.Subtitle as Subtitle\d_\d_,
this_.AllowsComments as AllowsCo\d_\d_\d_,
this_.CreatedAt as CreatedAt\d_\d_
FROM Blogs this_
WHERE this_.Id = 1
";
Assert.IsTrue(Regex.IsMatch(selectBlogById.Text, expected),selectBlogById.Text);
}
}

There are a couple of interesting things going on here. First, we can see the IntegrationTestBase, which has methods such as ExecuteScenarioInDifferentProcessWithDefaultConfig (the config controls the communication mechanism).

Then, all I need to do is assert on the actual model that was built as a result of executing the scenario.

Executing the scenario involves running the integration test project as an executable, and passing it the scenario to execute. This tests cross process communication, expose threading issues and in general means that I have a realistic view of what is going to happen in the actual application.

Print | posted on Thursday, November 06, 2008 5:04 PM

Feedback


Gravatar

# re: NH Prof Deep Dive: The Integration Test Architecture 11/6/2008 7:57 PM Avish

Just a quick off-topic regarding enumerable extension methods:

you can replace this:

StatementModel selectBlogById = (StatementModel)
sessionModel.Statements.Where(x=>x is StatementModel).First();

with this:

StatementModel selectBlogById =
sessionModel.Statements.OfType().First();

Which avoids the explicit cast and is more intention-revealing.


Gravatar

# re: NH Prof Deep Dive: The Integration Test Architecture 11/6/2008 7:59 PM Avish

Er... did subtext just eat my generic parameters because they looked like Xml?

I meant Statements.OfType<StatementModel>().First(), of course.

Comments have been closed on this topic.