SlideShare a Scribd company logo
Automated Testing with Databases Philip Nelson Chief Scientist Plan Administrators Inc.
Contact The final version of slides and demo code will be available at my blog site, http://tinyurl.com/78zb2 This presentation began as an article in “Applied Domain Driven Design and Patterns” by Jimmy Nilsson XUnit patterns by Gerard Meszaros
Why?
What we'll cover What do I mean by automated tests? When should you include database access in tests? What alternatives are there? How do you maintain test data? How do test with changing database schemas?
What do I mean by automated tests? Tests are run by a process and the results are tallied automatically Setup/cleanup for the tests do not require human intervention Tool support for verification of results Most commonly done with testing tools and frameworks, for example: junit, nunit, TestNG, AnyUnit etc.
When should you include database access in tests? Integration tests of course: you are integrating various parts of your system and the DB is important What about unit tests? What about acceptance tests, particularly the part of a plan where regression testing is executed?
When should you avoid databases in tests? Testing logic and design? Running hundreds to thousands of tests? Logic in SQL or Stored Procedures? Database isolated by layers or tiers? Data shared by many people?
How should you decide? There is no perfect answer The basic trade off is test speed vs # of database accesses and resets The more subtle trade off is between unit testing and integration testing How do I know I'm done?
Test flow Establish preconditions Execute code under test Verify Clean up
Test preconditions After 5 unsuccessful logins, the user will be locked out When inventory has been depleted to the critical level, send a message to the order system to replenish After assets have increased over $100,000 begin the process to have the account type changed to plan Y Manual testing is really hard because the required conditions often happen only once
public void TestLoginFailCheck() { doLoginSetup(); //stuff to test ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); doLoginCleanup(); } public void TestDepletedInventory() { doInventorySetup(); ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); doInventoryCleanup(); }
public void resetEnvironment() { .... } //database and other shared setup public void TestLoginFailCheck() { doLoginSetup(); //stuff to test ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); } public void TestDepletedInventory() { doInventorySetup(); ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); }
Tests should only setup what is unique about the test Yes – previous number of failed logins Yes – current inventory Yes – current asset total values No – test logins to work with No – part numbers needed to fill out inventory No – names of assets needed to make Asset class load correctly
Recap Automated testing allows you to think about setup for groups of tests with a shared setup Groups of tests involving a database and a deep class hierarchy are too hard to guess exactly what setup is required: the permutations of all the tables, fields and classes that affect the outcome are too numerous to manage test by test Separate database accessing tests from other tests from the very start!
Decision point Can you reset the whole database or not? The whole database should be set/reset to a known state before each test. Each developer/tester needs their own sandbox, and it should ideally be run locally If you can't reset the whole database, you will have to choose maintaining state techniques or mock techniques.
Know your reset techniques Truncate database (unlogged) and insert test data Reset proprietary database files during setup Build database and test data from scratch before each test Run tests in a transaction that you roll back when complete (maintain state technique)
Other ideas Fast, in memory databases (HSQL) Ramdisks File based databases (Access, dBase, SleepyCat) can just be copied if you can disconnect and close the file Xml/data files on the file system Anything where you can easily copy original setups can work.
Do your tests really need to hit a database? To many using a database in unit tests is a code smell.  Use Mock Objects Use Dynamic Mock Frameworks Use  alternate test based repository classes for tests These techniques make for much faster test speed, a major factor when the number of tests gets larger These techniques can make it easier to get consistent data environments for your tests
On the other hand These techniques can mean a parallel hierarchy of mock/stub/fake objects for the real data access objects If your tests require much data, you will be hand coding lots of data values As your project changes, your test data will have to be changed in your code Even if you avoid the database in unit tests, you still need integration tests with the database
Decision Point Test speed vs database connected tests DB tests with resets are hard to get done in less than 250 ms. and longer is easy to achieve Raw data is easier to manage in databases Putting your test data in your test code makes it easy to find and trace and share Keeping the database out of the tests allows your code to migrate along paths that make sense for code
Demonstration of reset techniques DbUnit Rebuild database from test data
Conclusions DbUnit is a JUnit extension The schema is maintained outside of the tool but there are places to execute a create script if you prefer Also allows tests to compare raw data rather than by doing asserts against object model Xml, Excel formats for data, though schema is opaque to meaning making editing challenging
Conclusions continued Best practices from DbUnit documentation “  Use one database instance per developer” “  Good setup don't need cleanup!” “  Use multiple small datasets” “  Perform setup of stale data once for entire test class or test suite”
Verification help DbUnit also has a set based Assert to compare a real data set with a canned data set. Set based compares are rare With an object oriented program it's often pretty easy to compare to object graphs Serialize “known good state” to xml Reconstitute the graph Write an iterator to compare the real vs expected
There are alternate ways to keep test data Xml that makes sense to your application YAML
Sample YAML from Ruby active record # Read about fixtures at  #http://ar.rubyonrails.org/classes/Fixtures.html first_training_log: id: 1 notes: "real easy" another_training_log: id: 2 intensity: 4 notes: "a bit harder today"
Demonstration of reset techniques Reset Sql Server data files
Reset conclusion Very clean way to reset a whole database Can be very fast, though hardware is a big factor Test data can be maintained in the DB data files and managed with normal database techniques The larger the DB files get, the longer the setup time will be Not all database systems have programmatic access to resets in this way Not practical unless you have a local database
Demonstration of reset techniques XtUnit Transaction rollback cleanup
XtUnit conclusions Very simple to do Sql Server/MS windows specific Your test cannot manipulate transactions themselves Setup speed issues are replaced by test speed issues, it all depends on the size of the transactions Can be used on a shared database across a network, making a very useful choice for some situations It's possible to use the transaction technique in other environments
Demonstration of reset techniques Reset with domain model and NHibernate
NHibernate conclusions Setup data is encoded in your actual language using your domain model.  The compiler can catch many of your schema evolution issues and the test setup will catch many more Depending on log issues, the test speed may be slower than some other techniques Use of Hibernate/NHibernate does make it possible to use other DB systems for tests
Decision point Mock object, or state based testing
Demonstration of Mock Techniques Domain Layer + Repository
Demonstration of Mock Techniques Record and Playback
Mock Object conclusions Mock approaches require some degree of parallel systems Dynamic mock approaches can be less code but have limitations you may not be able to live with Hand coded mock approaches can do exactly what you want, but increase the work Mock approaches offer a consistent and very performant way to test You will be maintaining test data in code or files
Mock conclusions.... You may be able to avoid test data to a large degree with “behavioral” techniques Test that  a stored procedure is called correctly Use a Mock Object for the data access Just “Verify()” that the data access object was called correctly and... Assume the stored procedure is a different unit and you  don't need to test the result Testing the results is known as “State based testing” Testing that the call was done is known as “behavioral based testing”
Different decisions for different tests Unit Test Integration Test Acceptance Test
Unit Tests – the case for no DB These are repeated massively so speed really counts While focusing on logic, dealing with data access can be distracting A database is not part of your “Unit”, so don't introduce it in the test By not using the DB, you can cross check the functionality of the unit without the assumptions of preconditions that the database might offer: nulls, default data etc.
Unit Tests – the case for using a DB Some logic requires lots of data: for example financial calculations and it's easier to manage lots of data with tools made for data If you can afford the execution time, you are exercising your actual system much more, not a mocked or stubbed system You don't have to fully architect for substitution of your data access classes. In legacy code, this may be the deal breaker It's easy to use live data as examples for test cases
Unit Tests - conclusion Unit test have natural preference to avoid the use of databases. However, you can make it work up to a point. On new code, I would suggest learning to live without, but on code that doesn't easily support the architecture, learn the tools needed and live with the database.
Integration Tests – the case for no DB There really isn't a case for no DB, these are integration tests where parts of the system come together.
Integration Tests – conclusion Integration tests are most often run as part of a continuous or daily build process. The speed is less a factor and exercising real code is paramount.
Acceptance tests There hasn't been much said about databases with acceptance tests. I have many stories to tell about QA testers that have to go through great agony to rerun tests, but generally systems are rebuilt daily at most. This is an interesting area for further research in the quest of better testing productivity.
Conclusions Can you work with a local database? Can you reset a local database with any of the techniques presented here? Would your architecture or programming culture accept mock techniques for testing? Separate database connected tests from the others What is a reasonable time for your test run to take?
Schema evolution Release day – capture current schema from live Current live + alter scripts to test databases Alter scripts as part of daily build Depending on the number of changes, you may need to run alter scripts against test databases Alternatively, automate the daily test schema After QA cycle, run alter scripts during release to live
Questions?

More Related Content

What's hot (20)

PPTX
Deployment model Blue Green deployment
jeetendra mandal
 
PDF
Intro to containerization
Balint Pato
 
ODP
BDD with Cucumber
Knoldus Inc.
 
PPS
JUnit Presentation
priya_trivedi
 
PDF
Domain Driven Design (Ultra) Distilled
Nicola Costantino
 
PPTX
Cucumber BDD
Pravin Dsilva
 
PDF
Kubernetes Interview Questions And Answers | Kubernetes Tutorial | Kubernetes...
Edureka!
 
PPTX
Android User Interface
Shakib Hasan Sumon
 
PDF
AWS CDK Introduction
Kasun Dilunika
 
PPT
Java Servlets
BG Java EE Course
 
PPTX
Behavior driven development (bdd)
Rohit Bisht
 
PDF
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
Yevgeniy Brikman
 
PPS
Coding Best Practices
mh_azad
 
PDF
Primeros pasos con ReactNative
Irene Alonso Candelario
 
PPTX
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Simplilearn
 
PPTX
Introduction to Spring Boot
Purbarun Chakrabarti
 
PDF
Redux and context api with react native app introduction, use cases, implemen...
Katy Slemon
 
PPTX
How to Implement Domain Driven Design in Real Life SDLC
Abdul Karim
 
PPTX
Introduction to docker
Frederik Mogensen
 
PPS
Test Process
tokarthik
 
Deployment model Blue Green deployment
jeetendra mandal
 
Intro to containerization
Balint Pato
 
BDD with Cucumber
Knoldus Inc.
 
JUnit Presentation
priya_trivedi
 
Domain Driven Design (Ultra) Distilled
Nicola Costantino
 
Cucumber BDD
Pravin Dsilva
 
Kubernetes Interview Questions And Answers | Kubernetes Tutorial | Kubernetes...
Edureka!
 
Android User Interface
Shakib Hasan Sumon
 
AWS CDK Introduction
Kasun Dilunika
 
Java Servlets
BG Java EE Course
 
Behavior driven development (bdd)
Rohit Bisht
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
Yevgeniy Brikman
 
Coding Best Practices
mh_azad
 
Primeros pasos con ReactNative
Irene Alonso Candelario
 
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Simplilearn
 
Introduction to Spring Boot
Purbarun Chakrabarti
 
Redux and context api with react native app introduction, use cases, implemen...
Katy Slemon
 
How to Implement Domain Driven Design in Real Life SDLC
Abdul Karim
 
Introduction to docker
Frederik Mogensen
 
Test Process
tokarthik
 

Similar to Automated Testing with Databases (20)

PPT
Building a Testable Data Access Layer
Todd Anglin
 
PDF
SELJE_Database_Unit_Testing_Slides.pdf
Eric Selje
 
PPT
Using xUnit as a Swiss-Aarmy Testing Toolkit
Chris Oldwood
 
PPTX
Evaluating Test Driven Development And Parameterized Unit Testing In Dot Net ...
mdfachowdhury
 
PPTX
Test Driven Database Development With Data Dude
Cory Foy
 
PDF
SELJE_Database_Unit_Testing.pdf
Eric Selje
 
PDF
Database Testing: A Detailed Guide
Enov8
 
PDF
A data driven etl test framework sqlsat madison
Terry Bunio
 
PPTX
Database Unit Testing Made Easy with VSTS
Sanil Mhatre
 
PPTX
Unit testing
PiXeL16
 
PDF
Test and Behaviour Driven Development (TDD/BDD)
Lars Thorup
 
PPTX
TDD Best Practices
Attila Bertók
 
PPT
Effective Test Driven Database Development
elliando dias
 
PDF
Unit testing (workshop)
Foyzul Karim
 
PPTX
Roy Osherove on Unit Testing Good Practices and Horrible Mistakes
Roy Osherove
 
PPTX
Automated Testing with Databases
Stephen Ritchie
 
PPTX
Iasi code camp 20 april 2013 marian chicu - database unit tests in the sql se...
Codecamp Romania
 
PDF
Microsoft SQL Server Testing Frameworks
Mark Ginnebaugh
 
PPT
Paper PsUpload
techweb08
 
Building a Testable Data Access Layer
Todd Anglin
 
SELJE_Database_Unit_Testing_Slides.pdf
Eric Selje
 
Using xUnit as a Swiss-Aarmy Testing Toolkit
Chris Oldwood
 
Evaluating Test Driven Development And Parameterized Unit Testing In Dot Net ...
mdfachowdhury
 
Test Driven Database Development With Data Dude
Cory Foy
 
SELJE_Database_Unit_Testing.pdf
Eric Selje
 
Database Testing: A Detailed Guide
Enov8
 
A data driven etl test framework sqlsat madison
Terry Bunio
 
Database Unit Testing Made Easy with VSTS
Sanil Mhatre
 
Unit testing
PiXeL16
 
Test and Behaviour Driven Development (TDD/BDD)
Lars Thorup
 
TDD Best Practices
Attila Bertók
 
Effective Test Driven Database Development
elliando dias
 
Unit testing (workshop)
Foyzul Karim
 
Roy Osherove on Unit Testing Good Practices and Horrible Mistakes
Roy Osherove
 
Automated Testing with Databases
Stephen Ritchie
 
Iasi code camp 20 april 2013 marian chicu - database unit tests in the sql se...
Codecamp Romania
 
Microsoft SQL Server Testing Frameworks
Mark Ginnebaugh
 
Paper PsUpload
techweb08
 
Ad

More from elliando dias (20)

PDF
Clojurescript slides
elliando dias
 
PDF
Why you should be excited about ClojureScript
elliando dias
 
PDF
Functional Programming with Immutable Data Structures
elliando dias
 
PPT
Nomenclatura e peças de container
elliando dias
 
PDF
Geometria Projetiva
elliando dias
 
PDF
Polyglot and Poly-paradigm Programming for Better Agility
elliando dias
 
PDF
Javascript Libraries
elliando dias
 
PDF
How to Make an Eight Bit Computer and Save the World!
elliando dias
 
PDF
Ragel talk
elliando dias
 
PDF
A Practical Guide to Connecting Hardware to the Web
elliando dias
 
PDF
Introdução ao Arduino
elliando dias
 
PDF
Minicurso arduino
elliando dias
 
PDF
Incanter Data Sorcery
elliando dias
 
PDF
Rango
elliando dias
 
PDF
Fab.in.a.box - Fab Academy: Machine Design
elliando dias
 
PDF
The Digital Revolution: Machines that makes
elliando dias
 
PDF
Hadoop + Clojure
elliando dias
 
PDF
Hadoop - Simple. Scalable.
elliando dias
 
PDF
Hadoop and Hive Development at Facebook
elliando dias
 
PDF
Multi-core Parallelization in Clojure - a Case Study
elliando dias
 
Clojurescript slides
elliando dias
 
Why you should be excited about ClojureScript
elliando dias
 
Functional Programming with Immutable Data Structures
elliando dias
 
Nomenclatura e peças de container
elliando dias
 
Geometria Projetiva
elliando dias
 
Polyglot and Poly-paradigm Programming for Better Agility
elliando dias
 
Javascript Libraries
elliando dias
 
How to Make an Eight Bit Computer and Save the World!
elliando dias
 
Ragel talk
elliando dias
 
A Practical Guide to Connecting Hardware to the Web
elliando dias
 
Introdução ao Arduino
elliando dias
 
Minicurso arduino
elliando dias
 
Incanter Data Sorcery
elliando dias
 
Fab.in.a.box - Fab Academy: Machine Design
elliando dias
 
The Digital Revolution: Machines that makes
elliando dias
 
Hadoop + Clojure
elliando dias
 
Hadoop - Simple. Scalable.
elliando dias
 
Hadoop and Hive Development at Facebook
elliando dias
 
Multi-core Parallelization in Clojure - a Case Study
elliando dias
 
Ad

Recently uploaded (20)

PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PPTX
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 

Automated Testing with Databases

  • 1. Automated Testing with Databases Philip Nelson Chief Scientist Plan Administrators Inc.
  • 2. Contact The final version of slides and demo code will be available at my blog site, http://tinyurl.com/78zb2 This presentation began as an article in “Applied Domain Driven Design and Patterns” by Jimmy Nilsson XUnit patterns by Gerard Meszaros
  • 4. What we'll cover What do I mean by automated tests? When should you include database access in tests? What alternatives are there? How do you maintain test data? How do test with changing database schemas?
  • 5. What do I mean by automated tests? Tests are run by a process and the results are tallied automatically Setup/cleanup for the tests do not require human intervention Tool support for verification of results Most commonly done with testing tools and frameworks, for example: junit, nunit, TestNG, AnyUnit etc.
  • 6. When should you include database access in tests? Integration tests of course: you are integrating various parts of your system and the DB is important What about unit tests? What about acceptance tests, particularly the part of a plan where regression testing is executed?
  • 7. When should you avoid databases in tests? Testing logic and design? Running hundreds to thousands of tests? Logic in SQL or Stored Procedures? Database isolated by layers or tiers? Data shared by many people?
  • 8. How should you decide? There is no perfect answer The basic trade off is test speed vs # of database accesses and resets The more subtle trade off is between unit testing and integration testing How do I know I'm done?
  • 9. Test flow Establish preconditions Execute code under test Verify Clean up
  • 10. Test preconditions After 5 unsuccessful logins, the user will be locked out When inventory has been depleted to the critical level, send a message to the order system to replenish After assets have increased over $100,000 begin the process to have the account type changed to plan Y Manual testing is really hard because the required conditions often happen only once
  • 11. public void TestLoginFailCheck() { doLoginSetup(); //stuff to test ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); doLoginCleanup(); } public void TestDepletedInventory() { doInventorySetup(); ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); doInventoryCleanup(); }
  • 12. public void resetEnvironment() { .... } //database and other shared setup public void TestLoginFailCheck() { doLoginSetup(); //stuff to test ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); } public void TestDepletedInventory() { doInventorySetup(); ..... Assert.AreEqual(“what I expected”, theTestedThing, “not good”); }
  • 13. Tests should only setup what is unique about the test Yes – previous number of failed logins Yes – current inventory Yes – current asset total values No – test logins to work with No – part numbers needed to fill out inventory No – names of assets needed to make Asset class load correctly
  • 14. Recap Automated testing allows you to think about setup for groups of tests with a shared setup Groups of tests involving a database and a deep class hierarchy are too hard to guess exactly what setup is required: the permutations of all the tables, fields and classes that affect the outcome are too numerous to manage test by test Separate database accessing tests from other tests from the very start!
  • 15. Decision point Can you reset the whole database or not? The whole database should be set/reset to a known state before each test. Each developer/tester needs their own sandbox, and it should ideally be run locally If you can't reset the whole database, you will have to choose maintaining state techniques or mock techniques.
  • 16. Know your reset techniques Truncate database (unlogged) and insert test data Reset proprietary database files during setup Build database and test data from scratch before each test Run tests in a transaction that you roll back when complete (maintain state technique)
  • 17. Other ideas Fast, in memory databases (HSQL) Ramdisks File based databases (Access, dBase, SleepyCat) can just be copied if you can disconnect and close the file Xml/data files on the file system Anything where you can easily copy original setups can work.
  • 18. Do your tests really need to hit a database? To many using a database in unit tests is a code smell. Use Mock Objects Use Dynamic Mock Frameworks Use alternate test based repository classes for tests These techniques make for much faster test speed, a major factor when the number of tests gets larger These techniques can make it easier to get consistent data environments for your tests
  • 19. On the other hand These techniques can mean a parallel hierarchy of mock/stub/fake objects for the real data access objects If your tests require much data, you will be hand coding lots of data values As your project changes, your test data will have to be changed in your code Even if you avoid the database in unit tests, you still need integration tests with the database
  • 20. Decision Point Test speed vs database connected tests DB tests with resets are hard to get done in less than 250 ms. and longer is easy to achieve Raw data is easier to manage in databases Putting your test data in your test code makes it easy to find and trace and share Keeping the database out of the tests allows your code to migrate along paths that make sense for code
  • 21. Demonstration of reset techniques DbUnit Rebuild database from test data
  • 22. Conclusions DbUnit is a JUnit extension The schema is maintained outside of the tool but there are places to execute a create script if you prefer Also allows tests to compare raw data rather than by doing asserts against object model Xml, Excel formats for data, though schema is opaque to meaning making editing challenging
  • 23. Conclusions continued Best practices from DbUnit documentation “ Use one database instance per developer” “ Good setup don't need cleanup!” “ Use multiple small datasets” “ Perform setup of stale data once for entire test class or test suite”
  • 24. Verification help DbUnit also has a set based Assert to compare a real data set with a canned data set. Set based compares are rare With an object oriented program it's often pretty easy to compare to object graphs Serialize “known good state” to xml Reconstitute the graph Write an iterator to compare the real vs expected
  • 25. There are alternate ways to keep test data Xml that makes sense to your application YAML
  • 26. Sample YAML from Ruby active record # Read about fixtures at #http://ar.rubyonrails.org/classes/Fixtures.html first_training_log: id: 1 notes: "real easy" another_training_log: id: 2 intensity: 4 notes: "a bit harder today"
  • 27. Demonstration of reset techniques Reset Sql Server data files
  • 28. Reset conclusion Very clean way to reset a whole database Can be very fast, though hardware is a big factor Test data can be maintained in the DB data files and managed with normal database techniques The larger the DB files get, the longer the setup time will be Not all database systems have programmatic access to resets in this way Not practical unless you have a local database
  • 29. Demonstration of reset techniques XtUnit Transaction rollback cleanup
  • 30. XtUnit conclusions Very simple to do Sql Server/MS windows specific Your test cannot manipulate transactions themselves Setup speed issues are replaced by test speed issues, it all depends on the size of the transactions Can be used on a shared database across a network, making a very useful choice for some situations It's possible to use the transaction technique in other environments
  • 31. Demonstration of reset techniques Reset with domain model and NHibernate
  • 32. NHibernate conclusions Setup data is encoded in your actual language using your domain model. The compiler can catch many of your schema evolution issues and the test setup will catch many more Depending on log issues, the test speed may be slower than some other techniques Use of Hibernate/NHibernate does make it possible to use other DB systems for tests
  • 33. Decision point Mock object, or state based testing
  • 34. Demonstration of Mock Techniques Domain Layer + Repository
  • 35. Demonstration of Mock Techniques Record and Playback
  • 36. Mock Object conclusions Mock approaches require some degree of parallel systems Dynamic mock approaches can be less code but have limitations you may not be able to live with Hand coded mock approaches can do exactly what you want, but increase the work Mock approaches offer a consistent and very performant way to test You will be maintaining test data in code or files
  • 37. Mock conclusions.... You may be able to avoid test data to a large degree with “behavioral” techniques Test that a stored procedure is called correctly Use a Mock Object for the data access Just “Verify()” that the data access object was called correctly and... Assume the stored procedure is a different unit and you don't need to test the result Testing the results is known as “State based testing” Testing that the call was done is known as “behavioral based testing”
  • 38. Different decisions for different tests Unit Test Integration Test Acceptance Test
  • 39. Unit Tests – the case for no DB These are repeated massively so speed really counts While focusing on logic, dealing with data access can be distracting A database is not part of your “Unit”, so don't introduce it in the test By not using the DB, you can cross check the functionality of the unit without the assumptions of preconditions that the database might offer: nulls, default data etc.
  • 40. Unit Tests – the case for using a DB Some logic requires lots of data: for example financial calculations and it's easier to manage lots of data with tools made for data If you can afford the execution time, you are exercising your actual system much more, not a mocked or stubbed system You don't have to fully architect for substitution of your data access classes. In legacy code, this may be the deal breaker It's easy to use live data as examples for test cases
  • 41. Unit Tests - conclusion Unit test have natural preference to avoid the use of databases. However, you can make it work up to a point. On new code, I would suggest learning to live without, but on code that doesn't easily support the architecture, learn the tools needed and live with the database.
  • 42. Integration Tests – the case for no DB There really isn't a case for no DB, these are integration tests where parts of the system come together.
  • 43. Integration Tests – conclusion Integration tests are most often run as part of a continuous or daily build process. The speed is less a factor and exercising real code is paramount.
  • 44. Acceptance tests There hasn't been much said about databases with acceptance tests. I have many stories to tell about QA testers that have to go through great agony to rerun tests, but generally systems are rebuilt daily at most. This is an interesting area for further research in the quest of better testing productivity.
  • 45. Conclusions Can you work with a local database? Can you reset a local database with any of the techniques presented here? Would your architecture or programming culture accept mock techniques for testing? Separate database connected tests from the others What is a reasonable time for your test run to take?
  • 46. Schema evolution Release day – capture current schema from live Current live + alter scripts to test databases Alter scripts as part of daily build Depending on the number of changes, you may need to run alter scripts against test databases Alternatively, automate the daily test schema After QA cycle, run alter scripts during release to live