BT6 Concurrent Session  11/8/2012 2:15 PM              "Database Development: The Object-oriented and Test-driven Way"       Presented by: Max Guernsey Hexagon Software, LLC             Brought to you by:        340 Corporate Way, Suite 300, Orange Park, FL 32073  888‐268‐8770 ∙ 904‐278‐0524 ∙ sqeinfo@sqe.com ∙ www.sqe.com
Max Guernsey Hexagon Software, LLC As head of Hexagon Software, LLC and a software developer with fifteen years of experience, Max Guernsey helps organizations make the transition to agility with a focus on good technical practices such as test-driven development and modern object-oriented design. He develops his company’s DataClass product, a language that allows .NET developers to treat databases like “just another object.” Max is the author of Transition Testing, the foundation of his current TDD database work; Test Driven Database Development which focuses on adapting the discipline of TDD to forces present in the database world; and Goad Testingin which he discusses what unit tests really are and how to make them more resilient to design changes.
Database Development The Test‐Driven and Object‐Oriented Way 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 1 Max Guernsey, III • • • • Max Guernsey, III 15 years as a developer 15 years as a developer Started w/DB early Author: – Test‐Driven Database  Development – Goad Testing – Transition Testing • max@hexsw.com 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 2 1
Agenda • • • • Simplifying Assumptions Establish the Problem Roadmap to True TDD DB Development Follow Roadmap – – – – – Class of Databases Safely Changing Design Enforcing Interfaces g Defining Behaviors Designing for Maintainability • OO DB Development (Whirlwind Tour) 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 3 To fit in a 75 minute box Simplifying Assumptions 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 4 2
Assumptions I assume that you know... • I assume that you know – ...know what TDD is – ...the difference between TDD and Test‐First – ...about mocking – ...a little about design patterns • If not, there are great resources for all • Pick them up, read, & practice before talk 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 5 Know what’s in our way Establish the Problem 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 6 3
TDD in Middle Tier Code [Test] public void AddEmployee() { var company = Company GetInstance(); Company.GetInstance(); var employee = Employee.GetInstance(); Setup Test Runner Test Runner Test1 company.AddEmployee(employee); Trigger Test2 Test3 Assert.That( company.Employees, Has.Some.SameAs(employee); Assertion ThisTest Test5 } Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 7 TDD in Middle Tier Code [Test] public void AddEmployee() { var company = Company GetInstance(); Company.GetInstance(); var employee = Employee.GetInstance(); Setup company.AddEmployee(employee); Trigger Assert.That( company.Employees, Has.Some.SameAs(employee); Assertion } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 8 4
Typical DB Test [Test] public void CannotAddLineItemWithoutType() { DBTestHelper.ClearDatabase(); DBTestHelper ClearDatabase(); Incomplete setup var cartId = DBTestHelper.CreateCart(); try { DBTestHelper.InsertLineItem( Trigger cart: cartId, itemTypeId: DBNull.Value, count: 100); } catch (ConstraintViolationException) { return; } Assertion Assert.Fail(); } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 9 How Was the DB Created? • You don’t know • No guarantee DB works like production • Potential for variation • Leads to... – ...rigorous “controls” over change – ...general “slow down” culture ...general  slow down culture – ...ultimately: bad database designs • DB test suites must cover creation 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 10 5
How to solve the problem Roadmap 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 11 Roadmap to TDD • Creating a Class of Databases – So creation is covered by tests • Testing Creation & Modification – So changes can be introduced w/confidence • Enforcing Interfaces – So consumers are forced to recognize changes • Defining “Behavior” g – So your tests cover the right things • Designing for Maintainability – So you don’t get bogged down by needless junk 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 12 6
There’s More! • OOD – C ti Creating systems of logical DBs w/good coupling & flexible designs t f l i l DB / d li & fl ibl d i • Mocking – Real, useful mocking along interface boundaries • Legacy Databases – Pulling legacy DBs into new process • Non‐DB applications – Serialized objects, XML, file structures • Won’t fit in 75 minutes • Shameless plug – They’re in the book 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 13 You don’t want to run tests against production, do you? Creating a Class of Databases 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 14 7
What is a Class of Databases? • Strictly St ct y – Provisions new DBs – Upgrades existing DBs – All DBs get same behavior • Effecti el Effectively – Uniform create/upgrade path – All DBs “grew” same way 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 15 Problem: Different Build Paths • Test databases need to be “cheap” est databases eed to be c eap – Easy to create & destroy • Production databases need to last – Created w/scripts – Improved incrementally w/scripts • Want all databases to ork the same Want all databases to work the same – Test & production • Exactly the same 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 16 8
How to Make Test DBs? • Test DBs are of low value est s a e o o a ue • Especially when cheap to make • Break one? – Pitch it • Got one dirty? – Pitch it • Make them however you like 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 17 How to Make Production DBs? • • • • • • Starts empty Starts empty Created w/series of instructions Upgraded w/series of instructions to v2 Upgraded w/series of instructions to v3 Etc. Etc No wiggle room – What actually happens is what actually happens 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 18 9
Takeaway #1 © Copyright 2011 Hexagon Software LLC. All rights reserved. 9/12/2012 19 The Sequence of Transitions • v0  v1 – Get a new v1 DB • v1  v2 – Upgrade from v1 to v2 • v0  v1  v2  v3  v4 – Get a new v4 DB • V2  v3  v4 – Upgrade from v2 to v4 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 20 10
Example: Writing a Test [Test] public void HasAnAccountsTable() { // you can do this once per suite if you want MyDatabase.Create(connection, 2); DB created by test Test Runner Test Runner Test1 connection.ExecuteSql("SELECT * FROM Accounts"); Test2 Test3 // exception thrown if no Accounts table ThisTest } Test5 Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 21 Example: Starting DB Script <database> <version number="1"> <script> <!-- Build the database --> </script> </version> </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 22 11
Example: Updating DB Design <database> <version number="1"> <script> <!-- Build the database --> </script> </version> <version number="2"> <script> <![CDATA[ CREATE Accounts(INT ID, NAME CHAR(23)); ]]> </version> </database> Test Runner Test Runner Test1 Test2 Test3 ThisTest Test5 Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 23 Reducing the risk of change rather than its frequency Safely Changing Design 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 24 12
“Neat” • Finding uniform build path a beginning d g u o bu d pat a beg g • Must drive error/variation from build • Builders/installers/etc. are code • What drives error/variation from code? • TESTS!! 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 25 Takeaway #2 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 26 13
A Transition Test • Setup – Bring database up to version X – Populate • Trigger – Transition to subsequent version • Assertion – Prove that content was preserved 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 27 Example: A Transition Test [Test] public void ContactsFactoredFromAccountsInV9() { MyDatabase.Create(connection, 8); var accountId = connection.ExecuteScalar(@" INSERT INTO Accounts(Name, PWHash, Email) VALUES('MaxGuernseyIII', 'pwhash', 'max@hexsw.com'); SELECT SCOPE_IDENTITY();"); Test Runner Test Runner Test1 Test2 Test3 MyDatabase.Create(connection, 9); ThisTest var emails = connection.ExecuteSelectList(@" SELECT Email FROM Contacts WHERE AccountID = ?", accountId); Assert.That( emails, Is.EqualTo(new[] { "max@hexsw.com" }); Test5 Test6 Test7 Test8 } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 28 14
Example: Creating Upgrade Script <database> <version number="9"> <script> p <![CDATA[ CREATE TABLE Contacts( AccountId INT FOREIGN KEY REFERENCES Account(ID), Email NVARCHAR(2048)); Test Runner Test Runner Test1 Test2 Test3 INSERT INTO Contacts(AccountID, Email) SELECT ID, Email FROM Accounts; ThisTest Test5 ALTER TABLE A Accounts DROP COLUMN E il t Email; ]]> </script> </version> </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. Test6 Test7 Test8 29 Getting the best feedback you can Enforcing Interfaces 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 30 15
Remember This? [Test] public void HasAnAccountsTable() { // you can do this once per suite if you want MyDatabase.Create(connection, 2); connection.ExecuteSql("SELECT * FROM Accounts"); // exception thrown if no Accounts table } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 31 Duplication Is Evil • • • • Two tests is annoying Two tests is annoying Ten is a pain Fifty is untenable  Any realistic number impossible to maintain  w/duplication 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 32 16
Easy Solution [Test] public void HasAnAccountsTable() { // you can do this once p y per suite if y you want MyDatabase.Create(connection, MyDatabase.CurrentVersion); connection.ExecuteSql("SELECT * FROM Accounts"); // exception thrown if no Accounts table } ... public class MyDatabase { public const int CurrentVersion = 2; ... } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 33 It’s More Pervasive Version numbers just most obvious • Version numbers just most obvious • Symbols are the real evil... 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 34 17
Duplication Abounds [Test] public void CanInsertData() { connection.Execute(@"INSERT INTO Data(Time, Reading) VALUES( 4:31:01.103 17.02.2009 VALUES('4:31:01 103 17 02 2009', 041 908);”); 041.908); ); } ... <script> CREATE TABLE Data(Time DATETIME, Reading NUMERIC(6,3)); </script> ... private void EnterReading(double reading) { connection.Execute( @"INSERT INTO Data(Time, Reading) VALUES(?,?)", DateTime.Now, reading); } ... private IEnumerable<double> GetOrderedReadings() { return connection.Execute<double>(@"SELECT Reading FROM Data ORDER BY Time ASC"); } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 35 One Solution Minimize w/string constants • Minimize w/string constants • Couple to constants from tests & code • What about interface changes? – Transition tests need old design Transition tests need old design – Unit tests & production code always need latest 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 36 18
Another Solution • • • • Document design w/each transition Document design w/each transition Couple transition tests to exact Couple unit tests to latest Couple production code to latest • What about DB script? 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 37 A Really Good Solution • Document design changes w/version ocu e t des g c a ges / e s o • Bind to design in scripts • Pre‐compile/package step: – Inject bound symbols – Generate coupling code • C Couple unit tests to latest design l i l d i • Couple production code to latest design • Couple transition tests to specific design 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 38 19
Example Script <database> Generate code from this before  <version number="2"> compilation/packaging <design> <add id="NewTable"> <add id="Col1" /> "Take the version 1  <add id="Col2" /> design and add this stuff" </add> </design> Replace w/ "NewTable"  <script> prior to packaging <scope id="NewTable"> CREATE TABLE <id/>( <bind>Col1</bind> INT, <bind>Col2</bind> CHAR(1)); </scope> </script> Replace w/ "Col2" prior  </version> to packaging </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 39 Takeaway #3 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 40 20
Replacing Symbol w/Itself? • 1st‐ly: You can do more y ou ca do o e – E.g.: Use different DB and logical names • 2nd‐ly: Gives advantages of compiler – across languages (SQL, C#, C++, etc.) • Don't believe compiler has advantages? ' b li il h d ? – You're crazy – Keep it to yourself 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 41 If databases are objects, what are their behaviors? Defining Behaviors 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 42 21
What Do Tests Test? • • • • Tests specify behaviors Tests specify behaviors Objects contain behaviors Databases are objects DB tests should specify DB behaviors 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 43 Concepts • • • • Knowledge  persistent data of value Knowledge – persistent data of value Information – useful part of signal Data – superclass of knowledge & information Behavior – Activity that produces a result – Answer to a question Answer to a question – Useful side effect 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 44 22
What Are Behaviors for  Transitions? • Transition behaviors simple Transition behaviors simple • Change from old structure to new • Preserve knowledge • Ignored for this segment Ignored for this segment 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 45 What Are DB Behaviors? DB behaviors slightly more subtle • DB behaviors slightly more subtle • Absorb information & translate to knowledge • Translate knowledge into requested info. • A table is no behavior A table is no behavior • A trigger is not behavior • Those are structure 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 46 23
Knowledge, Info, & Behavior DB Client Knowledge Info. Behavior 9/12/2012 Test © Copyright 2011 Hexagon Software LLC. All rights reserved. 47 Takeaway #4 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 48 24
Don't and Do Don't • Test a table • Test a trigger • Expose structure – E.g.: tables etc. 9/12/2012 Do • Test store & retrieval of info. • Test info causes side effect • Encapsulate structure – w/Views & stored procs © Copyright 2011 Hexagon Software LLC. All rights reserved. 49 Why Encapsulate Design? Weird question: Why not? • Weird question: Why not? • Hidden things cheap to change • Exposed ones expensive • Minimizing public interface maximizes Minimizing public interface maximizes  flexibility 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 50 25
Doing less now enables doing more later Designing for Maintainability 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 51 Don't Plan the Future • • • • • Future is unpredictable Future is unpredictable You cannot plan it Maybe your guess is right Maybe we all die from asteroid strike Usually: your guess  would have been right Usually: your guess "would have" been right – If only universe had cooperated 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 52 26
Plan for the Future Plan for the future to happen • Plan for the future to happen – You'll need to change stuff • Design so that change is easiest • Largely: what's been shown so far Additionally: don t overbuild • Additionally: don't overbuild • "What does that mean?" 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 53 Takeaway #5 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 54 27
Planning for the Future • Encapsulate design – So that structures can change • Enforce interface strongly – So changes don't break downstream functionality • Cover every behavior w/test – So changes don't introduce regression • Cover every transition w/test y / – So changes don't jeopardize knowledge • Minimize features to those needed now – So needed features not impeded by useless ones 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 55 Time to watch this work Live Example 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 56 28
A whirlwind tour The Rest 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 57 OOD • Once classes of DB used, OOD/OOP available O ce c asses o used, OO /OO a a ab e • Use it • Divide & conquer – Create composite DBs – Couple via public interface • Even create abstractions & variations b i & i i – Exploit division to introduce variation – Most important variation on next slide 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 58 29
Mocking Once you have OOD/OOP, easy, good mocking  • Once you have OOD/OOP easy good mocking available • Don't mock tables • Mock behaviors encapsulated in dependency  DBs 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 59 Legacy DBs • Mocking especially handy w/legacy DBs oc g espec a y a dy / egacy s • Create Façade DB, connects to legacy • Easy to test‐drive Façade behaviors: – Just mock out legacy • Transfer behavior to Façade over time • Alternatively: – "wrangle" legacy DB into tested state 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 60 30
Non‐DB Applications • Much of this works for non‐DB – (not recommendation for views & sprocs, obviously) • Have data?  Want to evolve structure over time? – This process works • E.g.: – – – – File systems/directory structures File systems/directory structures Registry keys XML documents Serialized objects 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 61 Thanks for coming.  Any other questions? Q&A 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 62 31

Database Development: The Object-oriented and Test-driven Way

  • 1.
              BT6 Concurrent Session  11/8/2012 2:15 PM              "Database Development: The Object-orientedand Test-driven Way"       Presented by: Max Guernsey Hexagon Software, LLC             Brought to you by:        340 Corporate Way, Suite 300, Orange Park, FL 32073  888‐268‐8770 ∙ 904‐278‐0524 ∙ sqeinfo@sqe.com ∙ www.sqe.com
  • 2.
    Max Guernsey Hexagon Software,LLC As head of Hexagon Software, LLC and a software developer with fifteen years of experience, Max Guernsey helps organizations make the transition to agility with a focus on good technical practices such as test-driven development and modern object-oriented design. He develops his company’s DataClass product, a language that allows .NET developers to treat databases like “just another object.” Max is the author of Transition Testing, the foundation of his current TDD database work; Test Driven Database Development which focuses on adapting the discipline of TDD to forces present in the database world; and Goad Testingin which he discusses what unit tests really are and how to make them more resilient to design changes.
  • 3.
    Database Development The Test‐Driven and Object‐Oriented Way 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 1 Max Guernsey, III • • • • Max Guernsey, III 15 years as a developer 15 years asa developer Started w/DB early Author: – Test‐Driven Database  Development – Goad Testing – Transition Testing • max@hexsw.com 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 2 1
  • 4.
  • 5.
    Assumptions I assume that you know... • I assumethat you know – ...know what TDD is – ...the difference between TDD and Test‐First – ...about mocking – ...a little about design patterns • If not, there are great resources for all • Pick them up, read, & practice before talk 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 5 Know what’s in our way Establish the Problem 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 6 3
  • 6.
    TDD in Middle Tier Code [Test] public void AddEmployee(){ var company = Company GetInstance(); Company.GetInstance(); var employee = Employee.GetInstance(); Setup Test Runner Test Runner Test1 company.AddEmployee(employee); Trigger Test2 Test3 Assert.That( company.Employees, Has.Some.SameAs(employee); Assertion ThisTest Test5 } Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 7 TDD in Middle Tier Code [Test] public void AddEmployee() { var company = Company GetInstance(); Company.GetInstance(); var employee = Employee.GetInstance(); Setup company.AddEmployee(employee); Trigger Assert.That( company.Employees, Has.Some.SameAs(employee); Assertion } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 8 4
  • 7.
    Typical DB Test [Test] public void CannotAddLineItemWithoutType(){ DBTestHelper.ClearDatabase(); DBTestHelper ClearDatabase(); Incomplete setup var cartId = DBTestHelper.CreateCart(); try { DBTestHelper.InsertLineItem( Trigger cart: cartId, itemTypeId: DBNull.Value, count: 100); } catch (ConstraintViolationException) { return; } Assertion Assert.Fail(); } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 9 How Was the DB Created? • You don’t know • No guarantee DB works like production • Potential for variation • Leads to... – ...rigorous “controls” over change – ...general “slow down” culture ...general  slow down culture – ...ultimately: bad database designs • DB test suites must cover creation 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 10 5
  • 8.
    How to solve the problem Roadmap 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 11 Roadmap to TDD • Creating a Class of Databases – So creation is covered by tests •Testing Creation & Modification – So changes can be introduced w/confidence • Enforcing Interfaces – So consumers are forced to recognize changes • Defining “Behavior” g – So your tests cover the right things • Designing for Maintainability – So you don’t get bogged down by needless junk 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 12 6
  • 9.
    There’s More! • OOD – Cti Creating systems of logical DBs w/good coupling & flexible designs t f l i l DB / d li & fl ibl d i • Mocking – Real, useful mocking along interface boundaries • Legacy Databases – Pulling legacy DBs into new process • Non‐DB applications – Serialized objects, XML, file structures • Won’t fit in 75 minutes • Shameless plug – They’re in the book 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 13 You don’t want to run tests against production, do you? Creating a Class of Databases 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 14 7
  • 10.
    What is a Class of Databases? • Strictly St cty – Provisions new DBs – Upgrades existing DBs – All DBs get same behavior • Effecti el Effectively – Uniform create/upgrade path – All DBs “grew” same way 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 15 Problem: Different Build Paths • Test databases need to be “cheap” est databases eed to be c eap – Easy to create & destroy • Production databases need to last – Created w/scripts – Improved incrementally w/scripts • Want all databases to ork the same Want all databases to work the same – Test & production • Exactly the same 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 16 8
  • 11.
    How to Make Test DBs? • Test DBs are of low value est sa e o o a ue • Especially when cheap to make • Break one? – Pitch it • Got one dirty? – Pitch it • Make them however you like 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 17 How to Make Production DBs? • • • • • • Starts empty Starts empty Created w/series of instructions Upgraded w/series of instructions to v2 Upgraded w/series of instructions to v3 Etc. Etc No wiggle room – What actually happens is what actually happens 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 18 9
  • 12.
    Takeaway #1 © Copyright 2011 Hexagon Software LLC. All rights reserved. 9/12/2012 19 The Sequence of Transitions • v0  v1 – Get a new v1 DB •v1  v2 – Upgrade from v1 to v2 • v0  v1  v2  v3  v4 – Get a new v4 DB • V2  v3  v4 – Upgrade from v2 to v4 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 20 10
  • 13.
    Example: Writing a Test [Test] public void HasAnAccountsTable(){ // you can do this once per suite if you want MyDatabase.Create(connection, 2); DB created by test Test Runner Test Runner Test1 connection.ExecuteSql("SELECT * FROM Accounts"); Test2 Test3 // exception thrown if no Accounts table ThisTest } Test5 Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 21 Example: Starting DB Script <database> <version number="1"> <script> <!-- Build the database --> </script> </version> </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 22 11
  • 14.
    Example: Updating DB Design <database> <version number="1"> <script> <!-- Buildthe database --> </script> </version> <version number="2"> <script> <![CDATA[ CREATE Accounts(INT ID, NAME CHAR(23)); ]]> </version> </database> Test Runner Test Runner Test1 Test2 Test3 ThisTest Test5 Test6 Test7 Test8 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 23 Reducing the risk of change rather than its frequency Safely Changing Design 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 24 12
  • 15.
    “Neat” • Finding uniform build path a beginning d gu o bu d pat a beg g • Must drive error/variation from build • Builders/installers/etc. are code • What drives error/variation from code? • TESTS!! 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 25 Takeaway #2 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 26 13
  • 16.
    A Transition Test • Setup – Bring database up to version X –Populate • Trigger – Transition to subsequent version • Assertion – Prove that content was preserved 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 27 Example: A Transition Test [Test] public void ContactsFactoredFromAccountsInV9() { MyDatabase.Create(connection, 8); var accountId = connection.ExecuteScalar(@" INSERT INTO Accounts(Name, PWHash, Email) VALUES('MaxGuernseyIII', 'pwhash', 'max@hexsw.com'); SELECT SCOPE_IDENTITY();"); Test Runner Test Runner Test1 Test2 Test3 MyDatabase.Create(connection, 9); ThisTest var emails = connection.ExecuteSelectList(@" SELECT Email FROM Contacts WHERE AccountID = ?", accountId); Assert.That( emails, Is.EqualTo(new[] { "max@hexsw.com" }); Test5 Test6 Test7 Test8 } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 28 14
  • 17.
    Example: Creating Upgrade Script <database> <version number="9"> <script> p <![CDATA[ CREATE TABLEContacts( AccountId INT FOREIGN KEY REFERENCES Account(ID), Email NVARCHAR(2048)); Test Runner Test Runner Test1 Test2 Test3 INSERT INTO Contacts(AccountID, Email) SELECT ID, Email FROM Accounts; ThisTest Test5 ALTER TABLE A Accounts DROP COLUMN E il t Email; ]]> </script> </version> </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. Test6 Test7 Test8 29 Getting the best feedback you can Enforcing Interfaces 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 30 15
  • 18.
    Remember This? [Test] public void HasAnAccountsTable(){ // you can do this once per suite if you want MyDatabase.Create(connection, 2); connection.ExecuteSql("SELECT * FROM Accounts"); // exception thrown if no Accounts table } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 31 Duplication Is Evil • • • • Two tests is annoying Two tests is annoying Ten is a pain Fifty is untenable  Any realistic number impossible to maintain  w/duplication 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 32 16
  • 19.
    Easy Solution [Test] public void HasAnAccountsTable(){ // you can do this once p y per suite if y you want MyDatabase.Create(connection, MyDatabase.CurrentVersion); connection.ExecuteSql("SELECT * FROM Accounts"); // exception thrown if no Accounts table } ... public class MyDatabase { public const int CurrentVersion = 2; ... } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 33 It’s More Pervasive Version numbers just most obvious • Version numbers just most obvious • Symbols are the real evil... 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 34 17
  • 20.
    Duplication Abounds [Test] public void CanInsertData(){ connection.Execute(@"INSERT INTO Data(Time, Reading) VALUES( 4:31:01.103 17.02.2009 VALUES('4:31:01 103 17 02 2009', 041 908);”); 041.908); ); } ... <script> CREATE TABLE Data(Time DATETIME, Reading NUMERIC(6,3)); </script> ... private void EnterReading(double reading) { connection.Execute( @"INSERT INTO Data(Time, Reading) VALUES(?,?)", DateTime.Now, reading); } ... private IEnumerable<double> GetOrderedReadings() { return connection.Execute<double>(@"SELECT Reading FROM Data ORDER BY Time ASC"); } 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 35 One Solution Minimize w/string constants • Minimize w/string constants • Couple to constants from tests & code • What about interface changes? – Transition tests need old design Transition tests need old design – Unit tests & production code always need latest 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 36 18
  • 21.
    Another Solution • • • • Document design w/each transition Document design w/eachtransition Couple transition tests to exact Couple unit tests to latest Couple production code to latest • What about DB script? 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 37 A Really Good Solution • Document design changes w/version ocu e t des g c a ges / e s o • Bind to design in scripts • Pre‐compile/package step: – Inject bound symbols – Generate coupling code • C Couple unit tests to latest design l i l d i • Couple production code to latest design • Couple transition tests to specific design 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 38 19
  • 22.
    Example Script <database> Generate code from this before  <version number="2"> compilation/packaging <design> <add id="NewTable"> <addid="Col1" /> "Take the version 1  <add id="Col2" /> design and add this stuff" </add> </design> Replace w/ "NewTable"  <script> prior to packaging <scope id="NewTable"> CREATE TABLE <id/>( <bind>Col1</bind> INT, <bind>Col2</bind> CHAR(1)); </scope> </script> Replace w/ "Col2" prior  </version> to packaging </database> 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 39 Takeaway #3 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 40 20
  • 23.
    Replacing Symbol w/Itself? • 1st‐ly: You can do more y ouca do o e – E.g.: Use different DB and logical names • 2nd‐ly: Gives advantages of compiler – across languages (SQL, C#, C++, etc.) • Don't believe compiler has advantages? ' b li il h d ? – You're crazy – Keep it to yourself 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 41 If databases are objects, what are their behaviors? Defining Behaviors 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 42 21
  • 24.
    What Do Tests Test? • • • • Tests specify behaviors Tests specify behaviors Objects contain behaviors Databases are objects DB tests should specify DB behaviors 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 43 Concepts • • • • Knowledge persistent data of value Knowledge – persistent data of value Information – useful part of signal Data – superclass of knowledge & information Behavior – Activity that produces a result – Answer to a question Answer to a question – Useful side effect 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 44 22
  • 25.
    What Are Behaviors for  Transitions? • Transition behaviorssimple Transition behaviors simple • Change from old structure to new • Preserve knowledge • Ignored for this segment Ignored for this segment 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 45 What Are DB Behaviors? DB behaviors slightly more subtle • DB behaviors slightly more subtle • Absorb information & translate to knowledge • Translate knowledge into requested info. • A table is no behavior A table is no behavior • A trigger is not behavior • Those are structure 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 46 23
  • 26.
  • 27.
    Don't and Do Don't • Test a table • Test a trigger •Expose structure – E.g.: tables etc. 9/12/2012 Do • Test store & retrieval of info. • Test info causes side effect • Encapsulate structure – w/Views & stored procs © Copyright 2011 Hexagon Software LLC. All rights reserved. 49 Why Encapsulate Design? Weird question: Why not? • Weird question: Why not? • Hidden things cheap to change • Exposed ones expensive • Minimizing public interface maximizes Minimizing public interface maximizes  flexibility 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 50 25
  • 28.
  • 29.
    Plan for the Future Plan for the future to happen • Planfor the future to happen – You'll need to change stuff • Design so that change is easiest • Largely: what's been shown so far Additionally: don t overbuild • Additionally: don't overbuild • "What does that mean?" 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 53 Takeaway #5 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 54 27
  • 30.
    Planning for the Future • Encapsulate design – So that structures can change •Enforce interface strongly – So changes don't break downstream functionality • Cover every behavior w/test – So changes don't introduce regression • Cover every transition w/test y / – So changes don't jeopardize knowledge • Minimize features to those needed now – So needed features not impeded by useless ones 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 55 Time to watch this work Live Example 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 56 28
  • 31.
    A whirlwind tour The Rest 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 57 OOD • Once classes of DB used, OOD/OOP available O cec asses o used, OO /OO a a ab e • Use it • Divide & conquer – Create composite DBs – Couple via public interface • Even create abstractions & variations b i & i i – Exploit division to introduce variation – Most important variation on next slide 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 58 29
  • 32.
    Mocking Once you have OOD/OOP, easy, good mocking  • Once youhave OOD/OOP easy good mocking available • Don't mock tables • Mock behaviors encapsulated in dependency  DBs 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 59 Legacy DBs • Mocking especially handy w/legacy DBs oc g espec a y a dy / egacy s • Create Façade DB, connects to legacy • Easy to test‐drive Façade behaviors: – Just mock out legacy • Transfer behavior to Façade over time • Alternatively: – "wrangle" legacy DB into tested state 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 60 30
  • 33.
    Non‐DB Applications • Much of this works for non‐DB – (not recommendation for views & sprocs, obviously) •Have data?  Want to evolve structure over time? – This process works • E.g.: – – – – File systems/directory structures File systems/directory structures Registry keys XML documents Serialized objects 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 61 Thanks for coming.  Any other questions? Q&A 9/12/2012 © Copyright 2011 Hexagon Software LLC. All rights reserved. 62 31