Database Unit Testing Fundamentals

Slides:



Advertisements
Similar presentations
A Brief Introduction to Test- Driven Development Shawn M. Jones.
Advertisements

#sqlsatPordenone #sqlsat367 February 28, 2015 Testing your databases Alessandro
Database testing Prepared by Saurabh sinha. Database testing mainly focus on: Data integrity test Data integrity test Stored procedures test Stored procedures.
@benday #vslive Automated Build, Test & Deploy with TFS, ASP.NET, and SQL Server Benjamin
UNIT TESTING FOR SQL Prepared for SUGSA CodeLabs Alain King Paul Johnson.
LiveCycle Data Services Introduction Part 2. Part 2? This is the second in our series on LiveCycle Data Services. If you missed our first presentation,
Views Lesson 7.
Data Driven Designs 99% of enterprise applications operate on database data or at least interface databases. Most common DBMS are Microsoft SQL Server,
1 Intro stored procedures Declaring parameters Using in a sproc Intro to transactions Concurrency control & recovery States of transactions Desirable.
Copyright 2015 Varigence, Inc. Unit and Integration Testing in SSIS A New Approach Scott @varigence.
Automated Build and Test
Core ELN Training: Office Web Apps (OWA)
Project Management: Messages
You Inherited a Database Now What?
Visual Studio Database Tools (aka SQL Server Data Tools)
Dynamic SQL Writing Efficient Queries on the Fly
Version Control with Subversion
Project Center Use Cases Revision 2
Project Center Use Cases
Making Your List and Checking It Twice
Introduction to unit and integration testing with tSQLt
Outsourcing Database Administration
Project Center Use Cases
Database Unit Testing Fundamentals
DBA and IT Professional for ~9 years. Currently I am a Data Architect
Dynamic SQL: Writing Efficient Queries on the Fly
Process Creation Processes get created (and destroyed) all the time in a typical computer Some by explicit user command Some by invocation from other running.
Cisco Data Virtualization
Reviewing Documents Guided Lesson.
Software Quality Assurance
Project Center Use Cases Revision 3
Dynamic SQL Writing Efficient Queries on the Fly
Error Handling Summary of the next few pages: Error Handling Cursors.
Project Center Use Cases Revision 3
Skill Based Assessment - Entity Framework -
Testing Database Code with tSQLt
Unit testing C# classes
DevOps Database Administration
SQL Server May Let You Do It, But it Doesn’t Mean You Should
Microsoft Word Reviewing Documents.
Continuous Integration For Databases
DHCP, DNS, Client Connection, Assignment 1 1.3
Principles of report writing
Populating a Data Warehouse
Testing in PowerShell Powered by Pester NATHAN ZIEHNERT 5/25/2018.
DevOps Database Administration
James Blankenship March , 2018
5 WAYS TO BYPASS *OR ENSURE* SQL SERVER SECURITY MATT MARTIN
Prove to your boss your database is sound - Unit Testing with tSQLt
Intro to Unit Testing with tSQLt
Teaching slides Chapter 8.
Populating a Data Warehouse
Visual Studio Database Tools (aka SQL Server Data Tools)
Dynamic SQL: Writing Efficient Queries on the Fly
Using JDeveloper.
Computer Science Testing.
DBA for ~4+years, IT Professional for 7.5 years.
Intermediate Security Topics in SQL SERver
CSE 303 Concepts and Tools for Software Development
Outsourcing Database Administration
Your code is not just…your code
You Inherited a Database Now What?
Summit Nashville /3/2019 1:48 AM
Easy-Speak How easy is it?
Security Principles and Policies CS 236 On-Line MS Program Networks and Systems Security Peter Reiher.
Jamie Cool Program Manager Microsoft
Vendor Software Lessons From Consulting Vendor Software.
Your code is not just…your code
Samir Behara, Senior Developer, EBSCO
Advanced Tips and Tricks
Presentation transcript:

Database Unit Testing Fundamentals Kevin G. Boles TheSQLGuru@Gmail.com Did a couple of SQL Saturdays last year Speak at various conferences User Group

