SlideShare a Scribd company logo
1 of 59
JUnit and Test Driven Development:
Experiences in MDM CS 2003 to 2012

   Justin Gordon
   Enterprise TDD Evangelist
   Senior Software Engineer
   IBM, Master Data Management Collaboration Server
   gordonju@us.ibm.com
   justin.gordon@gmail.com
   http://www.tddtips.com
   https://github.com/justin808/dof
Author background
 BA Harvard Applied Mathematics, MBA UC
  Berkeley
 Writing Java Enterprise Software since 1996
 Engineer at Trigo, acquired by IBM
 Product now called InfoSphere Master Data
  Management Collaboration Server. Led rewrite
  of storage layer doing using TDD
 Founder and author of Open Source Project
  “Dependent Object Framework”
 Outside of programming, interests include my
  kids, surfing, standup paddling, my dogs, cycling,
  and home improvement. Check out the house I
  designed and built:
  http://www.sugarranchmaui.com.
 Speaker SD West 2008, Architecture and Design
  World 2008, and SD Best Practices 2008. See
  my blog for notes! (http://www.tddtips.com)
 Please tell me about your challenges and maybe
  I can help

                                                       2
Success Factors
 Nature of the project
    – Existing, legacy, and not designed for testing?
    – New code
         – How many dependencies and how containable?
 Motivation of the team
    – TDD is hard work!
 Learning
    – There's a ton to learn about writing good tests. Lots of patterns. Lots of pitfalls.
    – Recommended: xUnit Test Patterns, but it's huge, and Kent Becks original book
      “Test Driven Development by Example”
 Measurement is key
    – Continuous Integration including Code Coverage Reports
 Benefits
    – Quality!
    – Sanity for the overall team, including developers, QA, and managers
 Test First Code
    – Really affects the overall structure of the code, as code is written to be testable.
 Most important overall is to have automation tests!
                                                                                             3
Summary of MDM CS JUnit
 Check out my blog articles, especially this one:
 JUnit and Test Driven Development for MDM CS -- Fixtures and Factories
    – Serialization development was perfect for jUnit
    – High algorithmic complexity, limited outside dependencies
 Rest of the product for jUnit
    – Challenging due to very complex database interactions
    – Led to the open source project Dependent Object Framework which works on the
      problem of test fixture setup
    – Big problem was that developers confused the usage of the framework in terms of
      how to use the true fixtures versus setting up scratch objects.
    – Good article on the subject of fixtures and factories for ruby testing:
       Fixture vs. Factories - Can't we all just get along.




                                                                                    4
Presentation given at SD West, 2009



JUnit and Test Driven Development:
Why and How in Enterprise Software




                                      5
Roadmap
Conventional versus Agile
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started




                             6
Conventional versus Agile
CONVENTIONAL
Architects  High Level Design (HLD)  Detailed Technical Design (DTD) 
  Coding  QA & Bug Fixing  Regressions  More QA & Bug Fixing 
  Major Release  Bug Fixing  Regressions  Bug Fixing  Minor Release
  …
       Painful mess! Unhappy developers, unhappy customers, unhappy
       managers!

AGILE
Stories and Requirements  Simple Specs  Write JUnit (automated) tests in
  Conjunction with Source  Ensure code coverage  Refactoring to make
  code better  QA  Limited bug fixing with JUnit tests for each bug fixed 
  Almost no regressions!  Performance tuning with confidence  Release 
  Very few bugs
          Happy developers, happy customers, happy managers!




                                                                                7
Premise
“A comprehensive suite of JUnit tests is one of the most import aspects of
a software project because it reduces bugs, facilitates adding new
developers, and enables refactoring and performance tuning with
confidence. Test-driven development (TDD) is the best way to build a suite
of tests. And the Dependent Object Framework is the best way to test
against database objects.”
Justin Gordon




                                                                         8
Roadmap
A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started




                                    9
JUnit Tests: What?
 JUnit test: a method, written in Java, that verifies the behavior of an
  individual unit of code, or occasionally of a larger subsystem, and
  reports errors in an automated fashion.




       public void testAddReturnsSum() {
                int sum = Calculator.add(2, 3);
                assertEquals(5, sum);
       }




                                                                            10
JUnit Tests: Why?
 If JUnit tests pass and code coverage is high  Nearly Bug-Free Code!
 When JUnit tests cover requirements and tests pass  Code is Complete!
 JUnit tests facilitate automatic test running to detect regressions instantly
  during bug fix cycles. Can’t do that with manual QA! Can’t do that with QA
  Automation tools!

 Enables Courage and Creativity
 Developers (experienced and new) can change the code with confidence,
  enabling
         – Refactoring
         – Performance Tuning
    – JUnit tests serve to document and demonstrate the API
 Large team sizes, offshoring, complexity



                                                                                  11
Catch 22: Why not write JUnit tests?
 “Normal” development cycle inhibits JUnit test creation

 Catch-22: existing quality is low, so developers are too busy fixing
  problems found in the field to write tests.

 (Bad) Attitude: “It’s QA’s job to find my bugs. I don’t have time to write
  tests.”
 Skills: tough to learn how to write JUnit tests for
  new code. Many new patterns!
 Even tougher for old code!
 Unless existing code is designed for testability,
  implementing JUnit tests is very difficult.



                 Really Tough!


                                                                               12
Roadmap
A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started




                                    13
What is Test Driven Development (TDD)?

“Programming practice in which all production code
is written in response to a failing test.”

List Requirements
                                              Refactor to eliminate code
   Write One Test                             smells (e.g., duplicated code)


 Run Test to
 Make Sure It Fails

                      Add or modify just enough code to make new
                      test pass and all previous tests pass


                       Read Kent Beck’s:
                       “Test Driven Development By Example”
                                                                               14
What Is Not Test Driven Development?
 Any time you write code that is not fixing a failing test.

 I.e., Writing code, then writing tests or intending to eventually write tests.

 Relying on QA to automate their manual tests.

 Be honest when trying this.

 Conventional Big Up Front Design is not TDD!




                                                                                   15
Why TDD  Code Coverage & Better Code
 Guarantees existence of JUnit tests covering most, if not all of your code!

 Guarantees code will be written to be testable.
    – Reverse is also true: if you write your code first, and then your tests, you may
      have difficulty writing tests for the new code, and then you may not write the tests
      at all! More natural to write untestable code unless tests written at the same time.


 Solves the motivation problem. Test writing becomes part of the coding
  process, not a tedious afterthought.

 Produces better code: more decoupled, with clearer, tighter contracts.
 Tests are the canary in the coal mine! Bad designs show up as hard to test!




                                                                                        16
Shooting hoops? Practice Makes Perfect
 Developers improve skills because of the immediate feedback
    from the tests, rather than months later from QA!




                Write Test               Write Code




   Academic study confirms higher quality code: “An Initial Investigation of Test
    Driven Development in Industry” by Boby George and Laurie Williams, 2003,
    http://collaboration.csc.ncsu.edu/laurie/Papers/TDDpaperv8.pdf
   TDD developers took more time (16%), but non-TDD developers did not write
    adequate automated test cases even though instructed to do so!

                                                                                     17
Does Test First Matter?
 Goal is Automated Unit Test Coverage
 Your choice how you get there
 Sometimes, you already have lots of code! So too late for
 pure TDD!

 So…

 Consider a broader definition of TDD…
 Not just “Test First Programming”

 But delivering code with unit tests

 You want automated test coverage as code is delivered!

                                                           18
Roadmap
A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started




                                    19
Making it Happen: Tools for Success
 IDEs: Eclipse, RSA, RAD, and IntelliJ offer these
  essentials:
     –   Ease of use to run a single new test
     –   Refactoring tools.

 Code Coverage
     –   Now built into Eclipse (EclEmma) and IntelliJ
     –   Clover or Emma are the most popular.
     –   How do you know how good your tests are?
     –   Measure progress for morale (and management reports).

 Continuous Automation
     – Jenkins, Cruise Control, or BuildForge
     –   Automated system for building code, running JUnit tests and
         reporting on code coverage.
     –   Alerts team of issues (build or JUnit) within minutes of checkins

 Mock Objects: Mockito
 Dependent Object Framework
     –   Ease of writing JUnit tests in the context of persistent objects →
         helps setup database fixtures


                                                                              20
Code Coverage Inside Eclipse

                               Code Coverage in
                               Eclipse provided by
                               EclEmma:
                               http://www.eclemma.org


                               Green lines indicate
                               coverage by unit
                               tests.


                               Pink lines indicate
                               code not covered by
                               unit tests




                                                21
Exercise 1: Simple TDD: Compute Change Coins

                                     public class Change
Problem: Compute Change Coins        { public int pennies, nickels, dimes, quarters;
 Coins include: pennies, nickels,   public Change(int pennies, int nickels, int dimes, int
                                        quarters) {
  dimes, quarters                       this.pennies = pennies;
 Machine may be out of any coin        this.nickels = nickels;
                                        this.dimes = dimes;
  except pennies                        this.quarters = quarters;
 Give least number of coins          }

                                     public class VendingMachine
Example:                             { // the number of coins left
All coins available:                    public int pennies, nickels, dimes, quarters;
 37 cents: 1 quarter, 1 dime, 2        public Change getChange(int cents)
                                        { … }
   pennies                           }
 80 cents: 3 quarters, 1 nickel
                                     public class VendingMachineTest extends TestCase
                                     {
No nickels:                             public void testGetChangeReturnsNoChangeIfNoCents)
 80 cents: 2 quarters, 3 dimes         { … }
                                     }
No dimes:
 85 cents: 3 quarters, 2 nickels


                                                                                        22
Exercise 1 Tips
 Only add code after adding a test that fails!
 Do bare minimum to make tests pass
 Patterns: Naming Test Methods
    –   test{MethodName}Returns{Value}When{Condition}
         –   testGetChangeReturnsZeroWhenNoCents
         –   testGetChangeReturnsThreeQuartersOneNickelWhenEightyCents
    –   test{MethodName} {DoesSomething}When{Condition}
         –   testGetChangeThrowsWhenCentsLessThanZero
    –   Why such long method names?
         1. Method names print out in test failures
         2. Programmers never call these methods


– Directory Structure
    –   src: Where production code goes
    –   junit:Where junit tests go, use parallel package structure to test package and protected
        methods.

 Implement equals() so that we can compare Change objects.
– Implement toString() so that error messages are clear




                                                                                                   23
Exercise 1: Steps for “Initial” example
1. Run VendingMachineTestSuite to see all tests run

2. Run the test suite with code coverage turned on to see code coverage

3. Uncomment Change.toString() to see effect on the error message 
   implement toString() for better messages

4. Uncomment Change.equals() to see VendingMachineTest tests pass.

5. Put @Ignore in front of failing test and run all tests to see that no failures and
   2 ignored tests




                                                                                   24
Exercise 1b: Steps for “Intermediate”
1.   Check out the triangulation method of verification.
2.   Fix the test testGetChangeReturnsThreePenniesIfTwoCents()
3.   Check out the use of the @Before setup of the variable VendingMachine
4.   Complete the rest of the commented tests
5.   Handle the tougher cases where the vending machine can run out of a
     certain kind of coin


Question: Can we exhaustively find all the solutions and check the code against
  these solutions? Possibly could write tests to use triangulation.




                                                                             25
Roadmap
A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started




                                    26
Architectural benefits of TDD

                       Without TDD, you often
                       see tight coupling between      Tight Coupling!
                       classes and throughout to all
                       dependencies, making the                          D
                                                            A
                       implementation of new tests
                       prohibitively painful.                                 class

                                                       B
 With TDD                                                               E   interface

                                                            C
 Better abstractions and better
  decoupling of classes.
                                                       Loose Coupling: TDD!
 Loose coupling, otherwise impossible
  to test individual components.                                    A
 When using “Test Doubles” (e.g., test
  stubs and mock objects), you want to                 bb           cc       dd
  mock out smaller APIs or else you’ll
  work too hard! Keep classes small                    B        e   C
  and methods tight.
                                                                             D

                                                                                         27
Test Doubles
 Test Doubles: Fakes, Stubs, Mocks – see “xUnit Test Patterns” by
 Meszaros

 Reasons to use Test Doubles
    – Isolates code for testing!
    – Awkward to setup for JUnit test – e.g. web services
    – Not available (or not yet written) – new component in large project
    – Too slow (less so now with in-memory DBs like H2)

 Reasons to not use Test Doubles
    – Extra code to maintain that is only used for testing
    – Difficult to refactor code to use test doubles
    – You still need to test the delivery code!
    – Don’t mock out the database!


                                                                            28
Making it Happen: Isolating Code for Testing
 Note – Mock objects are a form of test double and the name is used interchangeably here
 Successful TDD depends on dependency isolation – you need to separate the code to
  be tested from the rest of the system.
     –   This is THE main technical challenge, esp. for database and integration points
     –   Must decouple classes with interface/implementation/mock object pattern
     –   Use a combination of dependency location and/or dependency injection for dependencies
         (following slides)
     –   Typically mocking out a dependency on a clearly defined component, such as an object that
         would call a web service.
     –   Difficult to do TDD without using test doubles (or using the Dependent Object Framework)
     –   Tip: minimize business logic in mock objects because you have to duplicate that logic in the real
         implementation. Refactor code to minimize business logic in mock classes.




                                                              Dependency
                             Interface




   Class To Test
                                                            (Runtime Object)


                                                              Dependency
                                                             (Test Double,
                                                           e.g. Mock Object)
                                                                                                      29
Dependency Isolation: Static Location
 Example: Class fetches data from the database or from a mock source. But
how does your code get a handle to the correct Component?
Dependency location: your class looks up the dependency (test
double or real instance) from a known location, typically a static
method call

Test setup code:
// note, setTaxRateProvider takes interface TaxRateProvider
GlobalContext.setTaxRateProvider(new MockTaxRateProvider());

Production setup code:
GlobalContext.setTaxRateProvider(new SoapTaxRateProvider());
Production Code sees interface  does NOT know if real or
test double!!
class OrderProcessor                                                                                           Static method
public float getTaxRateForState(String state)
   {                                                                                                         returns interface!
         TaxRateProvider taxRateProvider =
               GlobalContext.getTaxRateProvider();
         return taxRateProvider.getSalesTax(state);
   }

See: “Inversion of Control Containers and the Dependency Injection pattern”: http://www.martinfowler.com/articles/injection.html

                                                                                                                                   30
Dependency Isolation: Constructor/Setter Injection

 Dependency Constructor/Setter Injection: Pass a reference to
  the dependency in the constructor (or a setter):

 Test setup code:
    // note interface TaxRateProvider
    TaxRateProvider mockTaxRateProvider = new MockTaxRateProvider();
    OrderProcessor orderProcessor = new OrderProcessor(mockTaxRateProvider)
 Production code:
    TaxRateProvider soapTaxRateProvider = new SoapTaxRateProvider());
    OrderProcessor orderProcessor = new OrderProcessor(soapTaxRateProvider)

 InvoiceComponent class does NOT know if it has a real or mock
  persistence object
                                                                  Member interface
    class OrderProcessor {                                           variable!
         TaxRateProvider taxRateProvider;
       // constructor injection
         OrderProcessor (TaxRateProvider taxRateProvider ) {
            this.taxRateProvider = taxRateProvider;
       }

    public float getTaxRateForState(String state)
        {
              return taxRateProvider.getSalesTax(state);
        }

                                                                                 31
Dependency Injection versus Service Locator
“Inversion of control is a common feature of frameworks, but it's something that comes at
   a price. It tends to be hard to understand and leads to problems when you are trying to
   debug. So on the whole I prefer to avoid it unless I need it. This isn't to say it's a bad
   thing, just that I think it needs to justify itself over the more straightforward alternative…
The key difference is that with a Service Locator every user of a service has a
  dependency to the locator. The locator can hide dependencies to other
  implementations, but you do need to see the locator. So the decision between locator
  and injector depends on whether that dependency is a problem.
A lot of this depends on the nature of the user of the service. If you are building an
   application with various classes that use a service, then a dependency from the
   application classes to the locator isn't a big deal….The difference comes if the lister is a
   component that I'm providing to an application that other people are writing. In this case
   I don't know much about the APIs of the service locators that my customers are going to
   use. Each customer might have their own incompatible service locators. I can get
   around some of this by using the segregated interface. Each customer can write an
   adapter that matches my interface to their locator, but in any case I still need to see the
   first locator to lookup my specific interface. And once the adapter appears then the
   simplicity of the direct connection to a locator is beginning to slip.

Martin Fowler
http://martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection



                                                                                               32
Mockito
Highly recommended! First, you have to isolate dependencies. Then mock:
http://code.google.com/p/mockito/




                                                                          33
Roadmap

A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started



                                    34
Basic Phases of an xUnit Test

         Setup
 Prepare Test Fixtures -- Get
                                         xUnit Test
Application State Ready To Do
          Something               DB Objects and the DOF

             Exercise
    Do Something With Fixtures Prefer
             Single Action


                                Verify
              Check Something Happened: assertSomething()


                                          Teardown
                                Restore application state for next test


                                                                      35
Database Issues
 Database is like a global variable that is slow to access!
 Actually worse than a global variable because it lives between test
  runs!
 Stickiness of data collides with xUnit philosophy of
  atomic/independent tests!

 DB “Fixture” Setup without the DOF
     –   Java code
     –   SQL scripts
     –   DB Backups

 Issues: Difficult, Monolithic, fragile, frustrating, slow
     – Greater possibility of slow and erratically failing tests

 Test fixtures often include objects that are persisted in the DB. I.e., in order to run
  a test, some values must exist in the DB, and a test may create some new records
  in the DB.

                                                                                       36
Why have xUnit tests hit the database?
 Production code for end users will hit the DB, so you need to test it!

 Catch 22: Refactor in order to isolate database dependencies to
  build tests, but without tests, how safely can we do the refactoring?!

 Mocks and stubs add (much) more code to maintain (and to fix
  bugs!).

 Reliance on mocks and stubs can mask errors with using the DB.

 Annecdote: GuideWire Software used to depend heavily on stubs
  and dependency isolation techniques, but now focuses exclusively
  on tests against the database, using H2 in-memory DB to speed up
  tests.




                                                                           37
DOF: What Problem Does it Solve?
 Setup of the DB in a “lazy” and “modular” fashion as
 needed by each test
   – Only populate what is needed for a test
   – Test does not worry if DB already populated

 Clarity of the DB setup required for a test
   – See clearly DB objects needed for a test

 Establishes a clear pattern for teamwork and reusability
 behind the DB setup




                                                             38
Simple Example – Logical Model

                                           Logical Object Model
              Invoice                          Defines object
                                         relationships behind the
                                          DOF setup but the DOF
                                             setup is about the
                                       instances of these objects
   Customer
                         Product        that have representations
                                              in the database



                        Manufacturer




                                                                    39
Data Relationships and Object Creation



                                                           With DOF, test
                    Invoice   1001                         only specifies top
                                                           level dependency!

                                        Customer   Jones

                                                                     Objects Created
 Product   Orange Juice                                               DOF takes care
                                                                    ensuring these DB
                   Product    Grape Juice                           backed objects are
                                                                    ready for your test
                         Manufacturer

                   Ocean Spray


                                                                                      40
Object Dependency Processing: Java Reference Object
Your test code   DOF plumbing      Your ReferenceBuilder code


ReferenceBuilder rbOrangeJuice = new Product_OrangeJuice();
Product orangeJuice = (Product) DOF.require(productOJ);
                                                                       Return Object “Orange Juice”
Object pk = rbOrangeJuice.getPrimaryKey()
Check cache for Orange Juice object                        OJ Found
                                                           in Cache
        OJ Not Found

Call rbOrangeJuice.fetch() to check DB for primary key
“Orange Juice”                                                   OJ Found in
                                                                 Database
           OJ Not Found

Call rbOrangeJuice.create()                                                        You persist the
                                                                                   Orange Juice object
ReferenceBuilder rbTropicana = new Manufacturer_Tropicana();                       with foreign key to
                                                                                   Tropicana
Manufacturer tropicana = DOF.require(rbManufacturerTropicana);



Check cache, maybe call
rbTropicana.fetch()                      Tropicana Found

Tropicana Not Found

Call rbTropicana.create()     You persist the Tropicana object
                                                                                                         41
Principles of Test Automation for the DOF
         From Meszaros, “xUnit Test Patterns”
             –   Highly recommended!

         “Keep Tests Independent” – Any test can run on its own or with other
          tests in any order. Independent test failures easiest to reproduce and
          fix!
             –   With the DOF, you can run test in any order and on a clean or existing DB
                 schema
             –   Absolute nightmare having giant DB setups for tests

         “Communicate Intent” -- minimize code and avoid logic in tests (if
          statements)
             – DOF hides the messy setup of preparing objects
             – Test reader sees only objects involved directly in a test

         “Don’t Modify the SUT” -- prefer testing the production code
             –   SUT = System Under Test – your production code
             –   DOF supports tests against “production” code which hits the database




                                                                                        42
Technique: Scratch Objects
Motivation: Avoid erratic tests that have database dependencies

Cause: Multiple tests depend on and modify the same objects in the database, and
  thus the tests sometimes fail because of uncertain database state

Solution: Always use a fresh primary key for objects created in a test



private Customer getNewUniqueCustomer()
    {
        Customer customer = new Customer();
        // Example of pattern to create unique PKs
        customer.setName(System.currentTimeMillis() + "");
        customerComponent.insert(customer);
        return customer;
    }




                                                                               43
In-Memory DBs for Testing

 Fixture setup for test class (not per test!)
    – Load frozen copy of DB
    – Load data into tables
    – Understand that test may interact with each other in the data for a given test class

 Breaks the “atomic” model of JUnit tests
    – This solution is a little like using lock striping, or maybe the way that conferences
      might break up the registration lines by first letter of last name.
    – All tests are not atomic
    – But groups of tests together form one “batch” where they get the database to
      interact with.

 Options
    – H2 – supposedly the fastest
    – HSQLDB – Hibernate examples are based on HSQLDB



 See article on blog: http://justingordon.org
                                                                                          44
Dependent Object Framework
 Open source project with EPL License: http://sourceforge.net/projects/dof

 Problem: setup of required persistent (DB) objects for JUnit tests

 Objectives:
     – Ease of test fixture setup:
          – Simply list dependencies for a test.
          – Support both “reference” objects and “scratch” objects
     – Performance: Tests must run quickly—Cache reference objects in memory
     – Tests are stable – run any number of times in any order
     – Easily distinguish between reference (shared) objects and scratch (unique, non-
       shared) objects
     – Either use “files and associated handlers” or “Java” to define objects
     – Support deletion/garbage collection of created objects


 Author: Justin Gordon based on technique used in product MDM Server for
  Product Information Management




                                                                                         45
Roadmap

A tale of two development groups
JUnit Tests
Test Driven Development
Tools
TDD Architecture
Database Techniques: DOF
Getting Started



                                    46
Making it Happen: Dealing with Legacy Code

 If only we could write everything from scratch
  again!

 Expect islands of old, untested, and untestable
  code
    – UI code tends to be particularly problematic
    – Most legacy code will be essentially untestable
 Try piecewise remodeling
    – Discard old modules one-by-one, replacing with TDD code

 Try “encrapsulation”
    – Wall off legacy junk behind a façade interface (if possible; sometimes not)
    – Mock out legacy code when testing new modules
                                 Clean
                  CRAP           Interface

                                                                              47
Pair Programming and TDD
 Complementary: Pair Programming helps with TDD
 Big aid in learning TDD
 One person thinks strategically, encourages the “coder” to write tests before
  the implementation.
    – “Don't write a line of code that doesn't fix a failing test.”
 Pairing allows collaboration on solving dependency isolation issues, along
  with other issues in getting first tests to run.
 Once there's a body of tests to use as examples, pair is less necessary.
 Highly recommended when a team is learning TDD.




                                                                                  48
Making it Happen: Getting the Team Started

Get Beck’s “Test Driven Development”, start up your IDE
and do TDD! Or try to recreate my accounting example.
Solidify commitment at every level of the organization
    –    TDD slower for first 6 months; net speedup afterwards.
    –    Don’t expect to hold the same schedule and “just add testing”!
    –    Systematically discover and eliminate obstacles.
    –    TDD takes discipline. Align incentives, communication, work
         environment – everything
Consider using the Dependent Object Framework
    –    Will avoid need to create too many mock objects
Start with a new project or pick a subproject
    –    TDD can be done against existing code, but MUCH harder
    –    Focus on lower levels of the system first

Allow extra time
     –    for learning: there are many new skills and patterns to pick up.
     –    for re-architecture: existing architecture probably doesn’t support testing
Expect discomfort at first – developers not used to working this way.                  Your best
     –    Start with a few respected “early adopters” and a trial run                     bet!
                                                                                                49
WASSUP? How enterprise projects without automated
tests can end up after 8 years!
http://www.youtube.com/watch?v=Qq8Uc5BFogE




                                                    50
Your Challenges?
 What are some of the biggest hurdles your projects face in becoming “Test
  Driven”?

 E-mail me with your challenges with TDD and maybe I can help.


 I’m not a formal consultant, but looking for material for my book in terms of
  real world enterprise problems and solutions in this area, and maybe you can
  benefit.


 Try out the DOF and I’d be happy to help.




                                                                                  51
Conclusion
 How would you choose between a project with awesome JUnit tests and a project
  without JUnit, but lots of great architectural documents and other documentation? I’d
  take the JUnit one hands down.
 Documentation gets out of date quickly. Code without tests may be quite buggy, and
  even if it’s not buggy, would I trust myself to join a project and not introduce bugs
  without JUnit?
 Having a comprehensive suite of JUnit tests is the most import piece of
  intellectual property in a software project.
 Why? First you have very few bugs. Second, developers, new and old, can change
  the code with confidence because they know immediately if they break something.
  This enables the two most important activities in a software project.
     – Refactoring
     – Performance Tuning

 And TDD is the best way to get that suite of tests (with the DOF for DB testing)!
 Thank you for listening!
http://sourceforge.net/projects/dof
http://justingordon.org
justingordon@yahoo.com


                                                                                          52
Resources
Justin Gordon
justin.gordon@gmail.com
http://www.tddtips.com
https://github.com/justin808/dof

 Just Do It! You cannot just read books on it!
  Just Do It!
 Use Eclipse or IntelliJ and try doing TDD on
  a simple example
 Gerard Meszaros – “xUnit Test Patterns”
 Kent Beck – “Test Driven Development”,
  “Extreme Programming Explained”
 Lasse Koskela – “Test Driven: TDD and
  Acceptance TDD for Java Developers”
 Martin Fowler, especially “Refactoring:
  Improving the Design of Existing Code”
 Michael Feathers “Working Effectively with
  Legacy Code”
                                                  53
Extras…




          54
Persistent Test Fixture Strategy
 Purpose of the DOF is Persistent Test Fixture
 Setup

 Keep the test clear by separating the “fixture”
 (setup of test) from the “test”

 Shared Test Fixture
   – Shared among multiple tests
   – Addresses Performance Issues of creating
     objects for each test
   – Must be immutable or else erratic tests

 Fresh Test Fixture (Scratch Objects)
                                                    Scratch
   – Uses unique identifier so no collisions
                                                    Objects
   – Used for objects your test will modify
   – String pk = System.currentTimeMillis() + “”;




                                                              55
“Reference” Objects versus “Scratch” Objects
               “Reference Objects” are
                  – “Shared Persistent Test Fixtures”
  Reference       – Background data for a test
   Objects
                  – Loaded once and cached  SUPER for PERFORMANCE
                  – Must not be changed by tests – immutable!
                  – Reference and Scratch objects can “refer” to (have foreign keys)
                    to either other “reference” objects or “scratch” objects

               “Scratch Objects”
                  – “Persistent Fresh Fixtures”
  Scratch         – These are what the test modifies
  Objects         – Only visible to a single test for a single test run
                  – Run test multiple times and new scratch objects are created
                  – Must be given a unique keys (i.e., timestamp string)
                  – Can refer to reference objects or scratch objects
                  – Ensures that tests don’t interfere with each other  no erratic
                    test runs!

                                                                                  56
DOF Basic Concepts
 One file (or Java class) per object definition.
 DOF takes care of recursive object creation. Thus, object dependencies are
  ONLY listed in an object’s definition file (or class), never in a test.
    – I.e., if object A depends on object B, you should NEVER need to specify both
      object B and object A in a test. Definition of object A specifies that it depends on
      object B.

 Best practices for use of the DOF
    – Each developer has own database.
    – Simple script for populating a clean schema.

 Critical to avoid changing reference objects, otherwise tests become erratic
  and unstable

 You can choose “Java” or “Text Files” or any combination to define objects.
 Deletion (garbage collection) of created objects is available, but discouraged
  (see next slide).


                                                                                         57
Java or Text Definitions for Objects?
 Java Builder Pattern
    – Create one Java class per reference object of scratch object definition
    – Implement interface ReferenceBuilder or ScratchBuilder
    – Advantage:
         – Full support of IDE for refactoring and navigation
         – More flexibility with Java code for each object
         – More explicit object creation
    – Disadvantage: Can be very verbose compared to a properties file or XML

 Text Files and Associated Handlers
    – For each class (file type), write a handler class that implements interface
      DependentObjectHandler
    – Create one file per reference object or scratch object
    – DOF takes care of the plumbing
    – Advantage: More concise format
    – Disadvantage: Can be awkward if changes are needed

 Use of Java and Text are not exclusive! Interoperable!

                                                                                    58
DOF FAQ
 How is this different from DBUnit?
    – DBUnit focuses on DB rows. DOF focuses on object dependencies

 Does the DOF only work with database dependencies?
    – No. Dependencies can be anywhere, such as with web services.

 Should I use an in-memory DB?
    – Being able to switch your DB from Oracle or DB2 to an in-memory one for testing
      is highly recommended for speeding up test execution. Check out H2 and
      HSQLDB.

 I work on a shared DB and I can’t simply recreate the schema. Help!
    – No problem. Make sure that you run DOF.deleteAll(DOF.DeletionOption.all) when
      you tear down your tests. If you do that, you will avoid adding any records to the
      DB.




                                                                                      59

More Related Content

What's hot

A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) CodeOps Technologies LLP
 
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...agil8 Ltd
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven DevelopmentLim Chanmann
 
