Red-gate SQL Test

Writing unittests for sql objects was one of my blind spots. Red-gate has a tool called SQL Test that should fill in the gap. I have given it a try.

sqltest

SQL Test is a graphical user interface for tSQLt, a unittest framework for Microsoft Visual Studio. The GUI makes it much easier to use. It integrates with SQL Server Management Studio.

The first step to using the framework is to add the SQL objects to your database. This also enables the CLR.

install.tsqlt.framework

SQLCop can be installed together with tSQLt. These are database best practices like enable sql agent and data and log files on different disks. My development instance failed 7 tests. How about your production instance?

With new test you create a new stored procedure to run as a unittest. This can be done in your own schema, just make sure the extended property tSQLt.TestClass is set to 1 on the schema.

create.tsqlt.schema

The new test is made mostly of placeholder comments. You can use the following framework functionality:

  1. AssertEqual, checks variables are equal,
  2. FakeTable, creates a temporary table based on the table to fake, this isolates your unittests,
  3. AssertEqualsTable, checks the contents of two tables is the same,
  4. SpyProcedure, fake stored procedure, logs the parameters used in the call,
  5. ApplyConstraint, creates the constraint in the parameter on the FakeTable

More details in the references.

Final thoughts

SQL Test helps sql server development. It should be part of every (database) developer.
Keep in mind that it actually is tSQLt and SQL Cop with some GUI. You don’t need a license for all instances, just for the GUI. 💡

References

Posted in Tooling | Tagged , , , | Leave a comment

Week roundup

Last week recap an links:

Image courtesy of kanate / FreeDigitalPhotos.net

Image courtesy of kanate / FreeDigitalPhotos.net

What are your best reads this week? Leave them in the comments below.

Posted in Uncategorized | Tagged , , , , | Leave a comment

Integration Test with Entity Framework Codefirst

Our database is developed using Entity Framework Codefirst. Everything in code. Enabled migrations to update existing environments as we roll out. The code passed all the unittests, but it didn’t feel right. Time for an integration test.

This brought me to the idea to use Sqlite with an inmemory database. Installed some nuget packages, even wrote a MigrationSqlGenerator to create the tables and indexes, but no candy. The connection was closed before the first test fired and that killed the database.

Now I looked into SqlExpress as database engine. The problem was that existing data could influence the results. That is one of the problems with integration tests.

Entity Framework can dropcreate the database every testrun. This is slow, but that is again a problem with integration tests. I’ll show the differences (in code) between a unittest and an integration test below.

Unittest

Below is the code for the unittest. Some variable definitions are left out for clarity.

[Fact]
public void AddNewPerson_Creates_New_Person(){
    var business = CreateIsolatedBusinessObject();
    business.AddNewPerson(validName, validStreet, validNumber, validZipcode, validCity);
    business.Context.AssertWasCalled(x => x.SaveChanges());
}
private DoSomethingForTheBusiness CreateIsolatedBusinessObject() {
    var isolatedBusinessObject = new DoSomethingForTheBusiness();
    isolatedBusinessObject.Context = MockRepository.GenerateStub<IPeopleContext>();
    return isolatedBusinessObject;
}

First the business object is isolated. The code uses a Stub for the database (IPeopleContext). This limits the code to execute and the things that can go wrong. This also means checks done by the database (unique, references) are not performed.
Second the asserts on the Stubs are only to verify the code in the business object is well executed. The business object approves the record.

Integration test

The code for the integration test looks a lot like the unittest code. Again some variable definitions are left out for clarity.

IntegrationPeopleContext Context { get; set; }

public DoSomethingForTheBusinessIntegration() {
    System.Data.Entity.Database.SetInitializer(
       new DropCreateDatabaseAlways<IntegrationPeopleContext>()
    ); 
    Context = new IntegrationPeopleContext();
    Context.Database.Initialize(true);
}

[Fact]
public void AddNewPerson_Creates_New_Person() {
    var business = CreateIsolatedBusinessObject();
    business.AddNewPerson(validName, validStreet, validNumber, validZipcode, validCity);            
    business.Context.Persons.First(p => p.Name.Equals(validName));
}

private DoSomethingForTheBusiness CreateIsolatedBusinessObject() {
    var isolatedBusinessObject = new DoSomethingForTheBusiness();
    isolatedBusinessObject.Context = Context;
    return isolatedBusinessObject;
}

During the setup (constructor) the DropCreateDatabaseAlways initializer is set and the Context is created. This is an inherited context that could have some extra Testing methods. The Context created in the beginning is used in all tests in the class to some save time.
The assert in the test is replaced by a Linq statement. This queries the database for the created person. If it doesn’t exists there will be an exception and a failed test.

Conclusion

The code differences between unittests and integration tests can be small, but remember when to use which. Can you see the big difference in the screenshot of the Test Explorer below?

integration.vs.unittest.time

I’ve create a sample project. Download it here.

Posted in Development | Tagged , , , , , , | Leave a comment

Week roundup

Last week recap an links:

Image courtesy of kanate / FreeDigitalPhotos.net

Image courtesy of kanate / FreeDigitalPhotos.net

What are your best reads this week? Leave them in the comments below.

Posted in Uncategorized | Tagged , , | Leave a comment

Week roundup

Here are the best articles I’ve read/seen last week:

Image courtesy of kanate / FreeDigitalPhotos.net

Image courtesy of kanate / FreeDigitalPhotos.net

What are your best reads this week? Leave them in the comments below.

Posted in Uncategorized | Tagged , , , , , , , | Leave a comment