2011/04/11

Integration tests, NHibernate and Sqlite, part 2 – in file database

Integration tests, NHibernate and Sqlite, part 1
Integration tests, NHibernate and Sqlite, part 2 – in file database
Integration tests, NHibernate and Sqlite, part 3 – enhanced in memory database

SqliteInMemorySharedScope issues
The disadvantage is that the time needed byc SqliteInMemorySharedSope instantiation grows with the size of the tested domain model. When the domain model is complex enough then execution of test suit may take unacceptable amount of time.

Storing the database in a file
Sqlite is able to store the database in a file as well. We create a database with its schema at first and store it in a file, let’s call it master file. Then it is easy to create a copy of the master file. Individual tests touch only own copy of the master file. So isolation is preserved and dependency between the time of database scope instantiation and complexity of the domain is significantly more moderate.

SqliteInFileDatabaseScope
The new session is connected to the private copy of the master file.
public ISession OpenSession()
{
    ISession session = SqliteInFilePrivateScope.sessionFactory.OpenSession(this.privateConnection);

    return session;
}

The private connection is created in the default constructor.
public SqliteInFilePrivateScope()
{
    EnsureMasterDatabaseExistence();

    // to avoid name collisions in parallel scenario
    this.privateDatabaseFileName = Guid.NewGuid().ToString() + ".db";

    File.Copy(masterDatabaseFileName, this.privateDatabaseFileName);

    string connectionString = BuildConnectionString(this.privateDatabaseFileName);
    this.privateConnection = new SQLiteConnection(connectionString);
    this.privateConnection.Open();
}

The master file, configuration and session factory are created only once per test suit run.
private static object configurationSync = new object();

private void EnsureMasterDatabaseExistence()
{
    // to support parallel execution of unit tests
    lock (configurationSync) {
        if (configuration == null) {
            string connectionString = BuildConnectionString(masterDatabaseFileName);
            configuration = BuildConfiguration(connectionString);
            sessionFactory = configuration.BuildSessionFactory();

            SchemaExport schemaExport = new SchemaExport(configuration);
            schemaExport.Execute(false, true, false); 
        }
    }
}

Connection string factoring:
private static string BuildConnectionString(string databaseName)
{
    return string.Format("Data Source={0};Version=3;New=True;", databaseName);
}

And BuildConfiguration is delegate that is injected on test suit initialization (for more details see this post):
public static Func<string, NHibernate.Cfg.Configuration> BuildConfiguration;

The full example is here.
The same example but using Microsoft Sql Server Compact Edition instead of Sqlite is here.
Complete source code can be downloaded here.

Why to support parallel scenarios in Visual Studio 2010
Tests are executed sequentially by default in Visual Studio and there is no setting to turn on parallel execution in VS2010 GUI. To achieve this, the file with test settings must be tweaked. The name of the file is Local.testsetings by default:
<TestSettings name="Local" id="caf44e0f-3ee4-46bf-a6ed-73aea6d93533" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Description>These are default test settings for a local test run.</Description>
  <Deployment enabled="false" />
  <Execution parallelTestCount="2">
    <TestTypeSpecific />
    <AgentRule name="Execution Agents">
    </AgentRule>
  </Execution>
</TestSettings>

Attribute parallelTestCount specifies how many tests are executed at one time. Parallel execution makes sense in these days of multicore processors because it can reduce the execution time of whole test suit. And it counts when doing continuous integration. You can find much more information in this blog post.

1 comment:

  1. Hello,
    The Article on Integration tests, NHibernate and Sqlite, part 2 – in file database is informative. It gives detailed information about it.Thanks for Sharing the information on Integration Testing .For More information check the detail on Integration testing check, Software Testing Company

    ReplyDelete