Test driven development and react js application go hand in hand
Test driven development and react js application go hand in handTest driven development and react js application go hand in hand
Test driven development and react js application go hand in handKaty Slemon
 
Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Jaehoon Oh
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentguestc8093a6
 
TDD vs. ATDD - What, Why, Which, When & Where
TDD vs. ATDD - What, Why, Which, When & WhereTDD vs. ATDD - What, Why, Which, When & Where
TDD vs. ATDD - What, Why, Which, When & WhereDaniel Davis
 
Software testing agile_environment_wp
Software testing agile_environment_wpSoftware testing agile_environment_wp
Software testing agile_environment_wpCristiano Caetano
 
Test driven development - Zombie proof your code
Test driven development - Zombie proof your codeTest driven development - Zombie proof your code
Test driven development - Zombie proof your codePascal Larocque
 
Refactoring legacy code driven by tests - ITA
Refactoring legacy code driven by tests -  ITARefactoring legacy code driven by tests -  ITA
Refactoring legacy code driven by tests - ITALuca Minudel
 
Teaching Kids Programming
Teaching Kids ProgrammingTeaching Kids Programming
Teaching Kids ProgrammingLynn Langit
 
Practices of agile developers
Practices of agile developersPractices of agile developers
Practices of agile developersDUONG Trong Tan
 
TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDDavid Rodenas
 
Waterfallacies V1 1
Waterfallacies V1 1Waterfallacies V1 1
Waterfallacies V1 1Jorge Boria
 
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...Zohirul Alam Tiemoon
 

What's hot (20)

Test driven development(tdd)
Test driven development(tdd)Test driven development(tdd)
Test driven development(tdd)
 
A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD) A Not-So-Serious Introduction to Test Driven Development (TDD)
A Not-So-Serious Introduction to Test Driven Development (TDD)
 
Test drive on driven development process
Test drive on driven development processTest drive on driven development process
Test drive on driven development process
 
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...
Agile Software Development and Test Driven Development: Agil8's Dave Putman 3...
 
TDD - Test Driven Development
TDD - Test Driven DevelopmentTDD - Test Driven Development
TDD - Test Driven Development
 
Test driven development and react js application go hand in hand
Test driven development and react js application go hand in handTest driven development and react js application go hand in hand
Test driven development and react js application go hand in hand
 
Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가Tdd 왜 배우기 어려운가
Tdd 왜 배우기 어려운가
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
TDD vs. ATDD - What, Why, Which, When & Where
TDD vs. ATDD - What, Why, Which, When & WhereTDD vs. ATDD - What, Why, Which, When & Where
TDD vs. ATDD - What, Why, Which, When & Where
 
