SlideShare une entreprise Scribd logo
1  sur  138
Télécharger pour lire hors ligne
Hey, You Got
Your TDD
In My SQL DB!
Jeff McKenzie
@jeffreymckenzie
mail@mcknz.com
Good morning everyone –
Thanks for being here to learn
About SQL Server testing using TDD
My name is Jeff McKenzie, and before we get started
I'd like to tell you a little bit about myself –
I like puppies, long walks on the beach…
And I'm also a Principal Consultant
At Cardinal Solutions – a little bit about Cardinal...
Cloud Mobile
Data Web
We are an IT services firm
With approximately 500 fulltime consultants
In 7 different locations across the eastern region,
Including a branch in Columbus –
And we are hiring, so talk to me after
Or get in touch if you are interested --
We have a strong focus in cloud technologies,
As well as custom application development,
DevOps, IoT, AR/VR, and data analytics.
@jeffreymckenzie
TDD
Today we are going to learn more about TDD –
How many of you have heard of TDD,
know what it means, or tried it? [hands]
How many use TDD
on a fairly regular basis? [hands]
@jeffreymckenzie
How to apply
TDD
to SQL Server
So My goal for today is to show you
How to use TDD practices
Specifically in SQL Server,
Whether that's standalone SQL,
Or the data layer in a larger application. ***
@jeffreymckenzie
TDD – the what
1
To realize that goal, we are first going to
Define TDD, explain it, qualify it,
To make sure we are all on the same page
When we talk about what TDD is and is not. ***
@jeffreymckenzie
TDD – the why
2
A lot of us have heard about the practice of TDD
But sometimes the actual reasons for doing it
get lost or obscured.
So we will examine the benefits of TDD. ***
@jeffreymckenzie
TDD – the how
3
Finally we will take a look at a specific example
Of a real-life production scenario
And demonstrate how to use TDD
against SQL Server. ***
@jeffreymckenzie
I Don't Know.
So one thing I'm not planning to do in this session
Is try to convince you how often and how thoroughly
you apply TDD, because I don't really have an answer.
This is one of those software development topics that
Tend to start religious wars, like, you know,
Other enthralling topics like spaces vs tabs.
On one side you have the TDD zealots… ***
=========
https://upload.wikimedia.org/wikipedia/commons/7/7b/Jan_Steen_-
_Argument_over_a_Card_Game_-_WGA21735.jpg
Jan Steen [Public domain], via Wikimedia Commons
@jeffreymckenzie
All
the
Way
Down
Who say even your unit tests should have unit tests.
On the other side are people who say TDD
Is garbage, is considered harmful, ***
=========
https://upload.wikimedia.org/wikipedia/commons/4/47/River_terrapin.jpg
By Pelf at en.wikipedia [Public domain], via Wikimedia Commons
@jeffreymckenzie
Burn It With Fire.
Promotes bad design, and should be
completely done away with.
Those are ideas and arguments you can explore
on your own.
All I can say is that I've used it, ***
=========
https://upload.wikimedia.org/wikipedia/commons/c/cd/Rammsterin_Fla
methrower.jpg
By Kreepin Deth (Own work) [CC BY-SA 4.0
(https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia
Commons
@jeffreymckenzie
Works on My Box.
Found some benefits with it, and generally have a feel
For when it's valuable and when it's not.
But all those concerns are offtopic for today –
We will be focusing on the what, why, and how. ***
=========
https://upload.wikimedia.org/wikipedia/commons/f/f5/Computer_MC80.3
x_CM5214.JPG
By LutzBruno (Own work) [CC BY 4.0
(http://creativecommons.org/licenses/by/4.0)], via Wikimedia Commons
@jeffreymckenzie
Who
Are
You
First, I'd like to get an idea of your technical background:
How many would consider yourselves
…application developers?
…DBAs or primarily SQL developers?
…QA or testing?
Any roles I missed? ***
=========
https://upload.wikimedia.org/wikipedia/commons/4/42/Townshend_sma
shing_guitar.jpg
By Heinrich Klaffs [CC BY-SA 2.0
(https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
Test-driven development was popularized in software development
In the late 1990s as part of the Extreme Programming project,
Which emerged as a set of technical practices designed to work with
Agile Software Development.
The specific technique of TDD was detailed in Kent Beck's
2002 book Test-Driven Development by Example.
=========
https://www.amazon.com/Test-Driven-Development-Kent-
Beck/dp/0321146530
https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_
Workshop_Mapping_XP.jpg
By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA
2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
The original description of TDD was in
an ancient book about programming. It
said you take the input tape, manually
type in the output tape you expect, then
program until the actual output tape
matches the expected output.
– Kent Beck
In that book however, Beck claims merely to have
re-discovered the technique. He cites what he calls
an ancient book on programming
(ancient in software development terms, which means
late sixties/Early seventies), but references have been
Discovered going back to the 50s. ***
=========
https://www.amazon.com/Test-Driven-Development-Kent-
Beck/dp/0321146530
https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_
Workshop_Mapping_XP.jpg
By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA
2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
The original description of TDD was in
an ancient book about programming. It
said you take the input tape, manually
type in the output tape you expect, then
program until the actual output tape
matches the expected output.
– Kent Beck
Beck describes a process where the expected output
of the program was manually created,
and the programmer would work until the
actual output matched the expected output,
Which is pretty much what TDD is all about. ***
=========
https://www.amazon.com/Test-Driven-Development-Kent-
Beck/dp/0321146530
https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_
Workshop_Mapping_XP.jpg
By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA
2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
TDD – the what
1
We call this practice Test-Driven
Because tests are written first, before any code.
With a traditional approach, tests are created after,
To verify what's already been coded. ***
@jeffreymckenzie
Don't know about you, but I find it helpful
to have a visual of what I'm trying to learn.
Here's a graphical depiction of the TDD process –
Which is really two separate cycles:
The test-driven development cycle,
And the refactoring cycle.
There are 3 steps for the first cycle:
Make the test, make it fail, and make it work. ***
=========
https://upload.wikimedia.org/wikipedia/commons/0/0b/TDD_Global_Life
cycle.png
By Xarawn (Own work) [CC BY-SA 4.0
(https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia
Commons
@jeffreymckenzie
Make the Test.
First step is probably the hardest barrier to get over
when learning and using TDD, and that is to create
the test first, before writing any code.
When we get requirements, we want to make
something happen, And writing a test
doesn't really feel like you're doing anything.
I'll add another point about writing a test, ***
=========
https://upload.wikimedia.org/wikipedia/commons/b/b2/V08383P339.jpg
By Calspan Corporation, National Highway Traffic Safety Administration
[Public domain], via Wikimedia Commons
@jeffreymckenzie
Make it simple.
Which is to make it simple. A test shouldn't try
to do too much.
It should be relatively easy to create and execute.
The tests we are talking about here are unit tests.
There's a definition for unit test I like,
Which says it's
One specific requirement for
One specific method. ***
=========
Picture of easy button, by me.
@jeffreymckenzie
…a test that tests
ONE specific requirement for
ONE specific method.
A Unit Test is…
– James Bender
This is from James Bender – just google James Bender
And TDD, and you'll find a lot of great info.
This definition really shows the difference between
a unit test and any higher level test, such as
integration or end-to-end testing.
These higher-level tests are going to hit
multiple methods, which makes it harder
To verify individual requirements.
A unit test should also be…. ***
@jeffreymckenzie
…fast
…isolated
…repeatable
A Unit Test is…
Fast.
Ideally you want to run all of your tests
as you are working,
To know when you are done
or have broken something.
If your tests are simple,
they are more likely to be fast. ***
@jeffreymckenzie
…fast
…isolated
…repeatable
A Unit Test is…
Your tests will also be faster
If they are isolated – meaning you want to reduce
Dependencies on other classes or methods.
Testing methods in isolation also makes sure
That you're targeting the right spot –
If your test fails, you know
Exactly where to look. ***
@jeffreymckenzie
…fast
…isolated
…repeatable
A Unit Test is…
Finally a test should be repeatable –
So if the code being tested has not changed,
The test result should be the same every time.
Any setup or teardown activity
should be handled within the test itself.
There should be no manual steps required
In between test runs.
This again helps the test to run quickly. ***
@jeffreymckenzie
Let's try out a quick concrete example.
So we have our easy button, and let's say
We want to create a computer model of it.
Our first requirement is…
Create an easy button,
=========
Picture of easy button, by me.
@jeffreymckenzie
Create an Easy Button…
with a Click() method…
returning “That was easy.”
With a click method,
Returning “That was easy.”
***
@jeffreymckenzie
public void Test_EasyButton_Click() {
//Arrange
//Act
//Assert
}
Here's the start of our test – we'll call it
Test Easy Button Click – and we're going to use
What we call the triple A pattern:
Arrange, Act, Assert.
Let's set up the arrange part –
This is where you do all of the setup
Just prior to code execution.
@jeffreymckenzie
public void Test_EasyButton_Click() {
//Arrange
var button = new EasyButton.Button();
String expected = "That was easy.";
//Act
//Assert
}
This is C# but this would be similar to a test
In a strongly typed language.
Here we create an instance of the EasyButton,
And also a variable called expected,
Which holds the value of the output
we expect. ***
@jeffreymckenzie
public void Test_EasyButton_Click() {
//Arrange
var button = new EasyButton.Button();
String expected = "That was easy.";
//Act
String actual = button.Click();
//Assert
}
Next we have the Act section –
Here we do the actual code execution,
And assign the output of the click method
To a variable called actual. ***
@jeffreymckenzie
public void Test_EasyButton_Click() {
//Arrange
var button = new EasyButton.Button();
String expected = "That was easy.";
//Act
String actual = button.Click();
//Assert
Assert.AreEqual(actual, expected);
}
Lastly we have our assert section.
An assertion is a verification
That our action executed the way we intended.
In this case, our assertion is that the actual output
of the click method is: That was Easy.
This is a pretty simple test –
We are testing just one thing. ***
@jeffreymckenzie
Make it fail.
After you've written your simple test,
You want to make sure it actually fails.
If you write a passing test by mistake,
Then you'll have no confidence that
Your code really does what it's supposed to.
Then, finally, write the code… ***
=========
https://upload.wikimedia.org/wikipedia/commons/5/54/Hydrogen_balloo
n_explosion.jpg
By Maxim Bilovitskiy (Own work) [CC BY-SA 4.0
(https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia
Commons
@jeffreymckenzie
public void Test_EasyButton_Click() {
//Arrange
var button = new EasyButton.Button();
String expected = "That was easy.";
//Act
String actual = button.Click();
//Assert
Assert.AreEqual(actual, expected);
}
So back to our test – is it going to pass?
No – why not?
Right, we haven't written the code yet,
There's no EasyButton.
Here's what I get when I attempt
To run the test … ***
@jeffreymckenzie
It doesn't even compile.
Tells me that EasyButton doesn't exist,
Which is good because
We haven't made it yet. ***
@jeffreymckenzie
Make it work.
So we need to make the test work.
The trick is to try to write as little code as possible.
The idea of TDD is to satisfy all requirements
With the least amount of work.
The less code there is, the fewer things
You have to go wrong.
So let's write the implementation. ***
=========
https://upload.wikimedia.org/wikipedia/commons/c/c4/Hillary_Clinton_%
2824007578223%29.jpgBy Gage Skidmore from Peoria, AZ, United
States of America (Hillary Clinton) [CC BY-SA 2.0
(https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
public class Button {
public String Click() {
return "That was easy.";
}
}
Pretty simple –
We just create the class, Create the method,
And return the output. ***
@jeffreymckenzie
So we re-run our test and we have success.
We coded only what we needed to pass the test.
If we code ahead and try to anticipate
Additional requirements or functionality,
we run the risk of coding too much, or adding code
We don't need. ***
@jeffreymckenzie
Now we get to refactoring, which is simply
rewriting code to make it better.
After you have a few passing tests,
You'll want to go back and make improvements.
The nice thing about having TDD is you now
Have a built-in test suite to verify that
All of your changes still meet the requirements.
If tests fail, you may need to fix code,
Or you may need to update tests to match
Your new design. ***
=========
https://upload.wikimedia.org/wikipedia/commons/0/0b/TDD_Global_Life
cycle.png
By Xarawn (Own work) [CC BY-SA 4.0
(https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia
Commons
@jeffreymckenzie
TDD – the why
2
Now that we have a general idea of what TDD is,
Let's examine why we might want want to use it –
What are the benefits it provides.
After all, there is extra work involved –
It simply takes more time to write a test
For every requirement, and to continually run
And update those tests.
It's like having a second code base. ***
@jeffreymckenzie
…quality
…design
…discipline
…documentation
Use TDD for…
The first benefit of TDD is that it improves code quality.
If you are diligent in your testing effort,
And have a unit test for the classes and methods
That make up each requirement, you will have baked in
Verification of your application's functionality.
Because you have been checking for correctness
As you go, the code is better, and has less defects.***
@jeffreymckenzie
…quality
…design
…discipline
…documentation
Use TDD for…
Another area TDD can assist is in the design
And organization of your code. Because you writing
The least possible code, and tests first, it forces you
To think in advance – as in our EasyButton example:
We had to think about the implementation we wanted
When writing the test.
@jeffreymckenzie
…quality
…design
…discipline
…documentation
Use TDD for…
TDD can also improve testing discipline.
I know from experience that it's difficult to write
All the tests you need when you do it after the code.
And often it just doesn't happen because you
Run out of time. If you write the test first,
You'll rarely be in a place where you have untested code.
@jeffreymckenzie
…quality
…design
…discipline
…documentation
Use TDD for…
If you are disciplined in writing tests,
Your test suites become in essence a form
Of documentation for your code –
Each test explains what a part of the application does.
Written documentation quickly gets out of date,
But if you have a passing test, you know the
Code is still used and working as intended.
But my number one reason for using TDD is
That it gives you confidence to make changes. ***
@jeffreymckenzie
…confidence to change
code details and design
– and at the same time –
retain existing functionality.
Use TDD for…
You are continually rerunning old tests, so you'll know
immediately if something's broken.
I think everyone's had an experience working with
a code base that people are afraid to touch.
Which means at release time, everyone in the company
Is staying late to click on buttons, hoping
That nothing got broken since the last deployment. ***
@jeffreymckenzie
What Have I Done.
You know, everyone lives in fear of changes to the application,
And the managers want to know exactly what changed
That caused this feature or that feature to break,
And why didn't we know that would happen.
So TDD can help prevent these types of problems. ***
=========
https://upload.wikimedia.org/wikipedia/commons/7/7e/US_Navy_03022
8-N-4953E-
001_Aviation_Ordnanceman_2nd_Class_Kyle_Marcinowski_conducts_
a_quality_assurance_check_on_a_GBU-
31_Joint_Direct_Attack_Munition_%28JDAM%29.jpg
By U.S. Navy photo by Photographer's Mate 3rd Class Danny Ewing Jr.
[Public domain], via Wikimedia Commons
@jeffreymckenzie
TDD – the how
3
So that brings us to the heart of today's session,
Which is how to bring the benefits of TDD
To your SQL Server database. This brings up the question
How do we, and how should we, test our data? ***
@jeffreymckenzie
How Do
We Test
Our Data?
What are some ways you approach data testing?
I think that sometimes when testing an application,
our first inclination is simply to skip data all together,
Because the database is a external dependency that
Slows down testing, and can cause unrelated issues.
@jeffreymckenzie
Isolation
Remember we talked about isolation as being
An important part of a unit test?
If we are writing our application,
It's often best practice to isolate our code
From the data because it's an outside dependency.
But that presents a problem -- we have database objects
As part of our code base, but not testing them
Along with the application. ***
@jeffreymckenzie
Manual
Queries
One common way is to manually query the database.
We write a query or stored proc, run it,
and verify its correctness. And that works to a degree,
but eventually you have the same problem –
as your data model changes,
How can you tell you're still getting proper data?
You have to go back and manually retest,
Which often you don't have time for.
Another method is to build in automation
Through integration tests. ***
@jeffreymckenzie
Automated
Integration
Tests
These kinds of tests are certainly a step up
From manual queries, and can be built in
As part of a continuous integration process
To make sure the application works when combined
With its persistence layer. One problem with this,
However, is that these tests are designed to test
The application itself, and the data only indirectly.
Could be that a integration test only succeeds
Coincidentally, and that the underlying SQL
Has unidentified problems. ***
@jeffreymckenzie
When Do
We Test
Our Data?
In addition to how we test, we need to ask
When we test data. We don't need to test
Everything. For example, in an application,
We probably don't need to test
That an object property has the value we assigned it.
We want to make sure we are testing functionality,
And not the underlying framework or language.
We probably don't need to test an insert statement.
We probably don't need to test our ORM. ***
@jeffreymckenzie
When Do
We Test
Our Data?
What is useful to test is complex behavior or logic.
Although stored procedures are kind of out of fashion,
They are still a great choice when doing intensive
Operations within multiple database objects.
Wouldn't it be nice if we could build in
The same kind of direct and continuous
Unit testing of our SQL, the way we do
For our application code?
Well, it just so happens that we can! ***
@jeffreymckenzie
There is a unit test framework for SQL Server
Called T SQL T, which allows you to take a TDD
Approach to writing SQL.
It's installed entirely within SQL server.
It's open source, with the source code freely
Available on GitHub. ***
@jeffreymckenzie
The TSQLT repository is on the tSQLt-org GitHub account,
And you can get it from their web site… ***
@jeffreymckenzie
On the download page at tSQLt.org
The whole framework clocks in zipped at 84K,
So that should pull down pretty fast… ***
@jeffreymckenzie
What we're going to walk through
Is a real world production feature I implemented
In SQL Server using the tSQLt framework.
In the interest of protecting client confidentiality,
however, I have changed almost everything
About the project, including the industry,
The client, and the product – all that remains
Is the business problem we need to solve.
So I'd like to introduce you to our client… ***
@jeffreymckenzie
Does anyone know this guy?
Ron was probably best known for being the director
Of the Parks and Rec department in Pawnee Indiana,
For 6 years. What's less well known, however, is that
after retiring from a long and illustrious career
as a civil servant, Ron Swanson decided to purchase
and run his favorite store… called… anyone? ***
=========
https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo
d_and_Stuff_2.png/revision/latest?cb=20120730155117
http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
@jeffreymckenzie
Food and Stuff. Does anyone remember this place?
Food and Stuff is located at 729 Glenmore Blvd
in Pawnee, Indiana. Ron buys all of his groceries there,
and describes it as: "a discount food outlet equidistant
from my home and my work". According to Mr. Swanson,
They have a broad and diverse catalog of items,
Including household paints…
=========
http://parksandrecreation.wikia.com/wiki/Food_and_Stuff
https://vignette.wikia.nocookie.net/parksandrecreation/images/1/15/Foo
d_and_Stuff.png/revision/latest?cb=20120730155051
@jeffreymckenzie
garden supplies…
=========
https://upload.wikimedia.org/wikipedia/commons/b/bd/EWM_paint_2007
.jpg
By Tom Murphy VII (Taken by uploader (user:brighterorange)) [Public
domain], via Wikimedia Commons
@jeffreymckenzie
Industrial tubing…
=========
https://upload.wikimedia.org/wikipedia/commons/d/d8/Shovel_leaning_a
gainst_a_wall.jpg
Santeri Viinamäki [CC BY-SA 4.0
(https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia
Commons
@jeffreymckenzie
buckets of different sizes…..
=========
https://upload.wikimedia.org/wikipedia/commons/6/65/Pvc_cevi.jpg
Mm.zaletel from sl [GFDL (http://www.gnu.org/copyleft/fdl.html)], via
Wikimedia Commons
@jeffreymckenzie
Fishtanks….
=========
https://upload.wikimedia.org/wikipedia/commons/a/a2/Bassines_de_tout
es_les_couleurs_march%C3%A9_%C3%A0_Hanoi.JPG
By Dinkum (Own work) [CC0], via Wikimedia Commons
@jeffreymckenzie
shelving units ….
=========
https://upload.wikimedia.org/wikipedia/commons/4/47/Okinawa_Aquariu
m.jpg
By Jordy Meow (Own work) [CC BY-SA 3.0
(https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia
Commons
@jeffreymckenzie
And lead-based paints.
=========
https://upload.wikimedia.org/wikipedia/commons/0/00/KAST_kast_desig
ned_by_Marcel_Douwe_Dekker_in_1992.jpg
By Marcel Douwe Dekker (Own work) [CC BY-SA 3.0
(https://creativecommons.org/licenses/by-sa/3.0) or GFDL
(http://www.gnu.org/copyleft/fdl.html)], via Wikimedia Commons
@jeffreymckenzie
And it's not only products –
They perform various services,
Such as engine repair…
=========
https://upload.wikimedia.org/wikipedia/commons/6/69/LeadPaint1.JPG
By Thester11 (Own work) [CC BY 3.0
(http://creativecommons.org/licenses/by/3.0)], via Wikimedia Commons
@jeffreymckenzie
Passport photos…
=========
https://upload.wikimedia.org/wikipedia/commons/d/d7/Under_the_Hood
_%289664838146%29.jpg
By Marines from Arlington, VA, United States (Under the Hood) [Public
domain], via Wikimedia Commons
@jeffreymckenzie
And catering
=========
https://upload.wikimedia.org/wikipedia/commons/4/4c/Miami_Passport_
Agency_Director_Dooley_and_Deputy_Director_Ward_Show_Secretary
_Kerry_a_New_Passport_in_Their_Manufacturing_Room_During_the_
Secretary%27s_Day_Trip_to_the_City_%2826406970916%29.jpg
By U.S. Department of State from United States [Public domain], via
Wikimedia Commons
@jeffreymckenzie
And catering.
=========
https://upload.wikimedia.org/wikipedia/commons/3/34/1956_-
_Americus_Hotel_Buffet.jpg
Unknown author [Public domain], via Wikimedia Commons
@jeffreymckenzie
So Ron's been doing pretty well, and business is strong.
He's got a point of sale system he's been using…
***
=========
https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo
d_and_Stuff_2.png/revision/latest?cb=20120730155117
http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
@jeffreymckenzie
Yeah, So no one ever accused Ron
of being a slave to technology.
He's also using this system to take customer orders,
track inventory, manage his books,
and all that good stuff.
But Ron has a few problems.
***
=========
https://upload.wikimedia.org/wikipedia/commons/1/19/Zenith_Z-
19_Terminal.jpg
By Jamie Cox from Melbourne, USA (Zenith Z-19 Terminal Uploaded
by Mewtu) [CC BY 2.0 (http://creativecommons.org/licenses/by/2.0)],
via Wikimedia Commons
@jeffreymckenzie
First, he's got about 12,000,000 new customers in his database
over the last 12 months, but the entire city of Pawnee
has only about 80,000 people.
=========
http://1.bp.blogspot.com/-
j9CbeOiNMLY/Vdr4b55bzcI/AAAAAAAAwOM/A_fjFcEBSJo/s1600/Paw
nee.jpg
https://swimnova.com/map-of-pawnee-indiana.html
@jeffreymckenzie
When he runs customer reports, he keeps seeing
the same names appear many times.
The point of sale system also allows Ron to mail
promotional materials to his customers, to remind
them when there are sales, or when new items
get in stock, like almond butter….
=========
https://upload.wikimedia.org/wikipedia/commons/3/3a/All_work_and_no
_play_makes_Jack_a_dull_boy_%28The_Shining%29_%28795773850
0%29.jpg
By Marcel Oosterwijk from Amsterdam, The Netherlands [CC BY-SA
2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia
Commons
@jeffreymckenzie
Or cattle prods….
=========
https://upload.wikimedia.org/wikipedia/commons/c/cf/Barney_butter_Jar
s.jpg
By Venomarv (Own work) [CC BY 1.0
(http://creativecommons.org/licenses/by/1.0)], via Wikimedia Commons
@jeffreymckenzie
But he's gotten complaints that his customers
are getting 4 or five copies of his newsletter,
and he's spending a fortune on postage.
So what is Ron's problem?
What's the problem with his system,
and specifically his database? ***
=========
https://upload.wikimedia.org/wikipedia/commons/d/d3/Electric_cattle_pr
od.jpg
Author Unknown
@jeffreymckenzie
Duplicate
Data
Yes, it's duplicate data.
Why might he have some duplication?
[doesn't check for existing customers]
[no customer search]
[no DB cleaning]
So Ron has asked us, all of us here,
To solve his problem, and we, collectively,
Are known as Apps N Stuff. ***
@jeffreymckenzie
Apps 'N Stuff
Ron wants us to fix his duplicate data problem.
He has 2 basic requirements for us.
First, he doesn't want to have to check
For duplicates up front.
@jeffreymckenzie
1. No Check at Order Time
2. Self-Service Cleanup
He really doesn't want the UI
for his order process to change
(you know, he likes things the way they are)
And he's worried that searching up front
Will slow the order, and that will make
His customers unhappy.
Second, he wants to clean up duplicates himself.
@jeffreymckenzie
1. No Check at Order Time
2. Self-Service Cleanup
He doesn't want Apps 'N Stuff to come out
Every week or so and clean up the data.
He also doesn't want to have some
Batch process running in the background
To automatically clean things up,
Because well, he just doesn't trust it.
@jeffreymckenzie
Food And Stuff
Solution
So we have to build a solution
That allows Ron to access the data,
Find duplicates,
And merge them together,
into a single record.
The first part of the solution is
a UI component,
@jeffreymckenzie
The actual screen that lets Ron find duplicates.
The second part of the solution
Is the backend database -- ***
=========
https://upload.wikimedia.org/wikipedia/commons/e/e0/Browser_ballonic
on2.svg
By pixelbuddha [CC BY 3.0
(http://creativecommons.org/licenses/by/3.0)], via Wikimedia Commons
@jeffreymckenzie
This is where we are going to focus
Our effort today.
We are going to write a stored procedure
That takes 2 duplicate customer records, ***
=========
https://commons.wikimedia.org/wiki/File:Applications-database.svg
By dracos (http://dracos.deviantart.com/#/d2y5ele) [CC BY-SA 3.0
(https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia
Commons
@jeffreymckenzie
Ron Swanson
Ron
Swanson
Ronald
Swanson
And merges them into a single customer.
The UI is going to take care of finding the customers,
So all the proc has to do is take the two records
And combine them. But there are complications.
We also have to make sure that the order history
For each customer is combined as well.
Let's take a look at the data model. ***
=========
https://upload.wikimedia.org/wikipedia/commons/4/40/Data-transfer.svg
By RRZEicons (Own work) [CC BY-SA 3.0
(https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia
Commons
This is an extremely simplified model –
I would not recommend this for a production DB.
Customer = first name, last name, loyalty id
OrderDetail = item purchased
Order = joins Customer with an Order
So once we are done, we should be left
With a single customer who has all the orders,
And the duplicate customer deleted. ***
@jeffreymckenzie
Before we start writing our procedure, however,
We need to get our TDD framework set up.
The tSQLt framework is very small, and in fact,
Contains only 6 files. ***
***
@jeffreymckenzie
There's a text file that explains the setup,
The license and release notes, and some example tests.
To install tSQLt you need to run the
Set CLR Enabled script –
There are some compiled assemblies
that tSQLt uses –
And then execute the tSqlt.class script,
Which will install all of the DB objects
That the framework needs. ***
@jeffreymckenzie
And what this does is install all
Of the tables, procedures, and functions
In its own schema, the tSQLt schema,
So it's logically separated from
The dbo schema or
Anything else you've created.
Now that we have tSQLt installed,
We can start working on our tests. ***
@jeffreymckenzie
1. Create Test Install Script
2. Create Test Run Script
So we are going to do two things –
First, create a SQL Script that installs our tests
in the database,
And second, create a SQL Script
that runs our tests.
Let's look at the install script first. ***
@jeffreymckenzie
USE Food_And_Stuff
GO
EXEC tSQLt.NewTestClass
@ClassName = N'FAS_Tests'
GO
------------- BEGIN [FAS_Tests].[InsertTestData] ----------
CREATE PROC FAS_Tests.InsertTestData
AS
BEGIN
END
------------- END [FAS_Tests].[InsertTestData] ------------
First, we're going to make sure that everything
Gets installed in the Food_And_Stuff database
With the use statement.
To execute a tSQLt statement, you type the
Schema name, followed by the command you want.
Here we use the tSQLt New Test Class command
To create our test class – what this actually does
Is create a new schema in the database we can
Attach our tests to…
@jeffreymckenzie
USE Food_And_Stuff
GO
EXEC tSQLt.NewTestClass
@ClassName = N'FAS_Tests'
GO
------------- BEGIN [FAS_Tests].[InsertTestData] ----------
CREATE PROC FAS_Tests.InsertTestData
AS
BEGIN
END
------------- END [FAS_Tests].[InsertTestData] ------------
again, this provides
A clear separation between our actual code,
Our tests, and the tSQLt framework.
One note of warning –
this will delete any test class with that name,
Without any warning (so script everything!)
Next we will create a procedure that inserts
The data we need for our tests.
First we'll create data for our customer table.
@jeffreymckenzie
---------------- BEGIN CUSTOMERS -------------------
DECLARE @RonaldId INT = 1, @RonId INT = 2
INSERT INTO dbo.Customer(
CustomerId, FirstName, LastName, LoyaltyId
)
VALUES(@RonaldId, 'Ronald', 'Swanson', 1234)
INSERT INTO dbo.Customer(
CustomerId, FirstName, LastName, LoyaltyId
)
VALUES(@RonId, 'Ron', 'Swanson', 1234)
---------------- END CUSTOMERS ---------------------
We want to test that a duplicate gets eliminated,
So we'll need two customers.
We're going to say Ron Swanson is the customer
We want to keep, and Ronald Swanson is the duplicate
So we'll insert customer ids (Ron is number 2),
The first name and last name, and finally the loyalty ID.
The loyalty ID is what tracks who gets what discounts --
@jeffreymckenzie
---------------- BEGIN CUSTOMERS -------------------
DECLARE @RonaldId INT = 1, @RonId INT = 2
INSERT INTO dbo.Customer(
CustomerId, FirstName, LastName, LoyaltyId
)
VALUES(@RonaldId, 'Ronald', 'Swanson', 1234)
INSERT INTO dbo.Customer(
CustomerId, FirstName, LastName, LoyaltyId
)
VALUES(@RonId, 'Ron', 'Swanson', 1234)
---------------- END CUSTOMERS ---------------------
You know, it's that card on your keychain
That says – yes, please take all of my personal
Information and record my purchases so
You can wrap it all up in a nice bow to sell
To a data broker who can in turn sell it
To an advertiser so they can milk me for more cash.
But I'm not cynical or anything.
But thank goodness Food And Stuff has this
Loyalty ID, because otherwise we'd have no way
To uniquely identify customers.
@jeffreymckenzie
---------------- BEGIN ORDERS ----------------------
DECLARE @RonaldOrderId INT = 11, @RonOrderId INT = 22
-- customer 1 order
INSERT INTO [dbo].[Order](OrderId, CustomerId)
VALUES(@RonaldOrderId, @RonaldId)
-- customer 2 order
INSERT INTO [dbo].[Order](OrderId, CustomerId)
VALUES(@RonOrderId, @RonId)
---------------- END ORDERS ------------------------
We'll do the same for orders,
Creating an order ID for both Ron and Ronald –
Again, at the end of this process,
Ron should have 2 orders under his name.
@jeffreymckenzie
---------------- BEGIN ORDER DETAIL ----------------
DECLARE @RonaldDetailId INT = 111
DECLARE @RonDetailId INT = 222
INSERT INTO [dbo].[OrderDetail](OrderDetailId, OrderId, ItemName)
VALUES(@RonaldDetailId, @RonaldOrderId,
'T-Bone Steaks: Val-U 20 Pack')
INSERT INTO [dbo].[OrderDetail](OrderDetailId, OrderId, ItemName)
VALUES(@RonaldDetailId, @RonaldOrderId,
'Bacon Strips: Val-U 100 Pack')
---------------- END ORDER DETAIL -------------------
And finally for order details.
We can see here that Ronald bought
A Value pack of 20 T-Bone steaks,
And Ron bought a Value pack
Of 100 bacon strips.
Clearly this is the same person.
@jeffreymckenzie
Fakes / Mocks
For the next part we need to talk about
The concept of faking or mocking in tests.
This is all part of test isolation that I
mentioned before. If the particular method
we are testing has to make a database
Or webservice call, we can simply create
A fake or mock of that call to keep our tests
Simple and focused. ***
@jeffreymckenzie
public class Button {
public String Click() {
return "That was easy.";
}
}
Let's go back to our EasyButton example.
Remember we implemented our click method?
Let's say instead of returning a hardcoded string,
We want to look up the quote from a service.
So let's do the replacement. ***
@jeffreymckenzie
public class Button {
public String Click(MessageService) {
return MessageService.Get();
}
}
I'm using a little pseudocode here just to
Make things a little clearer.
Now our unit test will actually be testing
The Click method and the service –
This will take longer, and could result
In failures from the service that are
Unrelated to our actual click method.
So what we can do is create a fake
Of our Service call. ***
@jeffreymckenzie
public class FakeMessageService {
public String Get() {
return “When I eat,
it is the food
that is scared.
– Ron Swanson";
}
}
Instead of passing a real instance
Of the Message Service, we will create
A fake version that returns the same
Message every time.
This makes sure we get a result
From the click method, and also
That the message service will never fail. ***
@jeffreymckenzie
------------- BEGIN [FAS_Tests].[Setup] -------------------
CREATE PROC FAS_Tests.Setup AS
BEGIN
--create fakes for tests against tables
EXEC tSQLt.FakeTable 'dbo.OrderDetail'
EXEC tSQLt.FakeTable 'dbo.Order'
EXEC tSQLt.FakeTable 'dbo.Customer'
-- populate fake tables
EXEC FAS_Tests.InsertTestData
END
GO
------------- END [FAS_Tests].[Setup] ---------------------
In the next part of the install script,
We are going to create the setup procedure.
If you have a procedure called Setup
In your test class, or schema, tSQLt
Will run that proc before every test.
We can use that to our advantage
And do some setup work
that every test will need.
First thing we do is create some Fakes….
@jeffreymckenzie
------------- BEGIN [FAS_Tests].[Setup] -------------------
CREATE PROC FAS_Tests.Setup AS
BEGIN
--create fakes for tests against tables
EXEC tSQLt.FakeTable 'dbo.OrderDetail'
EXEC tSQLt.FakeTable 'dbo.Order'
EXEC tSQLt.FakeTable 'dbo.Customer'
-- populate fake tables
EXEC FAS_Tests.InsertTestData
END
GO
------------- END [FAS_Tests].[Setup] ---------------------
For the tables we want to test.
The fake table command in tSQLt replaces
the actual table with an empty copy
That has no constraints.
That way it's isolated from the rest of the database
And we can test operations on that table alone.
After we create the fakes, we can use the proc
We created before to insert test data
about Ronald and Ron ***
@jeffreymckenzie
Here is our customer table,
With both Ron and Ronald in there…***
@jeffreymckenzie
Then the Order detail table,
With its meat extravaganza… ***
@jeffreymckenzie
And finally the Order table,
Which matches the customer
to the particular order.
Note that this only happens
when a test is run – before or after a test
These tables have whatever data
Was in them originally. ***
@jeffreymckenzie
----------- BEGIN GivenMerge-ThenCustomerIsCorrect --------------
CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomersIsCorrect]
AS
BEGIN
--Arrange
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --CustomerId we want to keep
DECLARE @ExpectedRonFirstName NVARCHAR(50) =
Now we're ready to create our first test.
tSQLt requires that every test be a procedure
That starts with the word TEST.
What we want to accomplish in this test
Is to do the merge, then ensure that data
In the Customers Table is correct.
So I've started the arrange section here.
Remember that when this test starts,
All of the tables will be populated… ***
@jeffreymckenzie
----------- BEGIN GivenMerge-ThenCustomerIsCorrect --------------
CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect]
AS
BEGIN
--Arrange
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --CustomerId we want to keep
DECLARE @ExpectedRonFirstName NVARCHAR(50) =
..because the setup has already run.
So to set the ExpectedRonFirstName variable,
What are a couple of ways we could do that?
***
@jeffreymckenzie
----------- BEGIN GivenMerge-ThenCustomerIsCorrect --------------
CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect]
AS
BEGIN
--Arrange
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --CustomerId we want to keep
DECLARE @ExpectedRonFirstName NVARCHAR(50) =
So to set the ExpectedRonFirstName variable,
What are a couple of ways we could do that?
Hardcode name –
Select based on ID --
***
@jeffreymckenzie
----------- BEGIN GivenMerge-ThenCustomerIsCorrect --------------
CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect]
AS
BEGIN
--Arrange
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --CustomerId we want to keep
DECLARE @ExpectedRonFirstName NVARCHAR(50) = (
SELECT FirstName FROM dbo.Customer
WHERE CustomerId = @RonId
)
If we select the value based on the ID,
That allows us to test other IDs without
Having to change a hardcoded string.
***
@jeffreymckenzie
----------- BEGIN GivenMerge-ThenCustomerIsCorrect --------------
CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect]
AS
BEGIN
--Arrange
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --CustomerId we want to keep
DECLARE @ExpectedRonFirstName NVARCHAR(50) = (
SELECT FirstName FROM dbo.Customer
WHERE CustomerId = @RonId
)
If we select the value based on the ID,
That allows us to test other IDs without
Having to change a hardcoded string.
***
@jeffreymckenzie
DECLARE @ExpectedRonFirstName NVARCHAR(50) = (
SELECT FirstName FROM dbo.Customer
WHERE CustomerId = @RonId
)
DECLARE @ExpectedRonLastName NVARCHAR(50)= (
SELECT LastName FROM dbo.Customer
WHERE CustomerId = @RonId
)
DECLARE @ExpectedLoyaltyId INT = (
SELECT LoyaltyId FROM dbo.Customer
WHERE CustomerId = @RonId
)
Now we can do the same for all of the other
Values in the Customer table.
Now, how do we do the actual comparison
Between the expected values and the actual values?
We can do so through a table compare…
***
@jeffreymckenzie
CREATE TABLE FAS_Tests.Expected(
CustomerId INT NOT NULL,
FirstName NVARCHAR(50) NOT NULL,
LastName NVARCHAR(50) NOT NULL,
LoyaltyId INT NOT NULL
)
-only Ron should exist
INSERT INTO FAS_Tests.Expected(
CustomerId, FirstName, LastName, LoyaltyId)
VALUES(@RonId, @ExpectedRonFirstName,
, @ExpectedRonLastName
, @ExpectedLoyaltyId
)
First we create an Expected table
Inside our FAS_Tests schema, again,
So it's separated from the application code,
And then we insert the expected values
Into that table, because we should only see
one record when the merge is complete.
That's it for the arrange section – everything
Is set up to see if our test is correct
Once the test is executed. Let's finish the test: ***
@jeffreymckenzie
--Act
EXEC dbo.MergeCustomer
@DuplicateCustomer = @RonaldId,
@CustomerToKeep = @RonId
--Assert
EXEC tSQLt.AssertEqualsTable
@Expected = N'FAS_Tests.Expected',
@Actual = N'dbo.Customer'
@FailMsg = N'Customer table has incorrect data.'
END
GO
-------- END GivenMergeCustomers-ThenCustomerIsCorrect ------------
For the Act section, we will execute
The MergeCustomer stored procedure.
For our assert section, we are going to use
The tSQLt AssertEqualsTable assertion –
This determines whether or not two tables
Have the same data – we are comparing
The expected table in our test schema
With the actual Customer table,
Which in this case is our Fake table.
@jeffreymckenzie
1. Create Test Install Script
2. Create Test Run Script
So we will run our Test Install Script
to create our test class with the latest tests.
In order to run this test,
We will need to start
on our test run script.
It's pretty simple.
***
@jeffreymckenzie
USE Food_And_Stuff
/*
EXEC tSQLt.RunAll
GO
EXEC tSQLt.Run
N'FAS_Tests'
GO */
EXEC tSQLt.Run
N'FAS_Tests.[test GivenMergeCustomers-ThenCustomerIsCorrect]'
GO
There are three ways to run a test in tSQLt –
First is the RunAll command, which runs all tests
In all test classes.
The second is the Run command with a class name,
Which will run all tests in that test class.
Finally you can call the Run command with
A single test name, which will run only that class.
[ASK]
So if we run our test, what's going to happen? ***
@jeffreymckenzie
(0 row(s) affected)
[FAS_Tests].[test GivenMergeCustomers...] failed: (Error) Could not
find stored procedure 'dbo.MergeCustomer'.[16,62]{MergeCustomer,49}
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result|
+--+--------------------------------+-------+------+
|1 |[FAS_Tests].[test GivenMerge...]| 236|Error |
-------------------------------------------------------------------
Msg 50000, Level 16, State 10, Line 1: Test Case Summary: 1 test
case(s) executed, 0 succeeded, 0 failed, 1 errored.
-------------------------------------------------------------------
Here's the output – tSQLt shows us
The actual error, that the MergeCustomer
Stored proc can't be found,
Then shows us the test summary, including
The name of the test, the duration,
And the result. Because it's red, we know
Immediately that it failed.
@jeffreymckenzie
So if this is our Customer table,
And we want to eliminate the Ronald record,
What's the least amount of effort we can do
To get this test to pass?
***
@jeffreymckenzie
USE Food_And_Stuff
GO
CREATE PROCEDURE [dbo].[MergeCustomer]
@DuplicateCustomer INT,
@CustomerToKeep INT
AS
BEGIN
END
GO
[delete duplicate]
@jeffreymckenzie
USE Food_And_Stuff
GO
CREATE PROCEDURE [dbo].[MergeCustomer]
@DuplicateCustomer INT,
@CustomerToKeep INT
AS
BEGIN
DELETE dbo.Customer
WHERE CustomerId = @DuplicateCustomer
END
GO
Yep, that's right – let's
Run our test again….
@jeffreymckenzie
(1 row(s) affected)
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result |
+--+--------------------------------+-------+-------+
|1 |[FAS_Tests].[test GivenMerge...]| 54|Success|
-------------------------------------------------------------------
Test Case Summary: 1 test case(s) executed, 1 succeeded, 0 failed,
0 errored.
-------------------------------------------------------------------
Now our test is passing.
Let's write our next test,
This time for the order table.
@jeffreymckenzie
This is a little different –
Remember we want to keep all
of the order history, so what should we
Expect the order table at the bottom
To look like once the merge is complete?
[CustomerId should be two for both orders]
Right, so let's write a test for that -- ***
@jeffreymckenzie
--------- BEGIN GivenMergeCustomers-ThenOrderIsCorrect ------------
CREATE PROC FAS_Tests.[test GivenMergeCustomers-ThenOrderIsCorrect]
AS
BEGIN
--Assert
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 --Customer Id we want to keep
CREATE TABLE FAS_Tests.Expected(
OrderId INT NOT NULL,
CustomerId INT NOT NULL
)
We will need to write the test a little differently
For this one – for the customer test,
We only needed one record, so we could
Insert one record into the expected table.
Here, we could have any number of orders
Between the two customers –
So how should we fill the expected table here? ***
@jeffreymckenzie
CREATE TABLE FAS_Tests.Expected(
OrderId INT NOT NULL,
CustomerId INT NOT NULL
)
--only orders for Ron (CustomerId 2) should exist
INSERT INTO FAS_Tests.Expected(
OrderId,
CustomerId
)
SELECT OrderId, @RonId
FROM dbo.[Order]
WHERE CustomerId = @RonaldId
OR CustomerId = @RonId
Essentially what we are doing here
Is selecting every record in the order table
For both customers, and inserting
The order id, as well as the customerId
We want to keep.
Let's finish with the act and assert
***
@jeffreymckenzie
--Act
EXEC dbo.MergeCustomer
@DuplicateCustomer = @RonaldId,
@CustomerToKeep = @RonId
--Assert
EXEC tSQLt.AssertEqualsTable
@Expected = N'FAS_Tests.Expected',
@Actual = N'dbo.Order'
@FailMsg = N'Order table has incorrect data.'
END
GO
-------- END GivenMergeCustomers-ThenOrderIsCorrect ------------
This is the same act and arrange as the last test,
Except we are now checking the Order table.
Let’s add our new test to the script… ***
@jeffreymckenzie
USE Food_And_Stuff
EXEC tSQLt.Run
N'FAS_Tests.[test GivenMergeCustomers-ThenCustomerIsCorrect]’
GO
EXEC tSQLt.Run
N'FAS_Tests.[test GivenMergeCustomers-ThenOrderIsCorrect]’
GO
Now we will run both to make sure
The previous test still passes. ***
@jeffreymckenzie
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result |
+--+----------------------------------+-------+-------+
|1 |[FAS_Tests].[test Given...Customer| 37|Success|
|2 |[FAS_Tests].[test Given...Order | 33|Failure|
-------------------------------------------------------------------
Msg 50000, Level 16, State 10, Line 7, Test Case Summary:
2 test case(s) executed, 1 succeeded, 1 failed, 0 errored.
-------------------------------------------------------------------
So our customer test is passing,
But our order test is not – which is good
Because we haven’t written the code yet.
When we are using the AssertEqualsTable
Assertion, we get an additional error message… ***
@jeffreymckenzie
(1 row(s) affected)
[FAS_Tests].[test GivenMergeCustomers-ThenOrderIsCorrect] failed:
(Failure) Order table has incorrect data.
|_m_|OrderId|CustomerId|
+---+-------+----------+
|< |11 |2 |
|= |22 |2 |
|> |11 |1 |
This graphical table shows us
Exactly how the data is incorrect
A less than sign means that the record
Is in the expected table but not the actual table –
The greater than sign means the record
Is in the actual table but not the expected table,
And the equals sign means it’s in both tables.
This output can help you troubleshoot data issues. ***
@jeffreymckenzie
So now we want to make our order table
Have all the orders for Ronald and Ron
Belong to Ron – what’s the least amount
Of code we need to accomplish this?
[UPDATE CustomerId column]
So let’s update our procedure…. ***
@jeffreymckenzie
CREATE PROCEDURE [dbo].[MergeCustomer]
@DuplicateCustomer INT,
@CustomerToKeep INT
AS
BEGIN
DELETE dbo.Customer
WHERE CustomerId = @DuplicateCustomer
UPDATE dbo.[Order]
SET CustomerId = @CustomerToKeep
WHERE CustomerId = @DuplicateCustomer
OR CustomerId = @CustomerToKeep
END
GO
We’ve added our update statement,
And we will run our tests again ***…
@jeffreymckenzie
(1 row(s) affected)
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result |
+--+----------------------------------------------+-------+-------+
|1 |[FAS_Tests].[test GivenMerge...Customer] | 37|Success|
|2 |[FAS_Tests].[test GivenMerge...Order] | 40|Success|
-------------------------------------------------------------------
Test Case Summary: 2 test case(s) executed, 2 succeeded, 0 failed,
0 errored.
-------------------------------------------------------------------
And now both are passing. ***
@jeffreymckenzie
Now because OrderDetail is tied to Order,
OrderDetail will stay the same,
So we don’t need a test for that,
Because we are not performing any action
On that table.
Our tests are passing, so let’s try this
On the live table – here’s our script … ***
@jeffreymckenzie
USE Food_And_Stuff
GO
BEGIN TRAN
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 /* Customer Id we want to keep */
EXEC FAS_Tests.InsertTestData
EXEC dbo.MergeCustomer
@DuplicateCustomer = @RonaldId,
@CustomerToKeep = @RonId
SELECT * FROM dbo.Customer
SELECT * FROM dbo.[Order]
SELECT * FROM dbo.OrderDetail
ROLLBACK TRAN
GO
We are going to run this in a transaction
So we can reset the tables and run it repeatedly.
First we have our regular customer IDs for
Ronald and Ron.
Then we run our insert data procedure,
Execute the merge procedure,
Then do some selects to see
What the data looks like….
***
@jeffreymckenzie
Msg 547, Level 16, State 0
Procedure MergeCustomer, Line 7 [Batch Start Line 2]
The DELETE statement conflicted with the REFERENCE
constraint "FK_Order_Customer_CustomerId".
The conflict occurred in database "Food_And_Stuff",
table "dbo.Order", column 'CustomerId’.
The statement has been terminated.
And we have an error –
What’s going on here?
[DELETED a customer record
still attached to an Order.]
Remember I said when you create
A fake table in tSQLt it creates
A blank copy without restraints?
We didn’t get this error in our test
Because we had no constraints. ***
@jeffreymckenzie
------------- BEGIN [FAS_Tests].[Setup] -------------------
CREATE PROC FAS_Tests.Setup AS
BEGIN
--create fakes for tests against tables
EXEC tSQLt.FakeTable 'dbo.OrderDetail'
EXEC tSQLt.FakeTable 'dbo.Order'
EXEC tSQLt.FakeTable 'dbo.Customer’
EXEC tSQLt.ApplyConstraint N'dbo.Order',
N'FK_Order_Customer_CustomerId'
-- populate fake tables
EXEC FAS_Tests.InsertTestData
END
GO
------------- END [FAS_Tests].[Setup] ---------------------
Fortunately we have a way
To add constraints to our tests,
Using the tSQLt.ApplyConstraint command.
After we create our fake table, all
Constraints are removed, but we can then
Apply individual constraints using the
Table name and constraint name – here
We are applying the foreign key constraint
Between the Order and Customer tables. ***
@jeffreymckenzie
[FAS_Tests].[test GivenMerge...CustomerIsCorrect] failed: (Error)
DELETE statement conflicted with "FK_Order_Customer_CustomerId".
The conflict occurred in database "Food_And_Stuff", table
"dbo.Order", column 'CustomerId'.[16,0]{MergeCustomer,7}
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result|
+--+--------------------------------+-------+------+
|1 |[FAS_Tests].[test GivenMerge...]| 236|Error |
-------------------------------------------------------------------
Msg 50000, Level 16, State 10, Line 1: Test Case Summary: 1 test
case(s) executed, 0 succeeded, 0 failed, 1 errored.
-------------------------------------------------------------------
When we run the test again,
We get the same error we did when running live.
So we now have a failing test that we need to fix.
Let’s take a look at our
MergeCustomer procedure… ***
@jeffreymckenzie
CREATE PROCEDURE [dbo].[MergeCustomer]
@DuplicateCustomer INT,
@CustomerToKeep INT
AS
BEGIN
DELETE dbo.Customer
WHERE CustomerId = @DuplicateCustomer
UPDATE dbo.[Order]
SET CustomerId = @CustomerToKeep
WHERE CustomerId = @DuplicateCustomer
OR CustomerId = @CustomerToKeep
END
GO
Again , what’s the simplest change we can make
To get our test to pass?
[flip the statements…] ***
@jeffreymckenzie
CREATE PROCEDURE [dbo].[MergeCustomer]
@DuplicateCustomer INT,
@CustomerToKeep INT
AS
BEGIN
UPDATE dbo.[Order]
SET CustomerId = @CustomerToKeep
WHERE CustomerId = @DuplicateCustomer
OR CustomerId = @CustomerToKeep
DELETE dbo.Customer
WHERE CustomerId = @DuplicateCustomer
END
GO
Right, we make the update statement first,
So when we do the customer delete,
That customer will have no relationship
With the Order table.
Let’s run our tests again…. ***
@jeffreymckenzie
(1 row(s) affected)
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result |
+--+----------------------------------------------+-------+-------+
|1 |[FAS_Tests].[test GivenMerge...Customer] | 37|Success|
|2 |[FAS_Tests].[test GivenMerge...Order] | 40|Success|
-------------------------------------------------------------------
Test Case Summary: 2 test case(s) executed, 2 succeeded, 0 failed,
0 errored.
-------------------------------------------------------------------
And now we are back to passing tests.
***
@jeffreymckenzie
USE Food_And_Stuff
GO
BEGIN TRAN
DECLARE @RonaldId INT= 1
DECLARE @RonId INT= 2 /* Customer Id we want to keep */
EXEC FAS_Tests.InsertTestData
EXEC dbo.MergeCustomer
@DuplicateCustomer = @RonaldId,
@CustomerToKeep = @RonId
SELECT * FROM dbo.Customer
SELECT * FROM dbo.[Order]
SELECT * FROM dbo.OrderDetail
ROLLBACK TRAN
GO
Let’s try our live test again and see
What that returns….
Again we are inserting test data
And performing the merge
against the actual table….
***
@jeffreymckenzie
Here’s the output – no errors
And it has what we expect,
Just the one record for Ron,
Who is attached to all of the orders now.
As we continue to add features
To this, we now have a set of tests
We can use to make sure everything
Is working properly.
***
@jeffreymckenzie
So congratulations everybody –
Ron is very happy with our work,
And has offered everyone
A five dollar gift card to Food and Stuff.
=========
https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo
d_and_Stuff_2.png/revision/latest?cb=20120730155117
http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
@jeffreymckenzie
That’s all I have….
=========
http://parksandrecreation.wikia.com/wiki/Food_and_Stuff
https://vignette.wikia.nocookie.net/parksandrecreation/images/1/15/Foo
d_and_Stuff.png/revision/latest?cb=20120730155051
Hey, You Got
Your TDD
In My SQL DB!
Jeff McKenzie
@jeffreymckenzie
mail@mcknz.com
So thank you for listening & for being here.
So does anybody have any questions about --
TDD, the tSQLt Framework, or testing in general?

Contenu connexe

Tendances

Test Driven Development (TDD) & Continuous Integration (CI)
Test Driven Development (TDD) & Continuous Integration (CI)Test Driven Development (TDD) & Continuous Integration (CI)
Test Driven Development (TDD) & Continuous Integration (CI)Fatkul Amri
 
Agile and test driven development
Agile and test driven developmentAgile and test driven development
Agile and test driven developmentAhmed El-Deeb
 
assertYourself - Breaking the Theories and Assumptions of Unit Testing in Flex
assertYourself - Breaking the Theories and Assumptions of Unit Testing in FlexassertYourself - Breaking the Theories and Assumptions of Unit Testing in Flex
assertYourself - Breaking the Theories and Assumptions of Unit Testing in Flexmichael.labriola
 
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...Ho Chi Minh City Software Testing Club
 
Improving the Quality of Incoming Code
Improving the Quality of Incoming CodeImproving the Quality of Incoming Code
Improving the Quality of Incoming CodeNaresh Jain
 
A journey to a Full Stack Tester
A journey to a Full Stack Tester A journey to a Full Stack Tester
A journey to a Full Stack Tester KMS Technology
 
Growing a Company Test Community: Roles and Paths for Testers
Growing a Company Test Community: Roles and Paths for TestersGrowing a Company Test Community: Roles and Paths for Testers
Growing a Company Test Community: Roles and Paths for TestersTEST Huddle
 
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019Agile India
 
How testers add value to the organization appium conf
How testers add value to the organization  appium confHow testers add value to the organization  appium conf
How testers add value to the organization appium confCorina Pip
 
Risk Mitigation Using Exploratory and Technical Testing | QASymphony Webinar
Risk Mitigation Using Exploratory and Technical Testing | QASymphony WebinarRisk Mitigation Using Exploratory and Technical Testing | QASymphony Webinar
Risk Mitigation Using Exploratory and Technical Testing | QASymphony WebinarQASymphony
 
Agile Test Driven Development
Agile Test Driven DevelopmentAgile Test Driven Development
Agile Test Driven DevelopmentViraf Karai
 
How to use selenium successfully
How to use selenium successfullyHow to use selenium successfully
How to use selenium successfullyTEST Huddle
 
Building and Scaling High Performing Technology Organizations by Jez Humble a...
Building and Scaling High Performing Technology Organizations by Jez Humble a...Building and Scaling High Performing Technology Organizations by Jez Humble a...
Building and Scaling High Performing Technology Organizations by Jez Humble a...Agile India
 
New Model Testing: A New Test Process and Tool
New Model Testing:  A New Test Process and ToolNew Model Testing:  A New Test Process and Tool
New Model Testing: A New Test Process and ToolTEST Huddle
 
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...TEST Huddle
 
CWIN17 New-York / Drive continuous delivery with continous testing
CWIN17 New-York / Drive continuous delivery with continous testingCWIN17 New-York / Drive continuous delivery with continous testing
CWIN17 New-York / Drive continuous delivery with continous testingCapgemini
 
Test Estimation Hacks: Tips, Tricks and Tools Webinar
Test Estimation Hacks: Tips, Tricks and Tools WebinarTest Estimation Hacks: Tips, Tricks and Tools Webinar
Test Estimation Hacks: Tips, Tricks and Tools WebinarQASymphony
 

Tendances (20)

Test Driven Development (TDD) & Continuous Integration (CI)
Test Driven Development (TDD) & Continuous Integration (CI)Test Driven Development (TDD) & Continuous Integration (CI)
Test Driven Development (TDD) & Continuous Integration (CI)
 
Agile and test driven development
Agile and test driven developmentAgile and test driven development
Agile and test driven development
 
New model
New modelNew model
New model
 
assertYourself - Breaking the Theories and Assumptions of Unit Testing in Flex
assertYourself - Breaking the Theories and Assumptions of Unit Testing in FlexassertYourself - Breaking the Theories and Assumptions of Unit Testing in Flex
assertYourself - Breaking the Theories and Assumptions of Unit Testing in Flex
 
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...
The New Agile Testing Quadrants: Bringing Skilled Testers and Developers Toge...
 
Improving the Quality of Incoming Code
Improving the Quality of Incoming CodeImproving the Quality of Incoming Code
Improving the Quality of Incoming Code
 
A journey to a Full Stack Tester
A journey to a Full Stack Tester A journey to a Full Stack Tester
A journey to a Full Stack Tester
 
Growing a Company Test Community: Roles and Paths for Testers
Growing a Company Test Community: Roles and Paths for TestersGrowing a Company Test Community: Roles and Paths for Testers
Growing a Company Test Community: Roles and Paths for Testers
 
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019
Acceptance Testing for Continuous Delivery by Dave Farley at #AgileIndia2019
 
A Taste of Exploratory Testing
A Taste of Exploratory TestingA Taste of Exploratory Testing
A Taste of Exploratory Testing
 
[HCMC STC Jan 2015] Workshop Of Context-Driven Testing In Agile
[HCMC STC Jan 2015] Workshop Of Context-Driven Testing In Agile[HCMC STC Jan 2015] Workshop Of Context-Driven Testing In Agile
[HCMC STC Jan 2015] Workshop Of Context-Driven Testing In Agile
 
How testers add value to the organization appium conf
How testers add value to the organization  appium confHow testers add value to the organization  appium conf
How testers add value to the organization appium conf
 
Risk Mitigation Using Exploratory and Technical Testing | QASymphony Webinar
Risk Mitigation Using Exploratory and Technical Testing | QASymphony WebinarRisk Mitigation Using Exploratory and Technical Testing | QASymphony Webinar
Risk Mitigation Using Exploratory and Technical Testing | QASymphony Webinar
 
Agile Test Driven Development
Agile Test Driven DevelopmentAgile Test Driven Development
Agile Test Driven Development
 
How to use selenium successfully
How to use selenium successfullyHow to use selenium successfully
How to use selenium successfully
 
Building and Scaling High Performing Technology Organizations by Jez Humble a...
Building and Scaling High Performing Technology Organizations by Jez Humble a...Building and Scaling High Performing Technology Organizations by Jez Humble a...
Building and Scaling High Performing Technology Organizations by Jez Humble a...
 
New Model Testing: A New Test Process and Tool
New Model Testing:  A New Test Process and ToolNew Model Testing:  A New Test Process and Tool
New Model Testing: A New Test Process and Tool
 
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...
Testing As A Bottleneck - How Testing Slows Down Modern Development Processes...
 
CWIN17 New-York / Drive continuous delivery with continous testing
CWIN17 New-York / Drive continuous delivery with continous testingCWIN17 New-York / Drive continuous delivery with continous testing
CWIN17 New-York / Drive continuous delivery with continous testing
 
Test Estimation Hacks: Tips, Tricks and Tools Webinar
Test Estimation Hacks: Tips, Tricks and Tools WebinarTest Estimation Hacks: Tips, Tricks and Tools Webinar
Test Estimation Hacks: Tips, Tricks and Tools Webinar
 

Similaire à Apply TDD to SQL with .NET

Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In ActionJon Kruger
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Abdelkrim Boujraf
 
Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)Gianluca Padovani
 
TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019Paulo Clavijo
 
Understanding Why Testing is Importaint
Understanding Why Testing is ImportaintUnderstanding Why Testing is Importaint
Understanding Why Testing is ImportaintSana Nasar
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Gianluca Padovani
 
TDD - Seriously, try it! - Opensouthcode
TDD - Seriously, try it! - OpensouthcodeTDD - Seriously, try it! - Opensouthcode
TDD - Seriously, try it! - OpensouthcodeNacho Cougil
 
iOS Test-Driven Development
iOS Test-Driven DevelopmentiOS Test-Driven Development
iOS Test-Driven DevelopmentPablo Villar
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010guest5639fa9
 
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoTest Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoElad Elrom
 
DevOps - Boldly Go for Distro
DevOps - Boldly Go for DistroDevOps - Boldly Go for Distro
DevOps - Boldly Go for DistroPaul Boos
 
Unit testing
Unit testingUnit testing
Unit testingPiXeL16
 
Driving application development through behavior driven development
Driving application development through behavior driven developmentDriving application development through behavior driven development
Driving application development through behavior driven developmentEinar Ingebrigtsen
 
Introduction to Test Driven Development
Introduction to Test Driven DevelopmentIntroduction to Test Driven Development
Introduction to Test Driven DevelopmentMichael Denomy
 
Test Drive Development
Test Drive DevelopmentTest Drive Development
Test Drive Developmentsatya sudheer
 

Similaire à Apply TDD to SQL with .NET (20)

Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
 
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
Test-Driven Developments are Inefficient; Behavior-Driven Developments are a ...
 
Ian Cooper webinar for DDD Iran: Kent beck style tdd seven years after
Ian Cooper webinar for DDD Iran: Kent beck style tdd   seven years afterIan Cooper webinar for DDD Iran: Kent beck style tdd   seven years after
Ian Cooper webinar for DDD Iran: Kent beck style tdd seven years after
 
Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)Tdd is not about testing (C++ version)
Tdd is not about testing (C++ version)
 
TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019TDD and Simple Design Workshop - Session 1 - March 2019
TDD and Simple Design Workshop - Session 1 - March 2019
 
Understanding Why Testing is Importaint
Understanding Why Testing is ImportaintUnderstanding Why Testing is Importaint
Understanding Why Testing is Importaint
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
TDD - Seriously, try it! - Opensouthcode
TDD - Seriously, try it! - OpensouthcodeTDD - Seriously, try it! - Opensouthcode
TDD - Seriously, try it! - Opensouthcode
 
iOS Test-Driven Development
iOS Test-Driven DevelopmentiOS Test-Driven Development
iOS Test-Driven Development
 
Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010Test Driven Development (TDD) Preso 360|Flex 2010
Test Driven Development (TDD) Preso 360|Flex 2010
 
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose presoTest Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
Test Driven Development (TDD) with FlexUnit 4 - 360|Flex San Jose preso
 
DevOps - Boldly Go for Distro
DevOps - Boldly Go for DistroDevOps - Boldly Go for Distro
DevOps - Boldly Go for Distro
 
Unit testing
Unit testingUnit testing
Unit testing
 
Driving application development through behavior driven development
Driving application development through behavior driven developmentDriving application development through behavior driven development
Driving application development through behavior driven development
 
TDD in Agile
TDD in AgileTDD in Agile
TDD in Agile
 
TDD Workshop UTN 2012
TDD Workshop UTN 2012TDD Workshop UTN 2012
TDD Workshop UTN 2012
 
Raising the Bar
Raising the BarRaising the Bar
Raising the Bar
 
Introduction to Test Driven Development
Introduction to Test Driven DevelopmentIntroduction to Test Driven Development
Introduction to Test Driven Development
 
Debugging
DebuggingDebugging
Debugging
 
Test Drive Development
Test Drive DevelopmentTest Drive Development
Test Drive Development
 

Plus de QA or the Highway

KrishnaToolComparisionPPT.pdf
KrishnaToolComparisionPPT.pdfKrishnaToolComparisionPPT.pdf
KrishnaToolComparisionPPT.pdfQA or the Highway
 
Ravi Lakkavalli - World Quality Report.pptx
Ravi Lakkavalli - World Quality Report.pptxRavi Lakkavalli - World Quality Report.pptx
Ravi Lakkavalli - World Quality Report.pptxQA or the Highway
 
Caleb Crandall - Testing Between the Buckets.pptx
Caleb Crandall - Testing Between the Buckets.pptxCaleb Crandall - Testing Between the Buckets.pptx
Caleb Crandall - Testing Between the Buckets.pptxQA or the Highway
 
Thomas Haver - Mobile Testing.pdf
Thomas Haver - Mobile Testing.pdfThomas Haver - Mobile Testing.pdf
Thomas Haver - Mobile Testing.pdfQA or the Highway
 
Thomas Haver - Example Mapping.pdf
Thomas Haver - Example Mapping.pdfThomas Haver - Example Mapping.pdf
Thomas Haver - Example Mapping.pdfQA or the Highway
 
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdf
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdfJoe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdf
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdfQA or the Highway
 
Sarah Geisinger - Continious Testing Metrics That Matter.pdf
Sarah Geisinger - Continious Testing Metrics That Matter.pdfSarah Geisinger - Continious Testing Metrics That Matter.pdf
Sarah Geisinger - Continious Testing Metrics That Matter.pdfQA or the Highway
 
Jeff Sing - Quarterly Service Delivery Reviews.pdf
Jeff Sing - Quarterly Service Delivery Reviews.pdfJeff Sing - Quarterly Service Delivery Reviews.pdf
Jeff Sing - Quarterly Service Delivery Reviews.pdfQA or the Highway
 
Leandro Melendez - Chihuahua Load Tests.pdf
Leandro Melendez - Chihuahua Load Tests.pdfLeandro Melendez - Chihuahua Load Tests.pdf
Leandro Melendez - Chihuahua Load Tests.pdfQA or the Highway
 
Rick Clymer - Incident Management.pdf
Rick Clymer - Incident Management.pdfRick Clymer - Incident Management.pdf
Rick Clymer - Incident Management.pdfQA or the Highway
 
Robert Fornal - ChatGPT as a Testing Tool.pptx
Robert Fornal - ChatGPT as a Testing Tool.pptxRobert Fornal - ChatGPT as a Testing Tool.pptx
Robert Fornal - ChatGPT as a Testing Tool.pptxQA or the Highway
 
Federico Toledo - Extra-functional testing.pdf
Federico Toledo - Extra-functional testing.pdfFederico Toledo - Extra-functional testing.pdf
Federico Toledo - Extra-functional testing.pdfQA or the Highway
 
Andrew Knight - Managing the Test Data Nightmare.pptx
Andrew Knight - Managing the Test Data Nightmare.pptxAndrew Knight - Managing the Test Data Nightmare.pptx
Andrew Knight - Managing the Test Data Nightmare.pptxQA or the Highway
 
Melissa Tondi - Automation We_re Doing it Wrong.pdf
Melissa Tondi - Automation We_re Doing it Wrong.pdfMelissa Tondi - Automation We_re Doing it Wrong.pdf
Melissa Tondi - Automation We_re Doing it Wrong.pdfQA or the Highway
 
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdf
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdfJeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdf
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdfQA or the Highway
 
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptx
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptxDesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptx
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptxQA or the Highway
 
Damian Synadinos - Word Smatter.pdf
Damian Synadinos - Word Smatter.pdfDamian Synadinos - Word Smatter.pdf
Damian Synadinos - Word Smatter.pdfQA or the Highway
 
Lee Barnes - What Successful Test Automation is.pdf
Lee Barnes - What Successful Test Automation is.pdfLee Barnes - What Successful Test Automation is.pdf
Lee Barnes - What Successful Test Automation is.pdfQA or the Highway
 
Jordan Powell - API Testing with Cypress.pptx
Jordan Powell - API Testing with Cypress.pptxJordan Powell - API Testing with Cypress.pptx
Jordan Powell - API Testing with Cypress.pptxQA or the Highway
 
Carlos Kidman - Exploring AI Applications in Testing.pptx
Carlos Kidman - Exploring AI Applications in Testing.pptxCarlos Kidman - Exploring AI Applications in Testing.pptx
Carlos Kidman - Exploring AI Applications in Testing.pptxQA or the Highway
 

Plus de QA or the Highway (20)

KrishnaToolComparisionPPT.pdf
KrishnaToolComparisionPPT.pdfKrishnaToolComparisionPPT.pdf
KrishnaToolComparisionPPT.pdf
 
Ravi Lakkavalli - World Quality Report.pptx
Ravi Lakkavalli - World Quality Report.pptxRavi Lakkavalli - World Quality Report.pptx
Ravi Lakkavalli - World Quality Report.pptx
 
Caleb Crandall - Testing Between the Buckets.pptx
Caleb Crandall - Testing Between the Buckets.pptxCaleb Crandall - Testing Between the Buckets.pptx
Caleb Crandall - Testing Between the Buckets.pptx
 
Thomas Haver - Mobile Testing.pdf
Thomas Haver - Mobile Testing.pdfThomas Haver - Mobile Testing.pdf
Thomas Haver - Mobile Testing.pdf
 
Thomas Haver - Example Mapping.pdf
Thomas Haver - Example Mapping.pdfThomas Haver - Example Mapping.pdf
Thomas Haver - Example Mapping.pdf
 
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdf
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdfJoe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdf
Joe Colantonio - Actionable Automation Awesomeness in Testing Farm.pdf
 
Sarah Geisinger - Continious Testing Metrics That Matter.pdf
Sarah Geisinger - Continious Testing Metrics That Matter.pdfSarah Geisinger - Continious Testing Metrics That Matter.pdf
Sarah Geisinger - Continious Testing Metrics That Matter.pdf
 
Jeff Sing - Quarterly Service Delivery Reviews.pdf
Jeff Sing - Quarterly Service Delivery Reviews.pdfJeff Sing - Quarterly Service Delivery Reviews.pdf
Jeff Sing - Quarterly Service Delivery Reviews.pdf
 
Leandro Melendez - Chihuahua Load Tests.pdf
Leandro Melendez - Chihuahua Load Tests.pdfLeandro Melendez - Chihuahua Load Tests.pdf
Leandro Melendez - Chihuahua Load Tests.pdf
 
Rick Clymer - Incident Management.pdf
Rick Clymer - Incident Management.pdfRick Clymer - Incident Management.pdf
Rick Clymer - Incident Management.pdf
 
Robert Fornal - ChatGPT as a Testing Tool.pptx
Robert Fornal - ChatGPT as a Testing Tool.pptxRobert Fornal - ChatGPT as a Testing Tool.pptx
Robert Fornal - ChatGPT as a Testing Tool.pptx
 
Federico Toledo - Extra-functional testing.pdf
Federico Toledo - Extra-functional testing.pdfFederico Toledo - Extra-functional testing.pdf
Federico Toledo - Extra-functional testing.pdf
 
Andrew Knight - Managing the Test Data Nightmare.pptx
Andrew Knight - Managing the Test Data Nightmare.pptxAndrew Knight - Managing the Test Data Nightmare.pptx
Andrew Knight - Managing the Test Data Nightmare.pptx
 
Melissa Tondi - Automation We_re Doing it Wrong.pdf
Melissa Tondi - Automation We_re Doing it Wrong.pdfMelissa Tondi - Automation We_re Doing it Wrong.pdf
Melissa Tondi - Automation We_re Doing it Wrong.pdf
 
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdf
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdfJeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdf
Jeff Van Fleet and John Townsend - Transition from Testing to Leadership.pdf
 
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptx
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptxDesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptx
DesiradhaRam Gadde - Testers _ Testing in ChatGPT-AI world.pptx
 
Damian Synadinos - Word Smatter.pdf
Damian Synadinos - Word Smatter.pdfDamian Synadinos - Word Smatter.pdf
Damian Synadinos - Word Smatter.pdf
 
Lee Barnes - What Successful Test Automation is.pdf
Lee Barnes - What Successful Test Automation is.pdfLee Barnes - What Successful Test Automation is.pdf
Lee Barnes - What Successful Test Automation is.pdf
 
Jordan Powell - API Testing with Cypress.pptx
Jordan Powell - API Testing with Cypress.pptxJordan Powell - API Testing with Cypress.pptx
Jordan Powell - API Testing with Cypress.pptx
 
Carlos Kidman - Exploring AI Applications in Testing.pptx
Carlos Kidman - Exploring AI Applications in Testing.pptxCarlos Kidman - Exploring AI Applications in Testing.pptx
Carlos Kidman - Exploring AI Applications in Testing.pptx
 

Dernier

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 

Dernier (20)

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 

Apply TDD to SQL with .NET

  • 1. Hey, You Got Your TDD In My SQL DB! Jeff McKenzie @jeffreymckenzie mail@mcknz.com Good morning everyone – Thanks for being here to learn About SQL Server testing using TDD My name is Jeff McKenzie, and before we get started I'd like to tell you a little bit about myself – I like puppies, long walks on the beach… And I'm also a Principal Consultant At Cardinal Solutions – a little bit about Cardinal...
  • 2. Cloud Mobile Data Web We are an IT services firm With approximately 500 fulltime consultants In 7 different locations across the eastern region, Including a branch in Columbus – And we are hiring, so talk to me after Or get in touch if you are interested -- We have a strong focus in cloud technologies, As well as custom application development, DevOps, IoT, AR/VR, and data analytics.
  • 3. @jeffreymckenzie TDD Today we are going to learn more about TDD – How many of you have heard of TDD, know what it means, or tried it? [hands] How many use TDD on a fairly regular basis? [hands]
  • 4. @jeffreymckenzie How to apply TDD to SQL Server So My goal for today is to show you How to use TDD practices Specifically in SQL Server, Whether that's standalone SQL, Or the data layer in a larger application. ***
  • 5. @jeffreymckenzie TDD – the what 1 To realize that goal, we are first going to Define TDD, explain it, qualify it, To make sure we are all on the same page When we talk about what TDD is and is not. ***
  • 6. @jeffreymckenzie TDD – the why 2 A lot of us have heard about the practice of TDD But sometimes the actual reasons for doing it get lost or obscured. So we will examine the benefits of TDD. ***
  • 7. @jeffreymckenzie TDD – the how 3 Finally we will take a look at a specific example Of a real-life production scenario And demonstrate how to use TDD against SQL Server. ***
  • 8. @jeffreymckenzie I Don't Know. So one thing I'm not planning to do in this session Is try to convince you how often and how thoroughly you apply TDD, because I don't really have an answer. This is one of those software development topics that Tend to start religious wars, like, you know, Other enthralling topics like spaces vs tabs. On one side you have the TDD zealots… *** ========= https://upload.wikimedia.org/wikipedia/commons/7/7b/Jan_Steen_- _Argument_over_a_Card_Game_-_WGA21735.jpg Jan Steen [Public domain], via Wikimedia Commons
  • 9. @jeffreymckenzie All the Way Down Who say even your unit tests should have unit tests. On the other side are people who say TDD Is garbage, is considered harmful, *** ========= https://upload.wikimedia.org/wikipedia/commons/4/47/River_terrapin.jpg By Pelf at en.wikipedia [Public domain], via Wikimedia Commons
  • 10. @jeffreymckenzie Burn It With Fire. Promotes bad design, and should be completely done away with. Those are ideas and arguments you can explore on your own. All I can say is that I've used it, *** ========= https://upload.wikimedia.org/wikipedia/commons/c/cd/Rammsterin_Fla methrower.jpg By Kreepin Deth (Own work) [CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia Commons
  • 11. @jeffreymckenzie Works on My Box. Found some benefits with it, and generally have a feel For when it's valuable and when it's not. But all those concerns are offtopic for today – We will be focusing on the what, why, and how. *** ========= https://upload.wikimedia.org/wikipedia/commons/f/f5/Computer_MC80.3 x_CM5214.JPG By LutzBruno (Own work) [CC BY 4.0 (http://creativecommons.org/licenses/by/4.0)], via Wikimedia Commons
  • 12. @jeffreymckenzie Who Are You First, I'd like to get an idea of your technical background: How many would consider yourselves …application developers? …DBAs or primarily SQL developers? …QA or testing? Any roles I missed? *** ========= https://upload.wikimedia.org/wikipedia/commons/4/42/Townshend_sma shing_guitar.jpg By Heinrich Klaffs [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 13. @jeffreymckenzie Test-driven development was popularized in software development In the late 1990s as part of the Extreme Programming project, Which emerged as a set of technical practices designed to work with Agile Software Development. The specific technique of TDD was detailed in Kent Beck's 2002 book Test-Driven Development by Example. ========= https://www.amazon.com/Test-Driven-Development-Kent- Beck/dp/0321146530 https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_ Workshop_Mapping_XP.jpg By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 14. @jeffreymckenzie The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output. – Kent Beck In that book however, Beck claims merely to have re-discovered the technique. He cites what he calls an ancient book on programming (ancient in software development terms, which means late sixties/Early seventies), but references have been Discovered going back to the 50s. *** ========= https://www.amazon.com/Test-Driven-Development-Kent- Beck/dp/0321146530 https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_ Workshop_Mapping_XP.jpg By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 15. @jeffreymckenzie The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output. – Kent Beck Beck describes a process where the expected output of the program was manually created, and the programmer would work until the actual output matched the expected output, Which is pretty much what TDD is all about. *** ========= https://www.amazon.com/Test-Driven-Development-Kent- Beck/dp/0321146530 https://upload.wikimedia.org/wikipedia/commons/5/55/Kent_Beck_no_ Workshop_Mapping_XP.jpg By Improve It (Flickr: Kent Beck no Workshop Mapping XP.) [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 16. @jeffreymckenzie TDD – the what 1 We call this practice Test-Driven Because tests are written first, before any code. With a traditional approach, tests are created after, To verify what's already been coded. ***
  • 17. @jeffreymckenzie Don't know about you, but I find it helpful to have a visual of what I'm trying to learn. Here's a graphical depiction of the TDD process – Which is really two separate cycles: The test-driven development cycle, And the refactoring cycle. There are 3 steps for the first cycle: Make the test, make it fail, and make it work. *** ========= https://upload.wikimedia.org/wikipedia/commons/0/0b/TDD_Global_Life cycle.png By Xarawn (Own work) [CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia Commons
  • 18. @jeffreymckenzie Make the Test. First step is probably the hardest barrier to get over when learning and using TDD, and that is to create the test first, before writing any code. When we get requirements, we want to make something happen, And writing a test doesn't really feel like you're doing anything. I'll add another point about writing a test, *** ========= https://upload.wikimedia.org/wikipedia/commons/b/b2/V08383P339.jpg By Calspan Corporation, National Highway Traffic Safety Administration [Public domain], via Wikimedia Commons
  • 19. @jeffreymckenzie Make it simple. Which is to make it simple. A test shouldn't try to do too much. It should be relatively easy to create and execute. The tests we are talking about here are unit tests. There's a definition for unit test I like, Which says it's One specific requirement for One specific method. *** ========= Picture of easy button, by me.
  • 20. @jeffreymckenzie …a test that tests ONE specific requirement for ONE specific method. A Unit Test is… – James Bender This is from James Bender – just google James Bender And TDD, and you'll find a lot of great info. This definition really shows the difference between a unit test and any higher level test, such as integration or end-to-end testing. These higher-level tests are going to hit multiple methods, which makes it harder To verify individual requirements. A unit test should also be…. ***
  • 21. @jeffreymckenzie …fast …isolated …repeatable A Unit Test is… Fast. Ideally you want to run all of your tests as you are working, To know when you are done or have broken something. If your tests are simple, they are more likely to be fast. ***
  • 22. @jeffreymckenzie …fast …isolated …repeatable A Unit Test is… Your tests will also be faster If they are isolated – meaning you want to reduce Dependencies on other classes or methods. Testing methods in isolation also makes sure That you're targeting the right spot – If your test fails, you know Exactly where to look. ***
  • 23. @jeffreymckenzie …fast …isolated …repeatable A Unit Test is… Finally a test should be repeatable – So if the code being tested has not changed, The test result should be the same every time. Any setup or teardown activity should be handled within the test itself. There should be no manual steps required In between test runs. This again helps the test to run quickly. ***
  • 24. @jeffreymckenzie Let's try out a quick concrete example. So we have our easy button, and let's say We want to create a computer model of it. Our first requirement is… Create an easy button, ========= Picture of easy button, by me.
  • 25. @jeffreymckenzie Create an Easy Button… with a Click() method… returning “That was easy.” With a click method, Returning “That was easy.” ***
  • 26. @jeffreymckenzie public void Test_EasyButton_Click() { //Arrange //Act //Assert } Here's the start of our test – we'll call it Test Easy Button Click – and we're going to use What we call the triple A pattern: Arrange, Act, Assert. Let's set up the arrange part – This is where you do all of the setup Just prior to code execution.
  • 27. @jeffreymckenzie public void Test_EasyButton_Click() { //Arrange var button = new EasyButton.Button(); String expected = "That was easy."; //Act //Assert } This is C# but this would be similar to a test In a strongly typed language. Here we create an instance of the EasyButton, And also a variable called expected, Which holds the value of the output we expect. ***
  • 28. @jeffreymckenzie public void Test_EasyButton_Click() { //Arrange var button = new EasyButton.Button(); String expected = "That was easy."; //Act String actual = button.Click(); //Assert } Next we have the Act section – Here we do the actual code execution, And assign the output of the click method To a variable called actual. ***
  • 29. @jeffreymckenzie public void Test_EasyButton_Click() { //Arrange var button = new EasyButton.Button(); String expected = "That was easy."; //Act String actual = button.Click(); //Assert Assert.AreEqual(actual, expected); } Lastly we have our assert section. An assertion is a verification That our action executed the way we intended. In this case, our assertion is that the actual output of the click method is: That was Easy. This is a pretty simple test – We are testing just one thing. ***
  • 30. @jeffreymckenzie Make it fail. After you've written your simple test, You want to make sure it actually fails. If you write a passing test by mistake, Then you'll have no confidence that Your code really does what it's supposed to. Then, finally, write the code… *** ========= https://upload.wikimedia.org/wikipedia/commons/5/54/Hydrogen_balloo n_explosion.jpg By Maxim Bilovitskiy (Own work) [CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia Commons
  • 31. @jeffreymckenzie public void Test_EasyButton_Click() { //Arrange var button = new EasyButton.Button(); String expected = "That was easy."; //Act String actual = button.Click(); //Assert Assert.AreEqual(actual, expected); } So back to our test – is it going to pass? No – why not? Right, we haven't written the code yet, There's no EasyButton. Here's what I get when I attempt To run the test … ***
  • 32. @jeffreymckenzie It doesn't even compile. Tells me that EasyButton doesn't exist, Which is good because We haven't made it yet. ***
  • 33. @jeffreymckenzie Make it work. So we need to make the test work. The trick is to try to write as little code as possible. The idea of TDD is to satisfy all requirements With the least amount of work. The less code there is, the fewer things You have to go wrong. So let's write the implementation. *** ========= https://upload.wikimedia.org/wikipedia/commons/c/c4/Hillary_Clinton_% 2824007578223%29.jpgBy Gage Skidmore from Peoria, AZ, United States of America (Hillary Clinton) [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 34. @jeffreymckenzie public class Button { public String Click() { return "That was easy."; } } Pretty simple – We just create the class, Create the method, And return the output. ***
  • 35. @jeffreymckenzie So we re-run our test and we have success. We coded only what we needed to pass the test. If we code ahead and try to anticipate Additional requirements or functionality, we run the risk of coding too much, or adding code We don't need. ***
  • 36. @jeffreymckenzie Now we get to refactoring, which is simply rewriting code to make it better. After you have a few passing tests, You'll want to go back and make improvements. The nice thing about having TDD is you now Have a built-in test suite to verify that All of your changes still meet the requirements. If tests fail, you may need to fix code, Or you may need to update tests to match Your new design. *** ========= https://upload.wikimedia.org/wikipedia/commons/0/0b/TDD_Global_Life cycle.png By Xarawn (Own work) [CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0)], via Wikimedia Commons
  • 37. @jeffreymckenzie TDD – the why 2 Now that we have a general idea of what TDD is, Let's examine why we might want want to use it – What are the benefits it provides. After all, there is extra work involved – It simply takes more time to write a test For every requirement, and to continually run And update those tests. It's like having a second code base. ***
  • 38. @jeffreymckenzie …quality …design …discipline …documentation Use TDD for… The first benefit of TDD is that it improves code quality. If you are diligent in your testing effort, And have a unit test for the classes and methods That make up each requirement, you will have baked in Verification of your application's functionality. Because you have been checking for correctness As you go, the code is better, and has less defects.***
  • 39. @jeffreymckenzie …quality …design …discipline …documentation Use TDD for… Another area TDD can assist is in the design And organization of your code. Because you writing The least possible code, and tests first, it forces you To think in advance – as in our EasyButton example: We had to think about the implementation we wanted When writing the test.
  • 40. @jeffreymckenzie …quality …design …discipline …documentation Use TDD for… TDD can also improve testing discipline. I know from experience that it's difficult to write All the tests you need when you do it after the code. And often it just doesn't happen because you Run out of time. If you write the test first, You'll rarely be in a place where you have untested code.
  • 41. @jeffreymckenzie …quality …design …discipline …documentation Use TDD for… If you are disciplined in writing tests, Your test suites become in essence a form Of documentation for your code – Each test explains what a part of the application does. Written documentation quickly gets out of date, But if you have a passing test, you know the Code is still used and working as intended. But my number one reason for using TDD is That it gives you confidence to make changes. ***
  • 42. @jeffreymckenzie …confidence to change code details and design – and at the same time – retain existing functionality. Use TDD for… You are continually rerunning old tests, so you'll know immediately if something's broken. I think everyone's had an experience working with a code base that people are afraid to touch. Which means at release time, everyone in the company Is staying late to click on buttons, hoping That nothing got broken since the last deployment. ***
  • 43. @jeffreymckenzie What Have I Done. You know, everyone lives in fear of changes to the application, And the managers want to know exactly what changed That caused this feature or that feature to break, And why didn't we know that would happen. So TDD can help prevent these types of problems. *** ========= https://upload.wikimedia.org/wikipedia/commons/7/7e/US_Navy_03022 8-N-4953E- 001_Aviation_Ordnanceman_2nd_Class_Kyle_Marcinowski_conducts_ a_quality_assurance_check_on_a_GBU- 31_Joint_Direct_Attack_Munition_%28JDAM%29.jpg By U.S. Navy photo by Photographer's Mate 3rd Class Danny Ewing Jr. [Public domain], via Wikimedia Commons
  • 44. @jeffreymckenzie TDD – the how 3 So that brings us to the heart of today's session, Which is how to bring the benefits of TDD To your SQL Server database. This brings up the question How do we, and how should we, test our data? ***
  • 45. @jeffreymckenzie How Do We Test Our Data? What are some ways you approach data testing? I think that sometimes when testing an application, our first inclination is simply to skip data all together, Because the database is a external dependency that Slows down testing, and can cause unrelated issues.
  • 46. @jeffreymckenzie Isolation Remember we talked about isolation as being An important part of a unit test? If we are writing our application, It's often best practice to isolate our code From the data because it's an outside dependency. But that presents a problem -- we have database objects As part of our code base, but not testing them Along with the application. ***
  • 47. @jeffreymckenzie Manual Queries One common way is to manually query the database. We write a query or stored proc, run it, and verify its correctness. And that works to a degree, but eventually you have the same problem – as your data model changes, How can you tell you're still getting proper data? You have to go back and manually retest, Which often you don't have time for. Another method is to build in automation Through integration tests. ***
  • 48. @jeffreymckenzie Automated Integration Tests These kinds of tests are certainly a step up From manual queries, and can be built in As part of a continuous integration process To make sure the application works when combined With its persistence layer. One problem with this, However, is that these tests are designed to test The application itself, and the data only indirectly. Could be that a integration test only succeeds Coincidentally, and that the underlying SQL Has unidentified problems. ***
  • 49. @jeffreymckenzie When Do We Test Our Data? In addition to how we test, we need to ask When we test data. We don't need to test Everything. For example, in an application, We probably don't need to test That an object property has the value we assigned it. We want to make sure we are testing functionality, And not the underlying framework or language. We probably don't need to test an insert statement. We probably don't need to test our ORM. ***
  • 50. @jeffreymckenzie When Do We Test Our Data? What is useful to test is complex behavior or logic. Although stored procedures are kind of out of fashion, They are still a great choice when doing intensive Operations within multiple database objects. Wouldn't it be nice if we could build in The same kind of direct and continuous Unit testing of our SQL, the way we do For our application code? Well, it just so happens that we can! ***
  • 51. @jeffreymckenzie There is a unit test framework for SQL Server Called T SQL T, which allows you to take a TDD Approach to writing SQL. It's installed entirely within SQL server. It's open source, with the source code freely Available on GitHub. ***
  • 52. @jeffreymckenzie The TSQLT repository is on the tSQLt-org GitHub account, And you can get it from their web site… ***
  • 53. @jeffreymckenzie On the download page at tSQLt.org The whole framework clocks in zipped at 84K, So that should pull down pretty fast… ***
  • 54. @jeffreymckenzie What we're going to walk through Is a real world production feature I implemented In SQL Server using the tSQLt framework. In the interest of protecting client confidentiality, however, I have changed almost everything About the project, including the industry, The client, and the product – all that remains Is the business problem we need to solve. So I'd like to introduce you to our client… ***
  • 55. @jeffreymckenzie Does anyone know this guy? Ron was probably best known for being the director Of the Parks and Rec department in Pawnee Indiana, For 6 years. What's less well known, however, is that after retiring from a long and illustrious career as a civil servant, Ron Swanson decided to purchase and run his favorite store… called… anyone? *** ========= https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo d_and_Stuff_2.png/revision/latest?cb=20120730155117 http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
  • 56. @jeffreymckenzie Food and Stuff. Does anyone remember this place? Food and Stuff is located at 729 Glenmore Blvd in Pawnee, Indiana. Ron buys all of his groceries there, and describes it as: "a discount food outlet equidistant from my home and my work". According to Mr. Swanson, They have a broad and diverse catalog of items, Including household paints… ========= http://parksandrecreation.wikia.com/wiki/Food_and_Stuff https://vignette.wikia.nocookie.net/parksandrecreation/images/1/15/Foo d_and_Stuff.png/revision/latest?cb=20120730155051
  • 57. @jeffreymckenzie garden supplies… ========= https://upload.wikimedia.org/wikipedia/commons/b/bd/EWM_paint_2007 .jpg By Tom Murphy VII (Taken by uploader (user:brighterorange)) [Public domain], via Wikimedia Commons
  • 59. @jeffreymckenzie buckets of different sizes….. ========= https://upload.wikimedia.org/wikipedia/commons/6/65/Pvc_cevi.jpg Mm.zaletel from sl [GFDL (http://www.gnu.org/copyleft/fdl.html)], via Wikimedia Commons
  • 61. @jeffreymckenzie shelving units …. ========= https://upload.wikimedia.org/wikipedia/commons/4/47/Okinawa_Aquariu m.jpg By Jordy Meow (Own work) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
  • 62. @jeffreymckenzie And lead-based paints. ========= https://upload.wikimedia.org/wikipedia/commons/0/00/KAST_kast_desig ned_by_Marcel_Douwe_Dekker_in_1992.jpg By Marcel Douwe Dekker (Own work) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0) or GFDL (http://www.gnu.org/copyleft/fdl.html)], via Wikimedia Commons
  • 63. @jeffreymckenzie And it's not only products – They perform various services, Such as engine repair… ========= https://upload.wikimedia.org/wikipedia/commons/6/69/LeadPaint1.JPG By Thester11 (Own work) [CC BY 3.0 (http://creativecommons.org/licenses/by/3.0)], via Wikimedia Commons
  • 67. @jeffreymckenzie So Ron's been doing pretty well, and business is strong. He's got a point of sale system he's been using… *** ========= https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo d_and_Stuff_2.png/revision/latest?cb=20120730155117 http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
  • 68. @jeffreymckenzie Yeah, So no one ever accused Ron of being a slave to technology. He's also using this system to take customer orders, track inventory, manage his books, and all that good stuff. But Ron has a few problems. *** ========= https://upload.wikimedia.org/wikipedia/commons/1/19/Zenith_Z- 19_Terminal.jpg By Jamie Cox from Melbourne, USA (Zenith Z-19 Terminal Uploaded by Mewtu) [CC BY 2.0 (http://creativecommons.org/licenses/by/2.0)], via Wikimedia Commons
  • 69. @jeffreymckenzie First, he's got about 12,000,000 new customers in his database over the last 12 months, but the entire city of Pawnee has only about 80,000 people. ========= http://1.bp.blogspot.com/- j9CbeOiNMLY/Vdr4b55bzcI/AAAAAAAAwOM/A_fjFcEBSJo/s1600/Paw nee.jpg https://swimnova.com/map-of-pawnee-indiana.html
  • 70. @jeffreymckenzie When he runs customer reports, he keeps seeing the same names appear many times. The point of sale system also allows Ron to mail promotional materials to his customers, to remind them when there are sales, or when new items get in stock, like almond butter…. ========= https://upload.wikimedia.org/wikipedia/commons/3/3a/All_work_and_no _play_makes_Jack_a_dull_boy_%28The_Shining%29_%28795773850 0%29.jpg By Marcel Oosterwijk from Amsterdam, The Netherlands [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)], via Wikimedia Commons
  • 71. @jeffreymckenzie Or cattle prods…. ========= https://upload.wikimedia.org/wikipedia/commons/c/cf/Barney_butter_Jar s.jpg By Venomarv (Own work) [CC BY 1.0 (http://creativecommons.org/licenses/by/1.0)], via Wikimedia Commons
  • 72. @jeffreymckenzie But he's gotten complaints that his customers are getting 4 or five copies of his newsletter, and he's spending a fortune on postage. So what is Ron's problem? What's the problem with his system, and specifically his database? *** ========= https://upload.wikimedia.org/wikipedia/commons/d/d3/Electric_cattle_pr od.jpg Author Unknown
  • 73. @jeffreymckenzie Duplicate Data Yes, it's duplicate data. Why might he have some duplication? [doesn't check for existing customers] [no customer search] [no DB cleaning] So Ron has asked us, all of us here, To solve his problem, and we, collectively, Are known as Apps N Stuff. ***
  • 74. @jeffreymckenzie Apps 'N Stuff Ron wants us to fix his duplicate data problem. He has 2 basic requirements for us. First, he doesn't want to have to check For duplicates up front.
  • 75. @jeffreymckenzie 1. No Check at Order Time 2. Self-Service Cleanup He really doesn't want the UI for his order process to change (you know, he likes things the way they are) And he's worried that searching up front Will slow the order, and that will make His customers unhappy. Second, he wants to clean up duplicates himself.
  • 76. @jeffreymckenzie 1. No Check at Order Time 2. Self-Service Cleanup He doesn't want Apps 'N Stuff to come out Every week or so and clean up the data. He also doesn't want to have some Batch process running in the background To automatically clean things up, Because well, he just doesn't trust it.
  • 77. @jeffreymckenzie Food And Stuff Solution So we have to build a solution That allows Ron to access the data, Find duplicates, And merge them together, into a single record. The first part of the solution is a UI component,
  • 78. @jeffreymckenzie The actual screen that lets Ron find duplicates. The second part of the solution Is the backend database -- *** ========= https://upload.wikimedia.org/wikipedia/commons/e/e0/Browser_ballonic on2.svg By pixelbuddha [CC BY 3.0 (http://creativecommons.org/licenses/by/3.0)], via Wikimedia Commons
  • 79. @jeffreymckenzie This is where we are going to focus Our effort today. We are going to write a stored procedure That takes 2 duplicate customer records, *** ========= https://commons.wikimedia.org/wiki/File:Applications-database.svg By dracos (http://dracos.deviantart.com/#/d2y5ele) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
  • 80. @jeffreymckenzie Ron Swanson Ron Swanson Ronald Swanson And merges them into a single customer. The UI is going to take care of finding the customers, So all the proc has to do is take the two records And combine them. But there are complications. We also have to make sure that the order history For each customer is combined as well. Let's take a look at the data model. *** ========= https://upload.wikimedia.org/wikipedia/commons/4/40/Data-transfer.svg By RRZEicons (Own work) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
  • 81. This is an extremely simplified model – I would not recommend this for a production DB. Customer = first name, last name, loyalty id OrderDetail = item purchased Order = joins Customer with an Order So once we are done, we should be left With a single customer who has all the orders, And the duplicate customer deleted. ***
  • 82. @jeffreymckenzie Before we start writing our procedure, however, We need to get our TDD framework set up. The tSQLt framework is very small, and in fact, Contains only 6 files. *** ***
  • 83. @jeffreymckenzie There's a text file that explains the setup, The license and release notes, and some example tests. To install tSQLt you need to run the Set CLR Enabled script – There are some compiled assemblies that tSQLt uses – And then execute the tSqlt.class script, Which will install all of the DB objects That the framework needs. ***
  • 84. @jeffreymckenzie And what this does is install all Of the tables, procedures, and functions In its own schema, the tSQLt schema, So it's logically separated from The dbo schema or Anything else you've created. Now that we have tSQLt installed, We can start working on our tests. ***
  • 85. @jeffreymckenzie 1. Create Test Install Script 2. Create Test Run Script So we are going to do two things – First, create a SQL Script that installs our tests in the database, And second, create a SQL Script that runs our tests. Let's look at the install script first. ***
  • 86. @jeffreymckenzie USE Food_And_Stuff GO EXEC tSQLt.NewTestClass @ClassName = N'FAS_Tests' GO ------------- BEGIN [FAS_Tests].[InsertTestData] ---------- CREATE PROC FAS_Tests.InsertTestData AS BEGIN END ------------- END [FAS_Tests].[InsertTestData] ------------ First, we're going to make sure that everything Gets installed in the Food_And_Stuff database With the use statement. To execute a tSQLt statement, you type the Schema name, followed by the command you want. Here we use the tSQLt New Test Class command To create our test class – what this actually does Is create a new schema in the database we can Attach our tests to…
  • 87. @jeffreymckenzie USE Food_And_Stuff GO EXEC tSQLt.NewTestClass @ClassName = N'FAS_Tests' GO ------------- BEGIN [FAS_Tests].[InsertTestData] ---------- CREATE PROC FAS_Tests.InsertTestData AS BEGIN END ------------- END [FAS_Tests].[InsertTestData] ------------ again, this provides A clear separation between our actual code, Our tests, and the tSQLt framework. One note of warning – this will delete any test class with that name, Without any warning (so script everything!) Next we will create a procedure that inserts The data we need for our tests. First we'll create data for our customer table.
  • 88. @jeffreymckenzie ---------------- BEGIN CUSTOMERS ------------------- DECLARE @RonaldId INT = 1, @RonId INT = 2 INSERT INTO dbo.Customer( CustomerId, FirstName, LastName, LoyaltyId ) VALUES(@RonaldId, 'Ronald', 'Swanson', 1234) INSERT INTO dbo.Customer( CustomerId, FirstName, LastName, LoyaltyId ) VALUES(@RonId, 'Ron', 'Swanson', 1234) ---------------- END CUSTOMERS --------------------- We want to test that a duplicate gets eliminated, So we'll need two customers. We're going to say Ron Swanson is the customer We want to keep, and Ronald Swanson is the duplicate So we'll insert customer ids (Ron is number 2), The first name and last name, and finally the loyalty ID. The loyalty ID is what tracks who gets what discounts --
  • 89. @jeffreymckenzie ---------------- BEGIN CUSTOMERS ------------------- DECLARE @RonaldId INT = 1, @RonId INT = 2 INSERT INTO dbo.Customer( CustomerId, FirstName, LastName, LoyaltyId ) VALUES(@RonaldId, 'Ronald', 'Swanson', 1234) INSERT INTO dbo.Customer( CustomerId, FirstName, LastName, LoyaltyId ) VALUES(@RonId, 'Ron', 'Swanson', 1234) ---------------- END CUSTOMERS --------------------- You know, it's that card on your keychain That says – yes, please take all of my personal Information and record my purchases so You can wrap it all up in a nice bow to sell To a data broker who can in turn sell it To an advertiser so they can milk me for more cash. But I'm not cynical or anything. But thank goodness Food And Stuff has this Loyalty ID, because otherwise we'd have no way To uniquely identify customers.
  • 90. @jeffreymckenzie ---------------- BEGIN ORDERS ---------------------- DECLARE @RonaldOrderId INT = 11, @RonOrderId INT = 22 -- customer 1 order INSERT INTO [dbo].[Order](OrderId, CustomerId) VALUES(@RonaldOrderId, @RonaldId) -- customer 2 order INSERT INTO [dbo].[Order](OrderId, CustomerId) VALUES(@RonOrderId, @RonId) ---------------- END ORDERS ------------------------ We'll do the same for orders, Creating an order ID for both Ron and Ronald – Again, at the end of this process, Ron should have 2 orders under his name.
  • 91. @jeffreymckenzie ---------------- BEGIN ORDER DETAIL ---------------- DECLARE @RonaldDetailId INT = 111 DECLARE @RonDetailId INT = 222 INSERT INTO [dbo].[OrderDetail](OrderDetailId, OrderId, ItemName) VALUES(@RonaldDetailId, @RonaldOrderId, 'T-Bone Steaks: Val-U 20 Pack') INSERT INTO [dbo].[OrderDetail](OrderDetailId, OrderId, ItemName) VALUES(@RonaldDetailId, @RonaldOrderId, 'Bacon Strips: Val-U 100 Pack') ---------------- END ORDER DETAIL ------------------- And finally for order details. We can see here that Ronald bought A Value pack of 20 T-Bone steaks, And Ron bought a Value pack Of 100 bacon strips. Clearly this is the same person.
  • 92. @jeffreymckenzie Fakes / Mocks For the next part we need to talk about The concept of faking or mocking in tests. This is all part of test isolation that I mentioned before. If the particular method we are testing has to make a database Or webservice call, we can simply create A fake or mock of that call to keep our tests Simple and focused. ***
  • 93. @jeffreymckenzie public class Button { public String Click() { return "That was easy."; } } Let's go back to our EasyButton example. Remember we implemented our click method? Let's say instead of returning a hardcoded string, We want to look up the quote from a service. So let's do the replacement. ***
  • 94. @jeffreymckenzie public class Button { public String Click(MessageService) { return MessageService.Get(); } } I'm using a little pseudocode here just to Make things a little clearer. Now our unit test will actually be testing The Click method and the service – This will take longer, and could result In failures from the service that are Unrelated to our actual click method. So what we can do is create a fake Of our Service call. ***
  • 95. @jeffreymckenzie public class FakeMessageService { public String Get() { return “When I eat, it is the food that is scared. – Ron Swanson"; } } Instead of passing a real instance Of the Message Service, we will create A fake version that returns the same Message every time. This makes sure we get a result From the click method, and also That the message service will never fail. ***
  • 96. @jeffreymckenzie ------------- BEGIN [FAS_Tests].[Setup] ------------------- CREATE PROC FAS_Tests.Setup AS BEGIN --create fakes for tests against tables EXEC tSQLt.FakeTable 'dbo.OrderDetail' EXEC tSQLt.FakeTable 'dbo.Order' EXEC tSQLt.FakeTable 'dbo.Customer' -- populate fake tables EXEC FAS_Tests.InsertTestData END GO ------------- END [FAS_Tests].[Setup] --------------------- In the next part of the install script, We are going to create the setup procedure. If you have a procedure called Setup In your test class, or schema, tSQLt Will run that proc before every test. We can use that to our advantage And do some setup work that every test will need. First thing we do is create some Fakes….
  • 97. @jeffreymckenzie ------------- BEGIN [FAS_Tests].[Setup] ------------------- CREATE PROC FAS_Tests.Setup AS BEGIN --create fakes for tests against tables EXEC tSQLt.FakeTable 'dbo.OrderDetail' EXEC tSQLt.FakeTable 'dbo.Order' EXEC tSQLt.FakeTable 'dbo.Customer' -- populate fake tables EXEC FAS_Tests.InsertTestData END GO ------------- END [FAS_Tests].[Setup] --------------------- For the tables we want to test. The fake table command in tSQLt replaces the actual table with an empty copy That has no constraints. That way it's isolated from the rest of the database And we can test operations on that table alone. After we create the fakes, we can use the proc We created before to insert test data about Ronald and Ron ***
  • 98. @jeffreymckenzie Here is our customer table, With both Ron and Ronald in there…***
  • 99. @jeffreymckenzie Then the Order detail table, With its meat extravaganza… ***
  • 100. @jeffreymckenzie And finally the Order table, Which matches the customer to the particular order. Note that this only happens when a test is run – before or after a test These tables have whatever data Was in them originally. ***
  • 101. @jeffreymckenzie ----------- BEGIN GivenMerge-ThenCustomerIsCorrect -------------- CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomersIsCorrect] AS BEGIN --Arrange DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --CustomerId we want to keep DECLARE @ExpectedRonFirstName NVARCHAR(50) = Now we're ready to create our first test. tSQLt requires that every test be a procedure That starts with the word TEST. What we want to accomplish in this test Is to do the merge, then ensure that data In the Customers Table is correct. So I've started the arrange section here. Remember that when this test starts, All of the tables will be populated… ***
  • 102. @jeffreymckenzie ----------- BEGIN GivenMerge-ThenCustomerIsCorrect -------------- CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect] AS BEGIN --Arrange DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --CustomerId we want to keep DECLARE @ExpectedRonFirstName NVARCHAR(50) = ..because the setup has already run. So to set the ExpectedRonFirstName variable, What are a couple of ways we could do that? ***
  • 103. @jeffreymckenzie ----------- BEGIN GivenMerge-ThenCustomerIsCorrect -------------- CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect] AS BEGIN --Arrange DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --CustomerId we want to keep DECLARE @ExpectedRonFirstName NVARCHAR(50) = So to set the ExpectedRonFirstName variable, What are a couple of ways we could do that? Hardcode name – Select based on ID -- ***
  • 104. @jeffreymckenzie ----------- BEGIN GivenMerge-ThenCustomerIsCorrect -------------- CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect] AS BEGIN --Arrange DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --CustomerId we want to keep DECLARE @ExpectedRonFirstName NVARCHAR(50) = ( SELECT FirstName FROM dbo.Customer WHERE CustomerId = @RonId ) If we select the value based on the ID, That allows us to test other IDs without Having to change a hardcoded string. ***
  • 105. @jeffreymckenzie ----------- BEGIN GivenMerge-ThenCustomerIsCorrect -------------- CREATE PROC FAS_Tests.[test GivenMerge-ThenCustomerIsCorrect] AS BEGIN --Arrange DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --CustomerId we want to keep DECLARE @ExpectedRonFirstName NVARCHAR(50) = ( SELECT FirstName FROM dbo.Customer WHERE CustomerId = @RonId ) If we select the value based on the ID, That allows us to test other IDs without Having to change a hardcoded string. ***
  • 106. @jeffreymckenzie DECLARE @ExpectedRonFirstName NVARCHAR(50) = ( SELECT FirstName FROM dbo.Customer WHERE CustomerId = @RonId ) DECLARE @ExpectedRonLastName NVARCHAR(50)= ( SELECT LastName FROM dbo.Customer WHERE CustomerId = @RonId ) DECLARE @ExpectedLoyaltyId INT = ( SELECT LoyaltyId FROM dbo.Customer WHERE CustomerId = @RonId ) Now we can do the same for all of the other Values in the Customer table. Now, how do we do the actual comparison Between the expected values and the actual values? We can do so through a table compare… ***
  • 107. @jeffreymckenzie CREATE TABLE FAS_Tests.Expected( CustomerId INT NOT NULL, FirstName NVARCHAR(50) NOT NULL, LastName NVARCHAR(50) NOT NULL, LoyaltyId INT NOT NULL ) -only Ron should exist INSERT INTO FAS_Tests.Expected( CustomerId, FirstName, LastName, LoyaltyId) VALUES(@RonId, @ExpectedRonFirstName, , @ExpectedRonLastName , @ExpectedLoyaltyId ) First we create an Expected table Inside our FAS_Tests schema, again, So it's separated from the application code, And then we insert the expected values Into that table, because we should only see one record when the merge is complete. That's it for the arrange section – everything Is set up to see if our test is correct Once the test is executed. Let's finish the test: ***
  • 108. @jeffreymckenzie --Act EXEC dbo.MergeCustomer @DuplicateCustomer = @RonaldId, @CustomerToKeep = @RonId --Assert EXEC tSQLt.AssertEqualsTable @Expected = N'FAS_Tests.Expected', @Actual = N'dbo.Customer' @FailMsg = N'Customer table has incorrect data.' END GO -------- END GivenMergeCustomers-ThenCustomerIsCorrect ------------ For the Act section, we will execute The MergeCustomer stored procedure. For our assert section, we are going to use The tSQLt AssertEqualsTable assertion – This determines whether or not two tables Have the same data – we are comparing The expected table in our test schema With the actual Customer table, Which in this case is our Fake table.
  • 109. @jeffreymckenzie 1. Create Test Install Script 2. Create Test Run Script So we will run our Test Install Script to create our test class with the latest tests. In order to run this test, We will need to start on our test run script. It's pretty simple. ***
  • 110. @jeffreymckenzie USE Food_And_Stuff /* EXEC tSQLt.RunAll GO EXEC tSQLt.Run N'FAS_Tests' GO */ EXEC tSQLt.Run N'FAS_Tests.[test GivenMergeCustomers-ThenCustomerIsCorrect]' GO There are three ways to run a test in tSQLt – First is the RunAll command, which runs all tests In all test classes. The second is the Run command with a class name, Which will run all tests in that test class. Finally you can call the Run command with A single test name, which will run only that class. [ASK] So if we run our test, what's going to happen? ***
  • 111. @jeffreymckenzie (0 row(s) affected) [FAS_Tests].[test GivenMergeCustomers...] failed: (Error) Could not find stored procedure 'dbo.MergeCustomer'.[16,62]{MergeCustomer,49} +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result| +--+--------------------------------+-------+------+ |1 |[FAS_Tests].[test GivenMerge...]| 236|Error | ------------------------------------------------------------------- Msg 50000, Level 16, State 10, Line 1: Test Case Summary: 1 test case(s) executed, 0 succeeded, 0 failed, 1 errored. ------------------------------------------------------------------- Here's the output – tSQLt shows us The actual error, that the MergeCustomer Stored proc can't be found, Then shows us the test summary, including The name of the test, the duration, And the result. Because it's red, we know Immediately that it failed.
  • 112. @jeffreymckenzie So if this is our Customer table, And we want to eliminate the Ronald record, What's the least amount of effort we can do To get this test to pass? ***
  • 113. @jeffreymckenzie USE Food_And_Stuff GO CREATE PROCEDURE [dbo].[MergeCustomer] @DuplicateCustomer INT, @CustomerToKeep INT AS BEGIN END GO [delete duplicate]
  • 114. @jeffreymckenzie USE Food_And_Stuff GO CREATE PROCEDURE [dbo].[MergeCustomer] @DuplicateCustomer INT, @CustomerToKeep INT AS BEGIN DELETE dbo.Customer WHERE CustomerId = @DuplicateCustomer END GO Yep, that's right – let's Run our test again….
  • 115. @jeffreymckenzie (1 row(s) affected) +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result | +--+--------------------------------+-------+-------+ |1 |[FAS_Tests].[test GivenMerge...]| 54|Success| ------------------------------------------------------------------- Test Case Summary: 1 test case(s) executed, 1 succeeded, 0 failed, 0 errored. ------------------------------------------------------------------- Now our test is passing. Let's write our next test, This time for the order table.
  • 116. @jeffreymckenzie This is a little different – Remember we want to keep all of the order history, so what should we Expect the order table at the bottom To look like once the merge is complete? [CustomerId should be two for both orders] Right, so let's write a test for that -- ***
  • 117. @jeffreymckenzie --------- BEGIN GivenMergeCustomers-ThenOrderIsCorrect ------------ CREATE PROC FAS_Tests.[test GivenMergeCustomers-ThenOrderIsCorrect] AS BEGIN --Assert DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 --Customer Id we want to keep CREATE TABLE FAS_Tests.Expected( OrderId INT NOT NULL, CustomerId INT NOT NULL ) We will need to write the test a little differently For this one – for the customer test, We only needed one record, so we could Insert one record into the expected table. Here, we could have any number of orders Between the two customers – So how should we fill the expected table here? ***
  • 118. @jeffreymckenzie CREATE TABLE FAS_Tests.Expected( OrderId INT NOT NULL, CustomerId INT NOT NULL ) --only orders for Ron (CustomerId 2) should exist INSERT INTO FAS_Tests.Expected( OrderId, CustomerId ) SELECT OrderId, @RonId FROM dbo.[Order] WHERE CustomerId = @RonaldId OR CustomerId = @RonId Essentially what we are doing here Is selecting every record in the order table For both customers, and inserting The order id, as well as the customerId We want to keep. Let's finish with the act and assert ***
  • 119. @jeffreymckenzie --Act EXEC dbo.MergeCustomer @DuplicateCustomer = @RonaldId, @CustomerToKeep = @RonId --Assert EXEC tSQLt.AssertEqualsTable @Expected = N'FAS_Tests.Expected', @Actual = N'dbo.Order' @FailMsg = N'Order table has incorrect data.' END GO -------- END GivenMergeCustomers-ThenOrderIsCorrect ------------ This is the same act and arrange as the last test, Except we are now checking the Order table. Let’s add our new test to the script… ***
  • 120. @jeffreymckenzie USE Food_And_Stuff EXEC tSQLt.Run N'FAS_Tests.[test GivenMergeCustomers-ThenCustomerIsCorrect]’ GO EXEC tSQLt.Run N'FAS_Tests.[test GivenMergeCustomers-ThenOrderIsCorrect]’ GO Now we will run both to make sure The previous test still passes. ***
  • 121. @jeffreymckenzie +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result | +--+----------------------------------+-------+-------+ |1 |[FAS_Tests].[test Given...Customer| 37|Success| |2 |[FAS_Tests].[test Given...Order | 33|Failure| ------------------------------------------------------------------- Msg 50000, Level 16, State 10, Line 7, Test Case Summary: 2 test case(s) executed, 1 succeeded, 1 failed, 0 errored. ------------------------------------------------------------------- So our customer test is passing, But our order test is not – which is good Because we haven’t written the code yet. When we are using the AssertEqualsTable Assertion, we get an additional error message… ***
  • 122. @jeffreymckenzie (1 row(s) affected) [FAS_Tests].[test GivenMergeCustomers-ThenOrderIsCorrect] failed: (Failure) Order table has incorrect data. |_m_|OrderId|CustomerId| +---+-------+----------+ |< |11 |2 | |= |22 |2 | |> |11 |1 | This graphical table shows us Exactly how the data is incorrect A less than sign means that the record Is in the expected table but not the actual table – The greater than sign means the record Is in the actual table but not the expected table, And the equals sign means it’s in both tables. This output can help you troubleshoot data issues. ***
  • 123. @jeffreymckenzie So now we want to make our order table Have all the orders for Ronald and Ron Belong to Ron – what’s the least amount Of code we need to accomplish this? [UPDATE CustomerId column] So let’s update our procedure…. ***
  • 124. @jeffreymckenzie CREATE PROCEDURE [dbo].[MergeCustomer] @DuplicateCustomer INT, @CustomerToKeep INT AS BEGIN DELETE dbo.Customer WHERE CustomerId = @DuplicateCustomer UPDATE dbo.[Order] SET CustomerId = @CustomerToKeep WHERE CustomerId = @DuplicateCustomer OR CustomerId = @CustomerToKeep END GO We’ve added our update statement, And we will run our tests again ***…
  • 125. @jeffreymckenzie (1 row(s) affected) +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result | +--+----------------------------------------------+-------+-------+ |1 |[FAS_Tests].[test GivenMerge...Customer] | 37|Success| |2 |[FAS_Tests].[test GivenMerge...Order] | 40|Success| ------------------------------------------------------------------- Test Case Summary: 2 test case(s) executed, 2 succeeded, 0 failed, 0 errored. ------------------------------------------------------------------- And now both are passing. ***
  • 126. @jeffreymckenzie Now because OrderDetail is tied to Order, OrderDetail will stay the same, So we don’t need a test for that, Because we are not performing any action On that table. Our tests are passing, so let’s try this On the live table – here’s our script … ***
  • 127. @jeffreymckenzie USE Food_And_Stuff GO BEGIN TRAN DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 /* Customer Id we want to keep */ EXEC FAS_Tests.InsertTestData EXEC dbo.MergeCustomer @DuplicateCustomer = @RonaldId, @CustomerToKeep = @RonId SELECT * FROM dbo.Customer SELECT * FROM dbo.[Order] SELECT * FROM dbo.OrderDetail ROLLBACK TRAN GO We are going to run this in a transaction So we can reset the tables and run it repeatedly. First we have our regular customer IDs for Ronald and Ron. Then we run our insert data procedure, Execute the merge procedure, Then do some selects to see What the data looks like…. ***
  • 128. @jeffreymckenzie Msg 547, Level 16, State 0 Procedure MergeCustomer, Line 7 [Batch Start Line 2] The DELETE statement conflicted with the REFERENCE constraint "FK_Order_Customer_CustomerId". The conflict occurred in database "Food_And_Stuff", table "dbo.Order", column 'CustomerId’. The statement has been terminated. And we have an error – What’s going on here? [DELETED a customer record still attached to an Order.] Remember I said when you create A fake table in tSQLt it creates A blank copy without restraints? We didn’t get this error in our test Because we had no constraints. ***
  • 129. @jeffreymckenzie ------------- BEGIN [FAS_Tests].[Setup] ------------------- CREATE PROC FAS_Tests.Setup AS BEGIN --create fakes for tests against tables EXEC tSQLt.FakeTable 'dbo.OrderDetail' EXEC tSQLt.FakeTable 'dbo.Order' EXEC tSQLt.FakeTable 'dbo.Customer’ EXEC tSQLt.ApplyConstraint N'dbo.Order', N'FK_Order_Customer_CustomerId' -- populate fake tables EXEC FAS_Tests.InsertTestData END GO ------------- END [FAS_Tests].[Setup] --------------------- Fortunately we have a way To add constraints to our tests, Using the tSQLt.ApplyConstraint command. After we create our fake table, all Constraints are removed, but we can then Apply individual constraints using the Table name and constraint name – here We are applying the foreign key constraint Between the Order and Customer tables. ***
  • 130. @jeffreymckenzie [FAS_Tests].[test GivenMerge...CustomerIsCorrect] failed: (Error) DELETE statement conflicted with "FK_Order_Customer_CustomerId". The conflict occurred in database "Food_And_Stuff", table "dbo.Order", column 'CustomerId'.[16,0]{MergeCustomer,7} +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result| +--+--------------------------------+-------+------+ |1 |[FAS_Tests].[test GivenMerge...]| 236|Error | ------------------------------------------------------------------- Msg 50000, Level 16, State 10, Line 1: Test Case Summary: 1 test case(s) executed, 0 succeeded, 0 failed, 1 errored. ------------------------------------------------------------------- When we run the test again, We get the same error we did when running live. So we now have a failing test that we need to fix. Let’s take a look at our MergeCustomer procedure… ***
  • 131. @jeffreymckenzie CREATE PROCEDURE [dbo].[MergeCustomer] @DuplicateCustomer INT, @CustomerToKeep INT AS BEGIN DELETE dbo.Customer WHERE CustomerId = @DuplicateCustomer UPDATE dbo.[Order] SET CustomerId = @CustomerToKeep WHERE CustomerId = @DuplicateCustomer OR CustomerId = @CustomerToKeep END GO Again , what’s the simplest change we can make To get our test to pass? [flip the statements…] ***
  • 132. @jeffreymckenzie CREATE PROCEDURE [dbo].[MergeCustomer] @DuplicateCustomer INT, @CustomerToKeep INT AS BEGIN UPDATE dbo.[Order] SET CustomerId = @CustomerToKeep WHERE CustomerId = @DuplicateCustomer OR CustomerId = @CustomerToKeep DELETE dbo.Customer WHERE CustomerId = @DuplicateCustomer END GO Right, we make the update statement first, So when we do the customer delete, That customer will have no relationship With the Order table. Let’s run our tests again…. ***
  • 133. @jeffreymckenzie (1 row(s) affected) +----------------------+ |Test Execution Summary| +----------------------+ |No|Test Case Name |Dur(ms)|Result | +--+----------------------------------------------+-------+-------+ |1 |[FAS_Tests].[test GivenMerge...Customer] | 37|Success| |2 |[FAS_Tests].[test GivenMerge...Order] | 40|Success| ------------------------------------------------------------------- Test Case Summary: 2 test case(s) executed, 2 succeeded, 0 failed, 0 errored. ------------------------------------------------------------------- And now we are back to passing tests. ***
  • 134. @jeffreymckenzie USE Food_And_Stuff GO BEGIN TRAN DECLARE @RonaldId INT= 1 DECLARE @RonId INT= 2 /* Customer Id we want to keep */ EXEC FAS_Tests.InsertTestData EXEC dbo.MergeCustomer @DuplicateCustomer = @RonaldId, @CustomerToKeep = @RonId SELECT * FROM dbo.Customer SELECT * FROM dbo.[Order] SELECT * FROM dbo.OrderDetail ROLLBACK TRAN GO Let’s try our live test again and see What that returns…. Again we are inserting test data And performing the merge against the actual table…. ***
  • 135. @jeffreymckenzie Here’s the output – no errors And it has what we expect, Just the one record for Ron, Who is attached to all of the orders now. As we continue to add features To this, we now have a set of tests We can use to make sure everything Is working properly. ***
  • 136. @jeffreymckenzie So congratulations everybody – Ron is very happy with our work, And has offered everyone A five dollar gift card to Food and Stuff. ========= https://vignette.wikia.nocookie.net/parksandrecreation/images/0/06/Foo d_and_Stuff_2.png/revision/latest?cb=20120730155117 http://parksandrecreation.wikia.com/wiki/File:Food_and_Stuff_2.png
  • 137. @jeffreymckenzie That’s all I have…. ========= http://parksandrecreation.wikia.com/wiki/Food_and_Stuff https://vignette.wikia.nocookie.net/parksandrecreation/images/1/15/Foo d_and_Stuff.png/revision/latest?cb=20120730155051
  • 138. Hey, You Got Your TDD In My SQL DB! Jeff McKenzie @jeffreymckenzie mail@mcknz.com So thank you for listening & for being here. So does anybody have any questions about -- TDD, the tSQLt Framework, or testing in general?