Monday 16 April 2012

Unit Testing when the success case is compilation failure (with C++)

There is an issue with the use of Window’s COM types being used with STL containers in versions of Visual Studio prior to 2010. The crux of the matter is that various COM types define the address-of operator and instead of returning the real address of the object they return a logical address. If the STL container re-arranges its contents this can lead to corruption as it can unwittingly manipulate an object at the incorrect address.

The prescribed solution to this problem is to not place the COM types directly into the STL container but instead wrap them with the ATL CAdapt class.  When adopting this approach there are two important aspects to consider:

  • Firstly, is there a way to prevent incorrect usage of the containers?
  • Secondly, assuming this is possible, is there a way to make sure it covers the various permutations of STL containers and COM types that are being used?

It turns out that the first issue is easily solved using template specialization.  The hard part though is creating  a set of unit tests that ensure specializations have been created for all permutations and that they are active.  This is made even more difficult by the fact a successful use of the specialization results in compilation failure.

This too can be solved by combing various template mechanisms and techniques: SFINAE & Template Meta-programming etc.  In the April issue of the ACCU Overload journal I have written article that describes this problem along with the solution.  Please follow the link below (and then jump to page 24 in the PDF if it doesn't open there automatically).

http://accu.org/var/uploads/journals/overload108.pdf#page=24

The complete source code the article is also available on GitHut: https://github.com/petebarber/TemplateArticleExamples

Monday 2 April 2012

Using NUnit and Entity Framework DbContext to programmatically create SQL Server CE databases & specify the databse directory

NOTE: An update to the method used here is provided in this newer post: Integration Testing with NUnit and Entity Framework.

I won't go into the why but I wanted to write what probably amounts to an integration test of an Entity Framework model.  I decided to use NUnit for this.  Even though it's predominately for Unit Testing there's no reason why it can't be used for other forms of testing.  In fact I think the SpecFlow BDD framework eventually performs its tests using NUnit: It's not what you've got but what you do with it!

The application I'm writing uses SQL Express but for my tests I wanted to create & destroy a database frequently and locally so I opted to use SQL Server Compact Edition.  This is pretty easy to do with EF's DbContext: just create an instance of it, pass in either the name of the database or a Connection String, e.g.


[Test]
public void TestWithConnectionString()
{
  var db = new DbContext("Name=Foo");


  db.Database.Create();
}

which references the following Connection String in the .config file


<connectionStrings>
  <add name="Foo"
    providerName="System.Data.SqlServerCe.4.0"
    connectionString="Data Source=foo.sdf"/>
</connectionStrings>



As I'm going to be potentially creating many of these I wanted precise control over their name and location.  This meant I didn't really want to use a Connection String as this is more or less hard-coded in the .config file.

Instead I opted to create it programmatically.  By default DbContext expects to be using SQL Server in particular an instance of SQLExpress named .\SQLExpress.  This is easily changed by replacing the DefaultConnectionFactory with the factory class for SQL Server CE: SqlCeConnectionFactory.

The first parameter to the constructor is the type of the factory class which allows instances of different versions to be created. This is simply the providerName as per the Connection String.  The second parameter is the directory to create any new databases in.  The third parameter (unused in the example below) are options to append to the generated Connection String.  The code below will result in the creation of C:\UsersPete\TestDBs\bar.sdf assuming the directory exists and the user has appropriate permissions and bar.sdf does not already exist.


[Test]
public void TestWithFactory()
{
  Database.DefaultConnectionFactory = 
    new SqlCeConnectionFactory(
      "System.Data.SqlServerCe.4.0", 
      @"C:\Users\Pete\TestDBs\", "");


  var db = new DbContext("bar.sdf");

  db.Database.Create();
}

That's mainly it:  A simple way to programmatically create databases.  This code should really be moved to the SetUp method and a corresponding TearDown method added to delete the database; oh, and some tests!

I haven't got that far yet and the actual reason for writing the entry was for a short while despite specifying the directory for the databases, i.e. C:\Users\Pete\TestDBs they were being created in the current working directory.  This was because rather than just specifying the name of the database as the argument to DbContext I was passing the string "DataSource=bar.sdf" of which the name part appears to be an absolute path and thus override that specified in the SqlCeConnectionFactory.  As only a file name is present it uses the current working directory for the path element. If you've got the same issue (whether integration testing or not) this might save you a little time.