TDD refresher
TDD refresherTDD refresher
TDD refresher
 
Tdd
TddTdd
Tdd
 
Software testing agile_environment_wp
Software testing agile_environment_wpSoftware testing agile_environment_wp
Software testing agile_environment_wp
 
Test driven development - Zombie proof your code
Test driven development - Zombie proof your codeTest driven development - Zombie proof your code
Test driven development - Zombie proof your code
 
Refactoring legacy code driven by tests - ITA
Refactoring legacy code driven by tests -  ITARefactoring legacy code driven by tests -  ITA
Refactoring legacy code driven by tests - ITA
 
Teaching Kids Programming
Teaching Kids ProgrammingTeaching Kids Programming
Teaching Kids Programming
 
Practices of agile developers
Practices of agile developersPractices of agile developers
Practices of agile developers
 
TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
 
Tdd
TddTdd
Tdd
 
Waterfallacies V1 1
Waterfallacies V1 1Waterfallacies V1 1
Waterfallacies V1 1
 
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...
Overview on TDD (Test Driven Development) & ATDD (Acceptance Test Driven Deve...
 

Viewers also liked

Improving Your Heroku App Performance with Asset CDN and Unicorn
Improving Your Heroku App Performance with Asset CDN and UnicornImproving Your Heroku App Performance with Asset CDN and Unicorn
Improving Your Heroku App Performance with Asset CDN and UnicornSimon Bagreev
 
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Justin Gordon
 
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Justin Gordon
 
Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Jessica Mauerhan
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016Justin Gordon
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practicesnickokiss
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with MockitoRichard Paul
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesDerek Smith
 
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...Toshiaki Maki
 
The Art of Product Marketing
The Art of Product MarketingThe Art of Product Marketing
The Art of Product MarketingRand Fishkin
 

Viewers also liked (14)

Improving Your Heroku App Performance with Asset CDN and Unicorn
Improving Your Heroku App Performance with Asset CDN and UnicornImproving Your Heroku App Performance with Asset CDN and Unicorn
Improving Your Heroku App Performance with Asset CDN and Unicorn
 
xUnit
xUnitxUnit
xUnit
 
React on rails v4
React on rails v4React on rails v4
React on rails v4
 
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
 
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
Rails Conf 2014 Concerns, Decorators, Presenters, Service-objects, Helpers, H...
 
Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!Double Loop: TDD & BDD Done Right!
Double Loop: TDD & BDD Done Right!
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016React on rails v6.1 at LA Ruby, November 2016
React on rails v6.1 at LA Ruby, November 2016
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
 
JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best Practices
 
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
#jjug_ccc #ccc_gh5 What's new in Spring Framework 4.3 / Boot 1.4 + Pivotal's ...
 
The Art of Product Marketing
The Art of Product MarketingThe Art of Product Marketing
The Art of Product Marketing
 

Similar to xUnit and TDD: Why and How in Enterprise Software, August 2012

Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In ActionJon Kruger
 
Cleaner Code Through Test-Driven Development
Cleaner Code Through Test-Driven DevelopmentCleaner Code Through Test-Driven Development
Cleaner Code Through Test-Driven DevelopmentAll Things Open
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testingikhwanhayat
 
BDD presentation
BDD presentationBDD presentation
BDD presentationtemebele
 
Test Driven Development - Overview and Adoption
Test Driven Development - Overview and AdoptionTest Driven Development - Overview and Adoption
Test Driven Development - Overview and AdoptionPyxis Technologies
 
Test driven development
Test driven developmentTest driven development
Test driven developmentSunil Prasad
 
Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference CardSeapine Software
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit TestingShaun Abram
 
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...mCloud
 
The Essentials Of Test Driven Development
The Essentials Of Test Driven Development The Essentials Of Test Driven Development
The Essentials Of Test Driven Development Rock Interview
 
Behavior Driven Development—A Guide to Agile Practices by Josh Eastman
Behavior Driven Development—A Guide to Agile Practices by Josh EastmanBehavior Driven Development—A Guide to Agile Practices by Josh Eastman
Behavior Driven Development—A Guide to Agile Practices by Josh EastmanQA or the Highway
 
How BDD enables True CI/CD
How BDD enables True CI/CDHow BDD enables True CI/CD
How BDD enables True CI/CDRoger Turnau
 
Behavior Driven Development with AngularJS & Jasmine
Behavior Driven Development with AngularJS & JasmineBehavior Driven Development with AngularJS & Jasmine
Behavior Driven Development with AngularJS & JasmineRemus Langu
 
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
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Developmentbhochhi
 
Test-Driven-Development.pptx
Test-Driven-Development.pptxTest-Driven-Development.pptx
Test-Driven-Development.pptxdheeraj438799
 
Topic tdd-and-bdd b4usolution
Topic tdd-and-bdd b4usolutionTopic tdd-and-bdd b4usolution
Topic tdd-and-bdd b4usolutionHoa Le
 

Similar to xUnit and TDD: Why and How in Enterprise Software, August 2012 (20)

Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
 
Cleaner Code Through Test-Driven Development
Cleaner Code Through Test-Driven DevelopmentCleaner Code Through Test-Driven Development
Cleaner Code Through Test-Driven Development
 
Understanding Unit Testing
Understanding Unit TestingUnderstanding Unit Testing
Understanding Unit Testing
 
TDD - Agile
TDD - Agile TDD - Agile
TDD - Agile
 
BDD presentation
BDD presentationBDD presentation
BDD presentation
 
Test Driven Development - Overview and Adoption
Test Driven Development - Overview and AdoptionTest Driven Development - Overview and Adoption
Test Driven Development - Overview and Adoption
 
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
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference Card
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit Testing
 
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
 
The Essentials Of Test Driven Development
The Essentials Of Test Driven Development The Essentials Of Test Driven Development
The Essentials Of Test Driven Development
 
Behavior Driven Development—A Guide to Agile Practices by Josh Eastman
Behavior Driven Development—A Guide to Agile Practices by Josh EastmanBehavior Driven Development—A Guide to Agile Practices by Josh Eastman
Behavior Driven Development—A Guide to Agile Practices by Josh Eastman
 
How BDD enables True CI/CD
How BDD enables True CI/CDHow BDD enables True CI/CD
How BDD enables True CI/CD
 
Behavior Driven Development with AngularJS & Jasmine
Behavior Driven Development with AngularJS & JasmineBehavior Driven Development with AngularJS & Jasmine
Behavior Driven Development with AngularJS & Jasmine
 
TDD in Agile
TDD in AgileTDD in Agile
TDD in Agile
 
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 ...
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Test-Driven-Development.pptx
Test-Driven-Development.pptxTest-Driven-Development.pptx
Test-Driven-Development.pptx
 
Topic tdd-and-bdd b4usolution
Topic tdd-and-bdd b4usolutionTopic tdd-and-bdd b4usolution
Topic tdd-and-bdd b4usolution
 

Recently uploaded

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 

Recently uploaded (20)

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 

xUnit and TDD: Why and How in Enterprise Software, August 2012

  • 1. JUnit and Test Driven Development: Experiences in MDM CS 2003 to 2012 Justin Gordon Enterprise TDD Evangelist Senior Software Engineer IBM, Master Data Management Collaboration Server gordonju@us.ibm.com justin.gordon@gmail.com http://www.tddtips.com https://github.com/justin808/dof
  • 2. Author background  BA Harvard Applied Mathematics, MBA UC Berkeley  Writing Java Enterprise Software since 1996  Engineer at Trigo, acquired by IBM  Product now called InfoSphere Master Data Management Collaboration Server. Led rewrite of storage layer doing using TDD  Founder and author of Open Source Project “Dependent Object Framework”  Outside of programming, interests include my kids, surfing, standup paddling, my dogs, cycling, and home improvement. Check out the house I designed and built: http://www.sugarranchmaui.com.  Speaker SD West 2008, Architecture and Design World 2008, and SD Best Practices 2008. See my blog for notes! (http://www.tddtips.com)  Please tell me about your challenges and maybe I can help 2
  • 3. Success Factors  Nature of the project – Existing, legacy, and not designed for testing? – New code – How many dependencies and how containable?  Motivation of the team – TDD is hard work!  Learning – There's a ton to learn about writing good tests. Lots of patterns. Lots of pitfalls. – Recommended: xUnit Test Patterns, but it's huge, and Kent Becks original book “Test Driven Development by Example”  Measurement is key – Continuous Integration including Code Coverage Reports  Benefits – Quality! – Sanity for the overall team, including developers, QA, and managers  Test First Code – Really affects the overall structure of the code, as code is written to be testable.  Most important overall is to have automation tests! 3
  • 4. Summary of MDM CS JUnit  Check out my blog articles, especially this one:  JUnit and Test Driven Development for MDM CS -- Fixtures and Factories – Serialization development was perfect for jUnit – High algorithmic complexity, limited outside dependencies  Rest of the product for jUnit – Challenging due to very complex database interactions – Led to the open source project Dependent Object Framework which works on the problem of test fixture setup – Big problem was that developers confused the usage of the framework in terms of how to use the true fixtures versus setting up scratch objects. – Good article on the subject of fixtures and factories for ruby testing: Fixture vs. Factories - Can't we all just get along. 4
  • 5. Presentation given at SD West, 2009 JUnit and Test Driven Development: Why and How in Enterprise Software 5
  • 6. Roadmap Conventional versus Agile JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 6
  • 7. Conventional versus Agile CONVENTIONAL Architects  High Level Design (HLD)  Detailed Technical Design (DTD)  Coding  QA & Bug Fixing  Regressions  More QA & Bug Fixing  Major Release  Bug Fixing  Regressions  Bug Fixing  Minor Release … Painful mess! Unhappy developers, unhappy customers, unhappy managers! AGILE Stories and Requirements  Simple Specs  Write JUnit (automated) tests in Conjunction with Source  Ensure code coverage  Refactoring to make code better  QA  Limited bug fixing with JUnit tests for each bug fixed  Almost no regressions!  Performance tuning with confidence  Release  Very few bugs  Happy developers, happy customers, happy managers! 7
  • 8. Premise “A comprehensive suite of JUnit tests is one of the most import aspects of a software project because it reduces bugs, facilitates adding new developers, and enables refactoring and performance tuning with confidence. Test-driven development (TDD) is the best way to build a suite of tests. And the Dependent Object Framework is the best way to test against database objects.” Justin Gordon 8
  • 9. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 9
  • 10. JUnit Tests: What?  JUnit test: a method, written in Java, that verifies the behavior of an individual unit of code, or occasionally of a larger subsystem, and reports errors in an automated fashion. public void testAddReturnsSum() { int sum = Calculator.add(2, 3); assertEquals(5, sum); } 10
  • 11. JUnit Tests: Why?  If JUnit tests pass and code coverage is high  Nearly Bug-Free Code!  When JUnit tests cover requirements and tests pass  Code is Complete!  JUnit tests facilitate automatic test running to detect regressions instantly during bug fix cycles. Can’t do that with manual QA! Can’t do that with QA Automation tools!  Enables Courage and Creativity  Developers (experienced and new) can change the code with confidence, enabling – Refactoring – Performance Tuning – JUnit tests serve to document and demonstrate the API  Large team sizes, offshoring, complexity 11
  • 12. Catch 22: Why not write JUnit tests?  “Normal” development cycle inhibits JUnit test creation  Catch-22: existing quality is low, so developers are too busy fixing problems found in the field to write tests.  (Bad) Attitude: “It’s QA’s job to find my bugs. I don’t have time to write tests.”  Skills: tough to learn how to write JUnit tests for new code. Many new patterns!  Even tougher for old code!  Unless existing code is designed for testability, implementing JUnit tests is very difficult. Really Tough! 12
  • 13. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 13
  • 14. What is Test Driven Development (TDD)? “Programming practice in which all production code is written in response to a failing test.” List Requirements Refactor to eliminate code Write One Test smells (e.g., duplicated code) Run Test to Make Sure It Fails Add or modify just enough code to make new test pass and all previous tests pass Read Kent Beck’s: “Test Driven Development By Example” 14
  • 15. What Is Not Test Driven Development?  Any time you write code that is not fixing a failing test.  I.e., Writing code, then writing tests or intending to eventually write tests.  Relying on QA to automate their manual tests.  Be honest when trying this.  Conventional Big Up Front Design is not TDD! 15
  • 16. Why TDD  Code Coverage & Better Code  Guarantees existence of JUnit tests covering most, if not all of your code!  Guarantees code will be written to be testable. – Reverse is also true: if you write your code first, and then your tests, you may have difficulty writing tests for the new code, and then you may not write the tests at all! More natural to write untestable code unless tests written at the same time.  Solves the motivation problem. Test writing becomes part of the coding process, not a tedious afterthought.  Produces better code: more decoupled, with clearer, tighter contracts.  Tests are the canary in the coal mine! Bad designs show up as hard to test! 16
  • 17. Shooting hoops? Practice Makes Perfect  Developers improve skills because of the immediate feedback from the tests, rather than months later from QA! Write Test Write Code  Academic study confirms higher quality code: “An Initial Investigation of Test Driven Development in Industry” by Boby George and Laurie Williams, 2003, http://collaboration.csc.ncsu.edu/laurie/Papers/TDDpaperv8.pdf  TDD developers took more time (16%), but non-TDD developers did not write adequate automated test cases even though instructed to do so! 17
  • 18. Does Test First Matter?  Goal is Automated Unit Test Coverage  Your choice how you get there  Sometimes, you already have lots of code! So too late for pure TDD!  So…  Consider a broader definition of TDD…  Not just “Test First Programming”  But delivering code with unit tests  You want automated test coverage as code is delivered! 18
  • 19. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 19
  • 20. Making it Happen: Tools for Success  IDEs: Eclipse, RSA, RAD, and IntelliJ offer these essentials: – Ease of use to run a single new test – Refactoring tools.  Code Coverage – Now built into Eclipse (EclEmma) and IntelliJ – Clover or Emma are the most popular. – How do you know how good your tests are? – Measure progress for morale (and management reports).  Continuous Automation – Jenkins, Cruise Control, or BuildForge – Automated system for building code, running JUnit tests and reporting on code coverage. – Alerts team of issues (build or JUnit) within minutes of checkins  Mock Objects: Mockito  Dependent Object Framework – Ease of writing JUnit tests in the context of persistent objects → helps setup database fixtures 20
  • 21. Code Coverage Inside Eclipse Code Coverage in Eclipse provided by EclEmma: http://www.eclemma.org Green lines indicate coverage by unit tests. Pink lines indicate code not covered by unit tests 21
  • 22. Exercise 1: Simple TDD: Compute Change Coins public class Change Problem: Compute Change Coins { public int pennies, nickels, dimes, quarters;  Coins include: pennies, nickels, public Change(int pennies, int nickels, int dimes, int quarters) { dimes, quarters this.pennies = pennies;  Machine may be out of any coin this.nickels = nickels; this.dimes = dimes; except pennies this.quarters = quarters;  Give least number of coins } public class VendingMachine Example: { // the number of coins left All coins available: public int pennies, nickels, dimes, quarters;  37 cents: 1 quarter, 1 dime, 2 public Change getChange(int cents) { … } pennies }  80 cents: 3 quarters, 1 nickel public class VendingMachineTest extends TestCase { No nickels: public void testGetChangeReturnsNoChangeIfNoCents)  80 cents: 2 quarters, 3 dimes { … } } No dimes:  85 cents: 3 quarters, 2 nickels 22
  • 23. Exercise 1 Tips  Only add code after adding a test that fails!  Do bare minimum to make tests pass  Patterns: Naming Test Methods – test{MethodName}Returns{Value}When{Condition} – testGetChangeReturnsZeroWhenNoCents – testGetChangeReturnsThreeQuartersOneNickelWhenEightyCents – test{MethodName} {DoesSomething}When{Condition} – testGetChangeThrowsWhenCentsLessThanZero – Why such long method names? 1. Method names print out in test failures 2. Programmers never call these methods – Directory Structure – src: Where production code goes – junit:Where junit tests go, use parallel package structure to test package and protected methods.  Implement equals() so that we can compare Change objects. – Implement toString() so that error messages are clear 23
  • 24. Exercise 1: Steps for “Initial” example 1. Run VendingMachineTestSuite to see all tests run 2. Run the test suite with code coverage turned on to see code coverage 3. Uncomment Change.toString() to see effect on the error message  implement toString() for better messages 4. Uncomment Change.equals() to see VendingMachineTest tests pass. 5. Put @Ignore in front of failing test and run all tests to see that no failures and 2 ignored tests 24
  • 25. Exercise 1b: Steps for “Intermediate” 1. Check out the triangulation method of verification. 2. Fix the test testGetChangeReturnsThreePenniesIfTwoCents() 3. Check out the use of the @Before setup of the variable VendingMachine 4. Complete the rest of the commented tests 5. Handle the tougher cases where the vending machine can run out of a certain kind of coin Question: Can we exhaustively find all the solutions and check the code against these solutions? Possibly could write tests to use triangulation. 25
  • 26. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 26
  • 27. Architectural benefits of TDD Without TDD, you often see tight coupling between Tight Coupling! classes and throughout to all dependencies, making the D A implementation of new tests prohibitively painful. class B  With TDD E interface C  Better abstractions and better decoupling of classes. Loose Coupling: TDD!  Loose coupling, otherwise impossible to test individual components. A  When using “Test Doubles” (e.g., test stubs and mock objects), you want to bb cc dd mock out smaller APIs or else you’ll work too hard! Keep classes small B e C and methods tight. D 27
  • 28. Test Doubles  Test Doubles: Fakes, Stubs, Mocks – see “xUnit Test Patterns” by Meszaros  Reasons to use Test Doubles – Isolates code for testing! – Awkward to setup for JUnit test – e.g. web services – Not available (or not yet written) – new component in large project – Too slow (less so now with in-memory DBs like H2)  Reasons to not use Test Doubles – Extra code to maintain that is only used for testing – Difficult to refactor code to use test doubles – You still need to test the delivery code! – Don’t mock out the database! 28
  • 29. Making it Happen: Isolating Code for Testing  Note – Mock objects are a form of test double and the name is used interchangeably here  Successful TDD depends on dependency isolation – you need to separate the code to be tested from the rest of the system. – This is THE main technical challenge, esp. for database and integration points – Must decouple classes with interface/implementation/mock object pattern – Use a combination of dependency location and/or dependency injection for dependencies (following slides) – Typically mocking out a dependency on a clearly defined component, such as an object that would call a web service. – Difficult to do TDD without using test doubles (or using the Dependent Object Framework) – Tip: minimize business logic in mock objects because you have to duplicate that logic in the real implementation. Refactor code to minimize business logic in mock classes. Dependency Interface Class To Test (Runtime Object) Dependency (Test Double, e.g. Mock Object) 29
  • 30. Dependency Isolation: Static Location  Example: Class fetches data from the database or from a mock source. But how does your code get a handle to the correct Component? Dependency location: your class looks up the dependency (test double or real instance) from a known location, typically a static method call Test setup code: // note, setTaxRateProvider takes interface TaxRateProvider GlobalContext.setTaxRateProvider(new MockTaxRateProvider()); Production setup code: GlobalContext.setTaxRateProvider(new SoapTaxRateProvider()); Production Code sees interface  does NOT know if real or test double!! class OrderProcessor Static method public float getTaxRateForState(String state) { returns interface! TaxRateProvider taxRateProvider = GlobalContext.getTaxRateProvider(); return taxRateProvider.getSalesTax(state); } See: “Inversion of Control Containers and the Dependency Injection pattern”: http://www.martinfowler.com/articles/injection.html 30
  • 31. Dependency Isolation: Constructor/Setter Injection  Dependency Constructor/Setter Injection: Pass a reference to the dependency in the constructor (or a setter):  Test setup code: // note interface TaxRateProvider TaxRateProvider mockTaxRateProvider = new MockTaxRateProvider(); OrderProcessor orderProcessor = new OrderProcessor(mockTaxRateProvider)  Production code: TaxRateProvider soapTaxRateProvider = new SoapTaxRateProvider()); OrderProcessor orderProcessor = new OrderProcessor(soapTaxRateProvider)  InvoiceComponent class does NOT know if it has a real or mock persistence object Member interface class OrderProcessor { variable! TaxRateProvider taxRateProvider; // constructor injection OrderProcessor (TaxRateProvider taxRateProvider ) { this.taxRateProvider = taxRateProvider; } public float getTaxRateForState(String state) { return taxRateProvider.getSalesTax(state); } 31
  • 32. Dependency Injection versus Service Locator “Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative… The key difference is that with a Service Locator every user of a service has a dependency to the locator. The locator can hide dependencies to other implementations, but you do need to see the locator. So the decision between locator and injector depends on whether that dependency is a problem. A lot of this depends on the nature of the user of the service. If you are building an application with various classes that use a service, then a dependency from the application classes to the locator isn't a big deal….The difference comes if the lister is a component that I'm providing to an application that other people are writing. In this case I don't know much about the APIs of the service locators that my customers are going to use. Each customer might have their own incompatible service locators. I can get around some of this by using the segregated interface. Each customer can write an adapter that matches my interface to their locator, but in any case I still need to see the first locator to lookup my specific interface. And once the adapter appears then the simplicity of the direct connection to a locator is beginning to slip. Martin Fowler http://martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection 32
  • 33. Mockito Highly recommended! First, you have to isolate dependencies. Then mock: http://code.google.com/p/mockito/ 33
  • 34. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 34
  • 35. Basic Phases of an xUnit Test Setup Prepare Test Fixtures -- Get xUnit Test Application State Ready To Do Something DB Objects and the DOF Exercise Do Something With Fixtures Prefer Single Action Verify Check Something Happened: assertSomething() Teardown Restore application state for next test 35
  • 36. Database Issues  Database is like a global variable that is slow to access!  Actually worse than a global variable because it lives between test runs!  Stickiness of data collides with xUnit philosophy of atomic/independent tests!  DB “Fixture” Setup without the DOF – Java code – SQL scripts – DB Backups  Issues: Difficult, Monolithic, fragile, frustrating, slow – Greater possibility of slow and erratically failing tests  Test fixtures often include objects that are persisted in the DB. I.e., in order to run a test, some values must exist in the DB, and a test may create some new records in the DB. 36
  • 37. Why have xUnit tests hit the database?  Production code for end users will hit the DB, so you need to test it!  Catch 22: Refactor in order to isolate database dependencies to build tests, but without tests, how safely can we do the refactoring?!  Mocks and stubs add (much) more code to maintain (and to fix bugs!).  Reliance on mocks and stubs can mask errors with using the DB.  Annecdote: GuideWire Software used to depend heavily on stubs and dependency isolation techniques, but now focuses exclusively on tests against the database, using H2 in-memory DB to speed up tests. 37
  • 38. DOF: What Problem Does it Solve?  Setup of the DB in a “lazy” and “modular” fashion as needed by each test – Only populate what is needed for a test – Test does not worry if DB already populated  Clarity of the DB setup required for a test – See clearly DB objects needed for a test  Establishes a clear pattern for teamwork and reusability behind the DB setup 38
  • 39. Simple Example – Logical Model Logical Object Model Invoice Defines object relationships behind the DOF setup but the DOF setup is about the instances of these objects Customer Product that have representations in the database Manufacturer 39
  • 40. Data Relationships and Object Creation With DOF, test Invoice 1001 only specifies top level dependency! Customer Jones Objects Created Product Orange Juice DOF takes care ensuring these DB Product Grape Juice backed objects are ready for your test Manufacturer Ocean Spray 40
  • 41. Object Dependency Processing: Java Reference Object Your test code DOF plumbing Your ReferenceBuilder code ReferenceBuilder rbOrangeJuice = new Product_OrangeJuice(); Product orangeJuice = (Product) DOF.require(productOJ); Return Object “Orange Juice” Object pk = rbOrangeJuice.getPrimaryKey() Check cache for Orange Juice object OJ Found in Cache OJ Not Found Call rbOrangeJuice.fetch() to check DB for primary key “Orange Juice” OJ Found in Database OJ Not Found Call rbOrangeJuice.create() You persist the Orange Juice object ReferenceBuilder rbTropicana = new Manufacturer_Tropicana(); with foreign key to Tropicana Manufacturer tropicana = DOF.require(rbManufacturerTropicana); Check cache, maybe call rbTropicana.fetch() Tropicana Found Tropicana Not Found Call rbTropicana.create() You persist the Tropicana object 41
  • 42. Principles of Test Automation for the DOF  From Meszaros, “xUnit Test Patterns” – Highly recommended!  “Keep Tests Independent” – Any test can run on its own or with other tests in any order. Independent test failures easiest to reproduce and fix! – With the DOF, you can run test in any order and on a clean or existing DB schema – Absolute nightmare having giant DB setups for tests  “Communicate Intent” -- minimize code and avoid logic in tests (if statements) – DOF hides the messy setup of preparing objects – Test reader sees only objects involved directly in a test  “Don’t Modify the SUT” -- prefer testing the production code – SUT = System Under Test – your production code – DOF supports tests against “production” code which hits the database 42
  • 43. Technique: Scratch Objects Motivation: Avoid erratic tests that have database dependencies Cause: Multiple tests depend on and modify the same objects in the database, and thus the tests sometimes fail because of uncertain database state Solution: Always use a fresh primary key for objects created in a test private Customer getNewUniqueCustomer() { Customer customer = new Customer(); // Example of pattern to create unique PKs customer.setName(System.currentTimeMillis() + ""); customerComponent.insert(customer); return customer; } 43
  • 44. In-Memory DBs for Testing  Fixture setup for test class (not per test!) – Load frozen copy of DB – Load data into tables – Understand that test may interact with each other in the data for a given test class  Breaks the “atomic” model of JUnit tests – This solution is a little like using lock striping, or maybe the way that conferences might break up the registration lines by first letter of last name. – All tests are not atomic – But groups of tests together form one “batch” where they get the database to interact with.  Options – H2 – supposedly the fastest – HSQLDB – Hibernate examples are based on HSQLDB  See article on blog: http://justingordon.org 44
  • 45. Dependent Object Framework  Open source project with EPL License: http://sourceforge.net/projects/dof  Problem: setup of required persistent (DB) objects for JUnit tests  Objectives: – Ease of test fixture setup: – Simply list dependencies for a test. – Support both “reference” objects and “scratch” objects – Performance: Tests must run quickly—Cache reference objects in memory – Tests are stable – run any number of times in any order – Easily distinguish between reference (shared) objects and scratch (unique, non- shared) objects – Either use “files and associated handlers” or “Java” to define objects – Support deletion/garbage collection of created objects  Author: Justin Gordon based on technique used in product MDM Server for Product Information Management 45
  • 46. Roadmap A tale of two development groups JUnit Tests Test Driven Development Tools TDD Architecture Database Techniques: DOF Getting Started 46
  • 47. Making it Happen: Dealing with Legacy Code  If only we could write everything from scratch again!  Expect islands of old, untested, and untestable code – UI code tends to be particularly problematic – Most legacy code will be essentially untestable  Try piecewise remodeling – Discard old modules one-by-one, replacing with TDD code  Try “encrapsulation” – Wall off legacy junk behind a façade interface (if possible; sometimes not) – Mock out legacy code when testing new modules Clean CRAP Interface 47
  • 48. Pair Programming and TDD  Complementary: Pair Programming helps with TDD  Big aid in learning TDD  One person thinks strategically, encourages the “coder” to write tests before the implementation. – “Don't write a line of code that doesn't fix a failing test.”  Pairing allows collaboration on solving dependency isolation issues, along with other issues in getting first tests to run.  Once there's a body of tests to use as examples, pair is less necessary.  Highly recommended when a team is learning TDD. 48
  • 49. Making it Happen: Getting the Team Started Get Beck’s “Test Driven Development”, start up your IDE and do TDD! Or try to recreate my accounting example. Solidify commitment at every level of the organization – TDD slower for first 6 months; net speedup afterwards. – Don’t expect to hold the same schedule and “just add testing”! – Systematically discover and eliminate obstacles. – TDD takes discipline. Align incentives, communication, work environment – everything Consider using the Dependent Object Framework – Will avoid need to create too many mock objects Start with a new project or pick a subproject – TDD can be done against existing code, but MUCH harder – Focus on lower levels of the system first Allow extra time – for learning: there are many new skills and patterns to pick up. – for re-architecture: existing architecture probably doesn’t support testing Expect discomfort at first – developers not used to working this way. Your best – Start with a few respected “early adopters” and a trial run bet! 49
  • 50. WASSUP? How enterprise projects without automated tests can end up after 8 years! http://www.youtube.com/watch?v=Qq8Uc5BFogE 50
  • 51. Your Challenges?  What are some of the biggest hurdles your projects face in becoming “Test Driven”?  E-mail me with your challenges with TDD and maybe I can help.  I’m not a formal consultant, but looking for material for my book in terms of real world enterprise problems and solutions in this area, and maybe you can benefit.  Try out the DOF and I’d be happy to help. 51
  • 52. Conclusion  How would you choose between a project with awesome JUnit tests and a project without JUnit, but lots of great architectural documents and other documentation? I’d take the JUnit one hands down.  Documentation gets out of date quickly. Code without tests may be quite buggy, and even if it’s not buggy, would I trust myself to join a project and not introduce bugs without JUnit?  Having a comprehensive suite of JUnit tests is the most import piece of intellectual property in a software project.  Why? First you have very few bugs. Second, developers, new and old, can change the code with confidence because they know immediately if they break something. This enables the two most important activities in a software project. – Refactoring – Performance Tuning  And TDD is the best way to get that suite of tests (with the DOF for DB testing)!  Thank you for listening! http://sourceforge.net/projects/dof http://justingordon.org justingordon@yahoo.com 52
  • 53. Resources Justin Gordon justin.gordon@gmail.com http://www.tddtips.com https://github.com/justin808/dof  Just Do It! You cannot just read books on it! Just Do It!  Use Eclipse or IntelliJ and try doing TDD on a simple example  Gerard Meszaros – “xUnit Test Patterns”  Kent Beck – “Test Driven Development”, “Extreme Programming Explained”  Lasse Koskela – “Test Driven: TDD and Acceptance TDD for Java Developers”  Martin Fowler, especially “Refactoring: Improving the Design of Existing Code”  Michael Feathers “Working Effectively with Legacy Code” 53
  • 54. Extras… 54
  • 55. Persistent Test Fixture Strategy  Purpose of the DOF is Persistent Test Fixture Setup  Keep the test clear by separating the “fixture” (setup of test) from the “test”  Shared Test Fixture – Shared among multiple tests – Addresses Performance Issues of creating objects for each test – Must be immutable or else erratic tests  Fresh Test Fixture (Scratch Objects) Scratch – Uses unique identifier so no collisions Objects – Used for objects your test will modify – String pk = System.currentTimeMillis() + “”; 55
  • 56. “Reference” Objects versus “Scratch” Objects  “Reference Objects” are – “Shared Persistent Test Fixtures” Reference – Background data for a test Objects – Loaded once and cached  SUPER for PERFORMANCE – Must not be changed by tests – immutable! – Reference and Scratch objects can “refer” to (have foreign keys) to either other “reference” objects or “scratch” objects  “Scratch Objects” – “Persistent Fresh Fixtures” Scratch – These are what the test modifies Objects – Only visible to a single test for a single test run – Run test multiple times and new scratch objects are created – Must be given a unique keys (i.e., timestamp string) – Can refer to reference objects or scratch objects – Ensures that tests don’t interfere with each other  no erratic test runs! 56
  • 57. DOF Basic Concepts  One file (or Java class) per object definition.  DOF takes care of recursive object creation. Thus, object dependencies are ONLY listed in an object’s definition file (or class), never in a test. – I.e., if object A depends on object B, you should NEVER need to specify both object B and object A in a test. Definition of object A specifies that it depends on object B.  Best practices for use of the DOF – Each developer has own database. – Simple script for populating a clean schema.  Critical to avoid changing reference objects, otherwise tests become erratic and unstable  You can choose “Java” or “Text Files” or any combination to define objects.  Deletion (garbage collection) of created objects is available, but discouraged (see next slide). 57
  • 58. Java or Text Definitions for Objects?  Java Builder Pattern – Create one Java class per reference object of scratch object definition – Implement interface ReferenceBuilder or ScratchBuilder – Advantage: – Full support of IDE for refactoring and navigation – More flexibility with Java code for each object – More explicit object creation – Disadvantage: Can be very verbose compared to a properties file or XML  Text Files and Associated Handlers – For each class (file type), write a handler class that implements interface DependentObjectHandler – Create one file per reference object or scratch object – DOF takes care of the plumbing – Advantage: More concise format – Disadvantage: Can be awkward if changes are needed  Use of Java and Text are not exclusive! Interoperable! 58
  • 59. DOF FAQ  How is this different from DBUnit? – DBUnit focuses on DB rows. DOF focuses on object dependencies  Does the DOF only work with database dependencies? – No. Dependencies can be anywhere, such as with web services.  Should I use an in-memory DB? – Being able to switch your DB from Oracle or DB2 to an in-memory one for testing is highly recommended for speeding up test execution. Check out H2 and HSQLDB.  I work on a shared DB and I can’t simply recreate the schema. Help! – No problem. Make sure that you run DOF.deleteAll(DOF.DeletionOption.all) when you tear down your tests. If you do that, you will avoid adding any records to the DB. 59

Editor's Notes

  1. Justin
  2. Wikipedia: http://en.wikipedia.org/wiki/Refactoring In software engineering, the term refactoring means modifying source code without changing its external behavior, and is sometimes informally referred to as "cleaning it up". In extreme programming and other agile methodologies refactoring is an integral part of the software development cycle: developers alternate between adding new tests and functionality and refactoring the code to improve its internal consistency and clarity. Automated unit testing ensures that refactoring does not make the code stop working. Refactoring does not fix bugs or add new functionality. Rather it is designed to improve the understandability of the code or change its structure and design, and remove dead code, to make it easier for human maintenance in the future. In particular, adding new behavior to a program might be difficult with the program's given structure, so a developer might refactor it first to make it easy, and then add the new behavior. An example of a trivial refactoring is to change a variable name into something more meaningful, such as from a single letter 'i' to 'interestRate'. A more complex refactoring is to turn the code within an if block into a subroutine. An even more complex refactoring is to replace an if conditional with polymorphism. While "cleaning up" code has happened for decades, the key insight in refactoring is to intentionally "clean up" code separately from adding new functionality, using a known catalogue of common useful refactoring methods, and then separately testing the code (knowing that any behavioral changes indicate a bug). The new aspect is explicitly wanting to improve an existing design without altering its intent or behavior.
  3. “ Normal” development cycle inhibits JUnit test creation Developers rewarded for getting something “working” ASAP Code like mad to meet a deadline (DCut?); testing is an afterthought Throw it over the fence to QA and fix bugs as they’re found Motivation to write tests for “already-working” code is low! Inertia : hard to change ingrained working habits
  4. Ask about purity of TDD in practice.
  5. Any time you write code that is not fixing a failing test. I.e., Writing code, then writing tests or intending to eventually write tests. No matter how good they are! Relying on QA to automate their manual tests. Especially using SilkTest or similar. Be honest when trying this. If it isn’t TDD, you won’t get the benefits What about the conventional approach of have the architects design the APIs, the developers code to the specs, and QA tests? Is that TDD?
  6. You cannot do TDD without the right tools Emacs or VIM??? These do not support single test running and refactoring,
  7. Note – this slide should be skipped in a short presentation. In a longer presentation, this material will be reviewed several times.
  8. Note – this slide should be skipped in a short presentation.
  9. The setup and teardown boxes are grey to indicate that the reader of the test should be able to focus on the logic of what is done and what is verified (orange boxes)
  10. Production code for end users will hit the DB, so you need to test it! Conventional Wisdom: Real xUnit tests don’t use a DB! But, developers are working on existing codebases that have countless intricate ties to the DB. Common advice is to refactor in order to isolate database dependencies in order to build tests that don’t hit the database, but without tests, how safely can we do the refactoring? Catch 22! Mocks and stubs add (much) more code to maintain (and to fix bugs!). Reliance on mocks and stubs can mask errors with using the DB. Annecdote: GuideWire Software used to depend heavily on stubs and dependency isolation techniques, but now focuses exclusively on tests against the database, using H2 in-memory DB to speed up tests.
  11. This slide tells its story via animation. If you’re reading this slide, then the “blinds” effect means “check” for this object and “pinwheel” means “create the object”
  12. Discuss this slide first with the DOF plumbing and then as if there was no DOF plumbing.
  13. Performance checks if the object with the path was already run, and if so, nothing is done. Then checks if given named object exists in the DB. The name is decoded from the path name. If the name exists, the script is not run.