An Introduction to Database Unit Testing with tSQLt
Last week I was looking through the Recently Published Courses list on Pluralsight and noticed one on Database Unit Testing (check it out). Given that it was quiet at work as not everyone was back from holidays I thought it would be a good time to look into it.
What is tSQLt?
tSQLt (website) is a testing framework for SQL Server, that basically means it provides (almost) everything you need to write tests against your database.
All the tests are written in T-SQL so that means that anyone working with SQL Server can write them and they are executed by a stored procedure. This means you stay working in SQL Server Management Studio with no need to context switch to another tool to write or execute your tests.
What tSQLt provides
tSQLt is a very rich testing framework and provides the following features:
- Isolation and setup functionality
- Assertions
- Expectations (for exceptions)
Anatomy of a Unit Test (The Three A’s)
In case you aren’t familiar with unit testing theory then the three A’s are a very simple way of thinking about how to write easily understood tests.
The three A’s are Arrange, Act, Assert.
Arrange: This is where any setup for running the test is done, including mocking objects if necessary.
Act: This is where the piece of functionality we are testing is executed (this is often referred to the system under test).
Assert: This is where the result from the Act stage is compared to the expectation (i.e. did the test do what we were expecting it to do)
Example tSQLt Unit Test
Time for an example.
Take the following two tables:
|
|
and the following stored procedure
|
|
To test that an entry into the audit_log table is made after a user has been created we can write the following stored procedure to act as our tSQLt unit test
|
|
Let’s dissect this piece by piece. In the Assemble stage, we set our expectation, which will be used in the Assertion section
|
|
Next is setting up the database, FakeTable is a tSQLt function which under the hoods makes a fresh copy of the table, removing all constraints, triggers, identities etc and then renames the existing one to a temporary name (this is then renamed back after the test has finished).
This allows the test to run in isolation.
|
|
In the Act stage the stored procedure that is being tested is executed.
|
|
Then from the audit_log table we set the actual result, which will then be compared to the excepted value
|
|
Finally in the Assert stage we use the tSQLt.AssertEqualsString stored procedure to check if the actual result matches the expected value
|
|
And that’s all there is to writing a simple unit test.
tSQLt likes you to group all the tests that relate to one database object into it’s own schema as this makes it easier to find all related tests in the object explorer.
tSQLt provides a stored procedure that can be used to create a new schema (test class)
|
|
tSQLt also provides a way to execute only unit test that belong to the same test class (schema), to execute all the stp_create_new_person tests
|
|
Wrap Up
As you can see, using tSQLt makes writing unit tests very easy. This should mean that you no longer have an excuse to not write them!
In my next post I’m going to cover off the issue of source control when using SQL Server Data Tools and the SQL Server project type.
Some Useful Resources
In this post I have only just scratched the surface of what can be achieved with tSQLt, I came across a number of useful resources that helped me to apply tSQLt:
- Unit Testing T-SQL Code with tSQLt - Pluralsight Course
- David Green’s blog - he is the author of the above Pluralsight course and has written a fair bit about tSQLt
- tSQLt.org - the official website has lots of useful information
- Greg Lucas has also written a lot about tSQLt on his blog - I found his article on cross database unit testing particularly helpful
🍪 I use Disqus for comments
Because Disqus requires cookies this site doesn't automatically load comments.
I don't mind about cookies - Show me the comments from now on (and set a cookie to remember my preference)