Who am I?? Kevin G. Boles SQL Server Consultant “The Wolfe” for the Relational Engine Indicium Resources, Inc. AIM/Twitter: TheSQLGuru Gtalk/GMail: TheSQLGuru@gmail.com MCITP, MCT, MVP 2007-2012, yada-yada

What do I do? World-class Better-than-average relational engine expert  ~45,000 man-hours invested in SQL Server Absolutely LOVE doing targeted performance analysis and tuning work VERY good at making others better at interacting with SQL Server Couldn’t SSAS my way out of a paper bag … with both ends open! 

Agenda What is “Unit Testing” What does it mean to “Unit Test” a database? How to do it in SSMS Manually coding tSQLt Framework SQL Test

What is “Unit Testing” Code that exercises a specific portion of your codebase in a particular context. Returns a simple pass/fail based on an expected known result. Inspect the results to know how things stand and possibly act on it. Does not test more than necessary May be more than one test for each piece of code Act = Continuous Integration

Goals Catch mistakes as early in the process as possible. Provide repeatable, regression-checking tests that A) validate code performs correctly B) are EXTREMELY important during refactors! One goal of unit testing is to catch mistakes as early in the process as possible. less expensive I’m sure someone here can find the stat on how much less expensive, but it’s considerable

Goals Keep your units of code as small and testable as possible. Tighter, more maintainable code Ensure that you have a good idea what the code is supposed to do, perhaps even before you write it. (née Test Driven Development) Another goal is to keep your units of code as small and testable as possible. (Side note: One of the premier reasons you'll here about why there's suddenly a movement towards developing web apps with 'MVC' style is that MVC exposes the functions in a testable way).  

Goals They give you confidence that your code works as you expect it to work. [look at audience] As a developer I’m a little jealous of DBAs because it seems as if they’re well paid and their job is easy as long as they don’t break things too badly. I can refactor my code without worrying if I'll break it. Well that's not true: I will break it, but at least now I'll know I broke it without relying on the most usual kind of test: "User Testing".  

Goals (for Database folks) Can ensure CONFORMITY with Standards SQL Cop coming later Eg Naming conventions A “meta” test

What to Test? Often not feasible to test everything You’d like to hit ~75% coverage Every method, possibly multiple tests Normal Conditions Edge Conditions Null / Empty parameters Out of bound conditions Really not possible to test every condition, but it's a good practice to test every method and send it as many edge conditions as you can think of. For example I wrote a routine to authenticate users. Simple function: Take a username and a password and returns whether it's valid. I wrote multiple unit tests for that one method. One to confirm that a valid username (in any case)/login could actually login One to confirm that an invalid username/password could not get in One to verify that an empty/null username but valid password would not work One to verify that an valid username but empty/null password would not work One to verify whether a subset of a username along with a valid password would not work (eg. If the user name was 'Administrator', did 'Admin' work?) You wouldn't want to find out that works when your boss calls you up and tells you a customer reported that he got in with that.

Problems with Unit Testing More up-front time / work Less instant gratification Pays off on the back end Hard to justify to upper management “Squishy” Can’t prove it worked TDD

Unit Testing is not…. Integration Testing in which we make sure our individual modules work well together. Does the 'Delete' button on the U/I actually invoke the 'Delete' method in the ORM properly and handle the result? Does calling the 'Delete' method in the ORM actually remove a record from the database?

Unit Testing is not…. System Testing, when you deliver your app to the testers and they check it all out to make sure it meets the requirements. Eg. load testing compatibility testing accessibility testing and many more. Testers: (let's be honest, the users, at which point it might be called Acceptance Testing) Requirements: (you've got the requirements documented, right?)

Unit Testing is… Peace of Mind Ask how many are unit testing now.

What does this have to do with DATABASES? Well, there IS code in and hitting databases Stored procedures Functions Constraints Views Triggers fired at your database by your favorite ORM This is a database conference after all. Let’s take a look at a very simple example…

