Download presentation
Presentation is loading. Please wait.
Published byAlicia McBride Modified over 9 years ago
1
UNIT TESTING FOR SQL Prepared for SUGSA CodeLabs Alain King Paul Johnson
2
Why? Simply put, we want quality! Unit Testing for SQL 2
3
How KRS is committed to Behaviour Driven Development (BDD), i.e. using stories and scenarios to drive development. With most of the newer technologies, these scenarios turn into unit tests, either in MSTest, Nunit, Junit, and others Unit Testing for SQL 3
4
…But… We also have big, complex legacy systems that have served us well for many years… …and these are mostly written using MS SQL Server stored procedures… …and yet we still demand quality, robust, elegant solutions… Unit Testing for SQL 4
5
…And… Clients have invested in high-end servers to host the database so we want to harness that power for large processing tasks (like month end processes)… … and there are a number of functions that happen through SQL code in the BI environment (like the ETL process) … Unit Testing for SQL 5
6
Now what? How do you safely add new database functionality? How do you safely refactor existing stored procedures/functions? …without breaking the existing system… Unit Testing for SQL 6
7
Introducing tSQLt tSQLt is a database unit testing framework for Microsoft SQL Server. tSQLt is compatible with SQL Server 2005 (service pack 2 required) and above on all editions. tSQLt allows you to implement unit tests in T- SQL. This is important as you do not have to switch between various tools to create your code and your unit tests. Unit Testing for SQL 7
8
tSQLt Features Tests are automatically run within transactions – this keeps tests independent and reduces any cleanup work you need Tests can be grouped together within a schema – allowing you to organize your tests and use common setup methods Output can be generated in plain text or XML – making it easier to integrate with a continuous integration tool Provides the ability to fake tables and views, and to create stored procedure spies – allowing you to isolate the code which you are testing Unit Testing for SQL 8
9
Examples Lets look at some sample code Write a test for a new stored proc Unit Testing for SQL 9
10
Examples begin tran select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Lee Duffy declare @BusinessEntityID int, @MiddleName varchar(50) select @BusinessEntityID = 2, @MiddleName = 'Leigh' update Person.Person set MiddleName = @MiddleName where BusinessEntityID = @BusinessEntityID select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Leigh Duffy rollback transaction select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Lee Duffy Unit Testing for SQL 10
11
Examples select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Lee Duffy begin tran declare @BusinessEntityID int, @MiddleName varchar(50) select @BusinessEntityID = 2, @MiddleName = 'Leigh' exec Person.uspUpdatePersonInfo @BusinessEntityID = @BusinessEntityID, @MiddleName = @MiddleName select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Leigh Duffy rollback transaction -- check that data is back to original select * from Person.Person where BusinessEntityID = 2 BusinessEntityID PersonType NameStyle Title FirstName MiddleName LastName 2 EM 0 NULL Terri Lee Duffy Unit Testing for SQL 11
12
Examples exec tSQLt.NewTestClass 'TestPerson' go drop proc TestPerson.[test Person middle name updated correctly] go create proc TestPerson.[test Person middle name updated correctly] as begin declare @BusinessEntityID int, @MiddleName varchar(50) select @BusinessEntityID = 2, @MiddleName = 'Leigh' -- When I update the MiddletName declare @retval int exec @retval = Person.uspUpdatePersonInfo @BusinessEntityID = @BusinessEntityID, @MiddleName = @MiddleName declare @ActualMiddleName varchar(50) select @ActualMiddleName = middlename from Person.Person where BusinessEntityID = @BusinessEntityID exec tSQLt.AssertEqualsString @MiddleName, 'broken' end exec tSQLt.RunAll Unit Testing for SQL 12
13
Examples exec tSQLt.RunAll [TestPerson].[test Person middle name updated correctly] failed: Expected: but was: +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Result | +--+--------------------------------------------------------+-------+ |1 |[TestPerson].[test Person middle name updated correctly]|Failure| ----------------------------------------------------------------------------- Msg 50000, Level 16, State 10, Line 1 Test Case Summary: 1 test case(s) executed, 0 succeeded, 1 failed, 0 errored. ----------------------------------------------------------------------------- Unit Testing for SQL 13
14
Examples Write a test for a new stored proc So what did I do wrong? Test First Unit Testing for SQL 14
15
Examples Scenario Given Person with ID 2 and Middle Name of Lee When I update the Middle Name to be Leigh Then the Middle Name for Person with ID 2 should be Leigh Unit Testing for SQL 15
16
Examples Write a test for a new stored proc Lets have a look at some code Unit Testing for SQL 16
17
Examples Write a test to compare 2 result sets Upgrading legacy systems to be 2008 / 2012 compliant Replacing complex queries with CTE’s to be easier to maintain In both cases, you are making changes to code and the expect result should be same Unit Testing for SQL 17
18
Examples Write a test to compare 2 result sets We can check this by writing a test to output the results from the original code into one table and the results of the modified code into another table and comparing them. But we don’t just want to compare for one set of inputs Unit Testing for SQL 18
19
Examples Write a test to compare 2 result sets JUnit and NUnit have TestCase functionality that allows one to run the same test with just supplying inputs and expected results as parameters. Unit Testing for SQL 19
20
Examples EXEC tSQLt.NewTestClass 'test_BillingReports'; GO /* ----------------------------------------------------------------------------- */ create procedure test_BillingReports.[test periodbilling (@periodno 201101).] as begin exec test_BillingReports.periodbilling_sub 201101 end; /* ----------------------------------------------------------------------------- */ create procedure test_BillingReports.[test periodbilling (@periodno 201201).] as begin exec test_BillingReports.periodbilling_sub 201201 end; /* ----------------------------------------------------------------------------- */ create procedure test_BillingReports.[test periodbilling (@periodno 201202).] as begin exec test_BillingReports.periodbilling_sub 201202 end; Unit Testing for SQL 20
21
Examples create procedure test_BillingReports.periodbilling_sub(@periodno int) as begin if object_id('actual') is not null drop table actual; if object_id('expected') is not null drop table expected; ------Assertion create table actual ( columns ) create table expected ( columns ) --OtherDatabase has the original version of the sproc insert expected ( columns ) exec OtherDatabase..periodbilling @periodno = @periodno insert actual ( columns ) exec periodbilling @periodno = @periodno exec tSQLt.assertEqualsTable 'expected', 'actual'; end; go EXEC tSQLt.run 'test_BillingReports'; Unit Testing for SQL 21
22
Examples Write a test to compare 2 result sets Lets take a look at some more code Unit Testing for SQL 22
23
Examples Write a test for an existing stored procedure This can be used for DDT – Defect Driven Testing or for enhancing existing functionality. Lets look at a test for an existing procedure in AdventureWorks called uspGetEmployeeManagers Unit Testing for SQL 23
24
Exercises Download from tsqlt.org exec tSQLt.NewTestClass 'TestPerson' Go create proc TestPerson.[test UpdatePersonMiddleName] as exec tSQLt.AssertEqualsString @MiddleName, @ActualMiddleName end exec tSQLt.RunAll Unit Testing for SQL 24
25
Exercises Write a test for a new stored procedure to check if an email address already exists in the database Unit Testing for SQL 25
26
Exercises Write a test for a new stored procedure to update available leave hours for an employee Unit Testing for SQL 26
27
Exercises We want to make changes to an existing stored procedure, write a test for uspGetBillOfMaterials to ensure that any changes you make do not have a negative impact on existing functionality. Unit Testing for SQL 27
28
28 Questions? www.krs.co.za (021) 681 2900 Alain King: alain.king@krs.co.zaalain.king@krs.co.za Paul Johnson: paul.johnson@krs.co.zapaul.johnson@krs.co.za Unit Testing for SQL
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.