Example #1 Write a unit test to ensure scalar function returns what we think it should. Also, make sure it doesn’t return what we don’t think it should. Test edge cases and boundary conditions!! Exercise all regions of code (separate tests) Demo Example Unit Test solution testStatus1.sql

Example #2 Write multiple unit tests for a function… Demo testStatusAll You may start to get the vague notion that managing these tests could get out of hand. Bear with me..

Example #3 How do we test tables? How compare data in them? Static and outputs from sprocs? How compare data in them? How compare schemas? How to test constraints (or NOT test them)? Embed in a TRANSACTION Try to add some bad data See if it threw an error End TRANSACTION Triggers? Testing constraints means throw some data into the table to make sure you can’t stick bad data in there. Be sure TRANSACTIONS are on – not a bad idea for all your tests.

Views Old way of testing Alter a view Compile? Run view Got data? Good to go! testTable.sql

Views How to test if a View’s data went bad? You’d have to have ‘saved’ a copy of your view data before you make changes. Make your changes Get your new view data Compare um…how do I do that? testTable.sql

Testing “Tabular Ouput”   OUTPUT A OUTPUT B ID FieldA FieldB 1 ABC 123 2 DEF 456 NULL 3 HIJ  789  4 KLM 101112 Suppose you set up a test that has this output. You can say this is exactly what I expect the output to look like and do a simple inner join from your Expected table to Actual table. But it isn’t that simple! You have to do the following: A = B (best handle NULLS!!), in A not in B, in B not in A What if column datatypes changed?!? INT, Identity (1,1) Numeric(18,0), Identity (1,1)

This is getting out of hand! We could write the unit tests in Visual Studio nUnit Sql Server Data Tools Requires a separate tool which we may not have. It'd be nice if there was a framework for writing unit tests that allowed us to remain within SQL Server Management Studio. SSDT - Hard to manage AND unless we commit these tests using Source Control, they’re not shared w/ everyone else

tSQLt Framework tSQLt is a database unit testing framework for Microsoft SQL Server. http://tsqlt.org/ Features: Test are run within transactions Tests are grouped within a schema Output can go to a file that a CI tool can use …and more

tSQLt Framework Installation Download zip (tSQLt.org) Add scripts to a project (optional) Comes w/ an example database… Because a database that is attached to an instance of SQL Server cannot be immediately trusted, the database is not allowed to access resources beyond the scope of the database until the database is explicitly marked trustworthy. ALTER AUTHORIZATION can be used to change the ownership of any entity that has an owner Let’s look at

Adding tSql to your database Prep your database ALTER AUTHORIZATION ON DATABASE TO sa (Maybe) SET TRUSTWORTHY ON Enable CLR on Server 2. Run tSqlt.class script on each database you want to generate tests in. This is why you don’t unit test a production database Let’s take a look at what tSqlt.class does to our database:

Redo our tests in tSQLt Create a test class: tSQLt.NewTestClass Creates a new schema with that classname Create a test: CREATE PROCEDURE Schema should be the new class name Prefix the sp name with ‘test’ Run the Test: tsqlt.Run <testName> tSQLt-1 EXEC tSQLt.NewTestClass 'AWTests';   -- Create a test within that Test Class (stored procedure, prefix the name with 'test' or it won't run ... alter procedure DAFUG.testStatus as begin DECLARE @status varchar(30) DECLARE @expected varchar(30) = 'In Process' SELECT @status = AdventureWorksLT2012.dbo.ufnGetSalesOrderStatusText(1) exec tSQLt.AssertEquals @Expected=@expected, @Actual=@status, @Message='Status 1 did not return "In Process"' end

Assertions AssertObjectExists AssertEmptyTable AssertEquals AssertNotEquals AssertLike AssertEqualsTable AssertResultSetsHaveSameMetaData http://tsqlt.org/user-guide/assertions/assertequals/ Equals works with any variant EqualsString works with VARCHAR(MAX) 

Handling Dependencies ApplyConstraint – Add constraint back to Fake Table by name. CHECK, single-column FOREIGN KEY only. FakeFunction – Remove complex code. Can replace with your own code. FakeTable – Basic copy of table. SpyProcedure – Logs execution of sproc including parameter values. http://tsqlt.org/user-guide/assertions/assertequals/ Equals works with any variant EqualsString works with VARCHAR(MAX) 

Faking It FakeTable No constraints ALL NULLable columns Can keep Identity definition No triggers (can add) Temp tables cannot be faked tSQLt.FakeTable [@TableName = ] 'table name‘ , [[@Identity = ] 'preserve identity'] , [[@ComputedColumns = ] 'preserve computed columns'] , [[@Defaults = ] 'preserve default constraints']

Handling Known Errors ExpectException – Good for cases like catching a PK violation on UPSERT action tSQLt.ExpectException [ [@ExpectedMessage= ] 'expected error message'] [, [@ExpectedSeverity= ] 'expected error severity'] [, [@ExpectedState= ] 'expected error state'] [, [@Message= ] 'supplemental fail message'] [, [@ExpectedMessagePattern= ] 'expected error message pattern'] [, [@ExpectedErrorNumber= ] 'expected error number'] http://tsqlt.org/user-guide/assertions/assertequals/ Equals works with any variant EqualsString works with VARCHAR(MAX) 

Running Tests One test per stored procedure tsqlt.Run <testName> tsqlt.RunTestClass <className> tsqlt.RunAll

Bonus Features! Sproc: <className>.Setup Last Execution Tracking Is executed at the start of every test execution for that class. Great for D.R.Y. stuff Create routinely accessed objects/fakes/spys Settings/object validation? Populating lookups? Last Execution Tracking tSQLt stores last test executed for each session (by SPID/LoginTime) EXEC tSQLt.Run (no parameter) will exec last test Anyone know what DRY stands for?

Tips Filter the Stored Procedures to just see Tests Assign a hotkey to run tests (Tools, Options, Environment, Keyboard, EXEC tSQLt.RunAll Create a template for creating a test Keep an eye on tlog size!! LOTS of stuff happens behind the scenes. Be especially aware because my clients NEVER seem to properly setup/maintain their DEV/TEST SQL Server environments! Heck, I’m lucky if they set up PRODUCTION servers at all!! 

Demos

Not Enough? No Pretty Color Coding? Visual cues to what/how many tests failed? I can't just doubleclick on my failed test to edit it?!?

SQL Test RedGate Not Free $369 Standalone $1895 in SQL Developer Bundle SQL Source Control Continuous Integration LOTS of useful tools!! Also SQL Toolbelt, which costs over $2500 but gives you over 16 tools http://www.red-gate.com/products/sql-development/sql-toolbelt/

SQL Test Provides … A nice GUI Color Coding SQL Cop Tests Demo … (actually run Master Sproc Stub) Also SQL Toolbelt, which costs over $2500 but gives you over 16 tools http://www.red-gate.com/products/sql-development/sql-toolbelt/

SQL Test Auto-Setup Demo…

Continuous Integration Automatically run Unit Tests On a schedule When code is checked in Reject if fails Proceed with other tests if succeeds Compile the app Distribute like the free and popular CruiseControl or TeamCity Never have errors again!

Conclusion Unit Testing is for Database People Discipline you to write testable code Reward you with easy to maintain code Fewer errors – ESPECIALLY on refactors!! Save money Save time Conform to standards

Q&A / Comments Contact Information: Kevin G. Boles TheSQLGuru@Gmail.com @TheSQLGuru LinkedIn: TheSQLGuru Think metadata Does every foreign key have an index, for example Are there any queries with SELECT *

Microsoft Engineering Excellence Resources tSQLt.org Website Unit Testing Database with tSQLt Ten Things I Wish I'd Known 48 SQL Cop Tests (Zip File) Using SQL Test in Continuous Integration How to write good unit tests Are Unit Tests overused? Test Driven Development Special thanks to Eric Selje for the deck and samples Microsoft Confidential