SlideShare une entreprise Scribd logo
1  sur  60
Télécharger pour lire hors ligne
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




             Improving tests with Obj t
             I      i g t t ith Object
               Mothers and Internal DSLs

                                Chris i h d
                                Ch i Richardson
                           Author of POJOs in Action
                            Founder of Cloud Tools
         http://www.chrisrichardson.net
         htt //      h i i h d        t

                            11/10/2008


Chris Richardson — Improving tests with Object Mothers and DSLs                                    1
Colorado Software Summit: October 19 – 24, 2008                                                              © Copyright 2008, Chris Richardson




                  Overview


                                Writingg
                               maintainable
                                  tests

                                                           Copyright (c) 2008 Chris Richardson. All rights                             2
Chris Richardson — Improving tests with Object Mothers and DSLs                                reserved.                            11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                    © Copyright 2008, Chris Richardson




                About Chris
                                                                  Grew up in England and live in Oakland, CA
                                                                         p     g                        ,
                                                                  Over twenty years of software development
                                                                  experience
                                                                      Building object-oriented software since 1986
                                                                      Using Java since 1996
                                                                      Using J2EE since 1999
                                                                  Author of POJOs in Action
                                                                  Speaker at JavaOne, SpringOne, NFJS, JavaPolis,
                                                                  Spring Experience, etc.
                                                                  Chair of the eBIG Java SIG in Oakland
                                                                  (www.ebig.org)
                                                                  (www ebig org)
                                                                  Run a consulting and training company that helps
                                                                  organizations build better software faster and
                                                                  deploy it on Amazon EC2
                                                                  Founder of Cloud Tools, an open-source project
                                                                  for d l i
                                                                  f deploying J Java applications on Amazon EC2:
                                                                                         li ti       A        EC2
                                                                  http://code.google.com/p/cloudtools




Chris Richardson — Improving tests with Object Mothers and DSLs                                                               Slide 3
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Agenda
       Tests - a double-edged sword
                 double edged
       Taming test fixture logic
       Simplifying verification code
       Writing web tests
       Testing Ajax applications




                                                                                            4
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Why test?
       Write new code more easily
              A t     t    h t
              Automates what we are doing already -
                                       d i      l d
              Right!?
              Run fast unit tests instead of slower
              web application
              Use TDD to incrementally solve a
              problem
       Tests are a safety net
              Confidently change existing code
              Easier to refactor code to prevent decay
       Fewer bugs that impact customers
       AND development


 Copyright (c) 2008 Chris Richardson. All rights
                                     reserved.
Chris Richardson — Improving tests with Object Mothers and DSLs                              11/10/2008
                                                                                                  5
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Why test?
       Increases longevity:
                    g    y
              Testable code is cleaner code
              Without tests your application will decay
                            y      pp                 y
              and die
       Absolutely essential when using a
       dynamic l
       d        language
              Compiler can't catch typos
              Nothing is too simple to test
              You need unit tests


Chris Richardson — Improving tests with Object Mothers and DSLs                              11/10/2008
                                                                                                  6
Colorado Software Summit: October 19 – 24, 2008                                             © Copyright 2008, Chris Richardson




                  4 phase tests
                                                                  public class FooTest
                                                                         extends TestCase {

                                                                      public void setUp() {

       Setupp                                                         }


       Exercise
                                                                      public void testSomething() {
                                                                         // test-specific setup

       Verify                                                             // Exercise the SUT


       Teardown
                                                                          // Verification

                                                                          // test-specific tear down
                                                                             test specific
                                                                      }

                                                                      public void tearDown() {
                                                                      }
                                                                  }

                                                                                                                      7
Chris Richardson — Improving tests with Object Mothers and DSLs                                                    11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Types of tests
            Domain model tests                                                      Easy to write
                                                                                    Fast to run


                   Test your domain objects and
                   services
                   In-memory tests
            Persistence tests
                   Test manipulating persistent objects
            Service integration tests
                   Test services using database
            Web tests
                   Automatic tests using Selenium
                   Click and type in the GUI
                                                                                 Difficult to write
                                                                                 Slow to run

                                                                                            8
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Example tests
       Walk through some example ptrack
       tests




                                                                                            9
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  The trouble with tests
       They make software more difficult to
          y
       change
              That's a good thing since they detect bugs
       But change is inevitable: new features,
       refactoring
       If you can't easily change the test
       code:
              Slows down the development
              Tests are removed or abandoned

                                                                                           10
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Poor quality test code
       Common test code smells
              Obscure T t – you can't tell what a test does
              Ob      Tests            't t ll h t t t d
              Test code duplication – copy and paste tests
       Badly structured test setup logic
              Complicated logic to create test fixtures
              E.g. the test objects (in-memory or in DB)
       Sprawling web tests
        p a    g   b
              Web test framework APIs are very low-level.
              Easily end up with large amounts of difficult to
              maintain code: click(),type(),…
                                  (), yp (),
              Lots of duplication
              Lots of obscure code


                                                                                           11
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                Excellent testing book
          Test smells and how to fix them
                 Obscure test
                 Fragile test
                 Test code duplication
                 …
          Comprehensive pattern language:
                 Four phase test
                 Minimal fixture
                 Test utility method
                 Test helper
                 Humble Objectj
                 …




                                                                                           12
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Agenda
       Tests - a double-edged sword
                 double edged
       Taming test fixture logic
       Simplifying verification code
       Writing web tests
       Testing Ajax applications




                                                                                           13
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  What s
                  What's a fixture
       Fixture = everything that needs to be
                        y   g
       in place to test an object/system
              Object/system we want to test
              Its collaborators, required test data etc
       Fixture is created by test fixture
                           y
       logic:
              Code in the test methods themselves
              Junit 3.x setUp()
              JUnit 4/TestNG @Before* annotations

                                                                                           14
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                The challenge of test fixtures
       Creating an object isn't always easy
              g      j              y     y
              Objects can have lots of attributes
              Objects are often aggregate roots
              new() is often insufficient
       Test fixtures often create multiple objects
              E.g. money transfer test needs two accounts
                              f           d
       Multiple tests need the same set of
       objects
                  • AccountTests, MoneyTransferServiceTests need
                    similar Account objects


                            11/10/2008
Chris Richardson — Improving tests with Object Mothers and DSLs                                  15
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Object graphs can be
                  complicated
                                                                  We need all
                                                                  of these
                                                                  objects to
                                                                  test a
                                                                  Project!




                                                                                           16
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Constructing individual objects
                  can be tricky
       Best way to construct an object is to use
              y                   j
       a non-default constructor:
              Supports objects without setters
              Supports immutable objects
              Forces you to supply all required objects
              Constructor can verify object state
       Limitations of constructors:
              Lots of constructor arguments ⇒ code is
              difficult to read
              Optional arguments ⇒ multiple constructors

                                                                                           17
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                            © Copyright 2008, Chris Richardson




                  The alternative to constructors
        Project project = new Project(initialStatus);
            project.setName(quot;Test Project #1quot;);
            project.setDescription(quot;descriptionquot;);
            project.setRequirementsContactName(quot;Rick Jonesquot;);
            project.setRequirementsContactEmail(quot;jones@nowhere.comquot;);
            project.setType(ProjectType.EXTERNAL_DB);
            project.setArtifacts(new ArtifactType[] {
                ArtifactType.ARCHITECTURE,
                ArtifactType.DEPLOYMENT, ArtifactType.MAINTENANCE });
            project.setInitiatedBy(user);

                                       Benefits:
                                           •Handles optional parameters
                                           •Is more readable
                                       But
                                           •Lots of noise: 'project.set‘
                                           •Breaks encapsulation
                                            Breaks
                                           •Object is mutable
                                           •Cannot validate state
                                                                                                    18
Chris Richardson — Improving tests with Object Mothers and DSLs                                   11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                           © Copyright 2008, Chris Richardson




                Constructing objects fluently
        Project project = new Project(initialStatus)
                .name(quot;Test P j t #1quot;)
                     (quot;T t Project
                .description(quot;Excellent projectquot;)
                .initiatedBy(user)
                .requirementsContactName(quot;Rick Jonesquot;)
                .requirementsContactEmail(quot;jones@nowhere.comquot;)
                     i     t C t tE il(quot;j       @    h      quot;)
                .type(ProjectType.EXTERNAL_DB)
                .artifact(ArtifactType.ARCHITECTURE)
                .artifact(ArtifactType.DEPLOYMENT)
                .artifact(ArtifactType.MAINTENANCE);
                   tif t(A tif tT      MAINTENANCE)
                                              Chained method calls
                                              Benefits:
                                                   •Less noise
                                                   •Meaning of each value is clear
                                                    Meaning
                                              Drawbacks:
                                                   •Breaks encapsulation – objects must have
                                                   mutators/setters
                                                   •Doesn't work with immutable objects
                                                   •No opportunity to validate state
                                                    No


                            11/10/2008
Chris Richardson — Improving tests with Object Mothers and DSLs                                                          19
Fluently creating immutable
Colorado Software Summit: October 19 – 24, 2008                                                     © Copyright 2008, Chris Richardson




                objects
            See
            http://developers.sun.com/learning/javaoneonline
            http://developers sun com/learning/javaoneonline
            /2007/pdf/TS-2689.pdf
         Project project = new Project.ProjectBuilder(initialStatus)
                .name(quot;Test Project #1quot;)
                     (quot;        j
                .description(quot;descriptionquot;)
                .initiatedBy(user)
                .requirementsContactName(quot;Rick Jonesquot;)
                     i       C         il(quot;j
                .requirementsContactEmail(quot;jones@nowhere.comquot;)
                                                @    h      quot;)
                .type(ProjectType.EXTERNAL_DB)
                .artifact(ArtifactType.ARCHITECTURE)
                .artifact(ArtifactType.DEPLOYMENT)
                .artifact(ArtifactType.MAINTENANCE)
                   tif t(A tif tT      MAINTENANCE)
                .make();
                                                             •    Initialize the mutable builder
                                                             •    make() instantiates the domain object via a constructor
                                                             •    Allows entity to be immutable
                                                             •    Builder can validate object state

                                                             This is an internal DSL
                            11/10/2008
Chris Richardson — Improving tests with Object Mothers and DSLs                                                                    20
Nested Entity Builder
Colorado Software Summit: October 19 – 24, 2008                                             © Copyright 2008, Chris Richardson




                example
      class Project {

          public static class ProjectBuilder {
            private String name;
            …

              public ProjectBuilder(Status initialStatus) {
                this.status = status;
              }

              ProjectBuilder name(String name) {
                this.name = name;
                return this;
              }

              public Project make() {
                // Verify that we have everything
                              j   (    );
                return new Project(this);
              }
          }
                                                                  • Pass builder as the sole constructor argument
          public Project(ProjectBuilder builder) {
            this.name = builder.name;
            this.initiatedBy = builder.initiatedBy;
          }

                            11/10/2008
Chris Richardson — Improving tests with Object Mothers and DSLs                                                            21
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Testing makes your objects
                  smarter
       Production code often has simple
                                    p
       requirements:
              Create using default constructor
              Accesses Java bean properties
       But tests need smarter objects
                                j
              E.g. fluent interfaces
              Counter to the concept of not having test
              code in production code
       But this is ok: tests are important

                                                                                           22
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Centralizing test object
Colorado Software Summit: October 19 – 24, 2008                                             © Copyright 2008, Chris Richardson




                creation with Object Mothers
      Fluent interfaces can help
      but                                                         public class ProjectMother {
             Fixture logic can still be
                                                                      public static Project
             complex                                                       makeProjectInProposalState (
             Same object created in                                             Status initialStatus, User user) {
                                                                                                               )
             multiple t t ⇒ d li ti
                lti l tests    duplication                              …
      Eliminate duplication:                                          }

             Centralize object creation in a                          public static Project
             test utility class called an                                makeProjectInRequirementsState(
             Object Mother                                                      Status initialStatus, User user) {
             Defines factory methods for
                                                                          …
             creating fully formed                                    }
             aggregate
             Different methods for different
             aggregate states                                     }

                                    See: http://www xpuniverse com/2001/pdfs/Testing03 pdf
                                         http://www.xpuniverse.com/2001/pdfs/Testing03.pdf


                                                                                                                     23
Chris Richardson — Improving tests with Object Mothers and DSLs                                                    11/10/2008
Creating multiple connected
Colorado Software Summit: October 19 – 24, 2008                                                     © Copyright 2008, Chris Richardson




                aggregates
       Each Object Mother
       method creates a
          th d      t
       single aggregate
       But some tests need
       to create multiple
       aggregates with
       shared sub-
       aggregates
       Must avoid                                                 itDepartment = DepartmentMother.makeItDepartment();


       duplicating that                                           itProjectManager =
                                                                         UserMother.makeProjectManager(itDepartment);

       code in multiple                                            itBusinessAnalyst =
                                                                          UserMother.makeBusinessAnalyst(itDepartment);

       tests                                                      projectInCompleteState =
                                                                         ProjectMother.makeProjectInCompleteState(…);
                                                                  projectInRequirementsState =
                                                                      ProjectMother.makeProjectInRequirementsState(…);
                                                                      P j tM th        k P j tI R     i     t St t ( )
                                                                  …


                                                                                                                             24
Chris Richardson — Improving tests with Object Mothers and DSLs                                                            11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Use stateful object mothers
       Test instantiates object mother
       Object mother's constructor
              Creates aggregates (by calling their Object
              Mothers)
              Stores them in (public) fields
       Test gets the data it needs from the
       object mother


                                                                                           25
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                         © Copyright 2008, Chris Richardson




                   Example of a stateful mother
                                                                  public class ProjectTests extends TestCase {


   public class PTrackWorld {                                      private Project project;
                                                                   private User projectManager;
       private   final   Department itDepartment;                  private User businessAnalyst;
       private   final   User itProjectManager;
                                                                   protected void setUp() throws Exception {
       private   final   User itBusinessAnalyst;                     PTrackWorld world = new PTrackWorld();
       private   final   Project projectInCompleteState;             projectManager = world.getItProjectManager();
                                                                     businessAnalyst = world.getItBusinessAnalyst();
       …                                                             project = world.getProjectInProposalState();
                                                                   }
       public PTrackWorld() {
        itDepartment = DepartmentMother.makeItDepartment()'
                        DepartmentMother.makeItDepartment()

           itProjectManager = UserMother.makeProjectManager(itDepartment);
           itBusinessAnalyst = UserMother.makeBusinessAnalyst(itDepartment
            …
           stateMachine = DefaultStateMachineFactory.makeStateMachine(quot;defaultquot;);
           initialStatus = stateMachine.getInitialStatus();
           projectInCompleteState = ProjectMother.makeProjectInCompleteState(initialStatus,
                                               itProjectManager, getAllITDepartmentEmployees());
           …
       }

   }


                                                                                                                                 26
Chris Richardson — Improving tests with Object Mothers and DSLs                                                                11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                             © Copyright 2008, Chris Richardson




                  Object Mothers and databases
       Initialize database                                        public class PtrackDatabaseInitializer
       using objects
         i      bj t                                                implements InitializingBean, DatabaseInitializer {

       created by                                                     private HibernateTemplate template;
                                                                      private PTrackWorld world;
       mothers                                                        public PtrackDatabaseInitializer(HibernateTemplate

              Create objects                                            this.template = template;
                                                                                                     template) {


              using mothers                                           }


              Persist them
                                                                      public void afterPropertiesSet() {
                                                                        initializeDatabase();
                                                                      }
       Very easy when                                                 public void initializeDatabase() {
       using ORM                                                        world = new PTrackWorld();
                                                                        StateMachine stateMachine = world.getStateMachine();

       Avoids difficult to
                                                                        template.save(stateMachine);
                                                                        D      t
                                                                        Department itD         t   t
                                                                                     t itDepartment = world.getITDepartment();
                                                                                                         ld   tITD    t   t()

       maintain flat files:
                                                                        template.save(itDepartment);
                                                                        …

       CSV, SQL, XML
                                                                      }
                                                                  }




Chris Richardson — Improving tests with Object Mothers and DSLs                                                                       Slide 27
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Object Mother design
       Choices
              Same data each time vs. random data
              Referenced aggregates as parameters vs
                                                  vs.
              create those aggregates too
       Tip: use descriptive names
              Bad: makeProject1(), makeProject2(), ...
              Better: makeProjectIn<State>() …
                      makeProjectIn<State>(),
       Tip: use Object Mothers from day 1

Chris Richardson — Improving tests with Object Mothers and DSLs                              11/10/2008
                                                                                                 28
Colorado Software Summit: October 19 – 24, 2008                               © Copyright 2008, Chris Richardson




                Finding balance
  public void testOptionA() {
    ShoppingCart cart
    Sh     i C t      t
                                                                          Intention revealing
        = ShoppingCartMother.makeEmptyCart();
                                                                          But risks duplication
    cart.add(ProductMother.makeInstockPart(), 1);
    cart.add(ProductMother.makeBackOrderdPart(), 1);
    cart.add(ProductMother.makeDiscontinuedPart(), 1);
       t dd(P d tM th         k Di   ti   dP t() 1)

      …
  }

                                                                  OR
  public void testOptionB() {
   ShoppingCart cart =
    ShoppingCartMother.makeWithInstockPartBackorderedPartandDiscontinuedPart();

      …
  }                                                                    Ridiculously long
                                                                       names???


Chris Richardson — Improving tests with Object Mothers and DSLs                                          11/10/2008
                                                                                                             29
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Agenda
       Tests - a double-edged sword
                 double edged
       Taming test fixture logic
       Simplifying verification code
       Writing web tests
       Testing Ajax applications




                                                                                           30
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Writing readable verification
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                logic
       Verification phase verifies that expected
       outcome h been obtained
         t       has b      bt i d
       State verification makes assertions about:
              Returned value
              State of system under test
              State of collaborators
       Test frameworks provide the basic assert
       methods but we must:
              Ensure readability
              E         d bilit
              Avoid code duplication


                            11/10/2008
Chris Richardson — Improving tests with Object Mothers and DSLs                                  31
Colorado Software Summit: October 19 – 24, 2008                                   © Copyright 2008, Chris Richardson




                Smelly verification code
protected void setUp() throws Exception {
  PTrackWorld world = new PTrackWorld();
  p j
  projectManager = world.getItProjectManager();
              g            g      j       g ();

     project = world.getProjectInProposalState();
     startTime = new Date();

     state0 = world.getInitialState();
     state1 = state0.getApprovalStatus();
     state2 = state1.getApprovalStatus();
 }

public void testChangeStatus() throws InterruptedException {
  boolean result = project.changeStatus(true,
                              projectManager, quot;Excellentquot;);
  Date endTime = new Date();

     assertTrue(result);
     assertEquals(state1, project.getStatus());
     assertEquals(1, project.getHistory().size());

     O    ti        ti        j t    tHi t   ()   t(0)
     Operation operation = project.getHistory().get(0);
     assertEquals(quot;Excellentquot;, operation.getComments());          Lots of assertions = obscure code
     assertEquals(projectManager, operation.getUser());
     assertEquals(state0, operation.getFromStatus());
                                                                  Likely code duplication
     assertEquals(state1, operation.getToStatus());
     assertFalse(operation.getTimestamp().before(startTime));
     assertFalse(operation.getTimestamp().after(endTime));
     assertFalse(operation getTimestamp() after(endTime));
 }


                                                                                                           32
Chris Richardson — Improving tests with Object Mothers and DSLs                                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Using Custom Assertions
       Verification code calls a Test Utility
       Method that makes assertions
       Has an Intention Revealing Name
       Benefits:
              Makes th
              M k the code more readable
                           d         d bl
              Eliminates duplication




Chris Richardson — Improving tests with Object Mothers and DSLs                              11/10/2008
                                                                                                 33
Colorado Software Summit: October 19 – 24, 2008                                 © Copyright 2008, Chris Richardson




                Simplified test
                    protected void setUp() throws Exception {
                    …
                       expectedOperation0 =
                         new Operation(null, projectManager,
                                       state0, state1,
                                       quot;Excellentquot;);
                     }

                     public void testChangeStatus()
                    {
                       boolean result = project.changeStatus(true,
                                      projectManager, quot;E
                                         j tM         quot;Excellentquot;);
                                                           ll tquot;)
                       Date endTime = new Date();

                           assertTrue(result);
                           assertEquals(state1, project.getStatus());
                                  q    (       ,p j     g        ());

                           assertHistoryContains(project, startTime, endTime,
                                  expectedOperation0);
                       }




                                                                                                         34
Chris Richardson — Improving tests with Object Mothers and DSLs                                        11/10/2008
Colorado Software Summit: October 19 – 24, 2008                            © Copyright 2008, Chris Richardson




             Custom Assertion Methods
         private void assertHistoryContains(Project project, Date startTime,
                                             Date endTime,
                                             Operation... expectedOperations) {
            int i = 0;
            List<Operation> history = project.getHistory();
            assertEquals(expectedOperations.length, history.size());
            for (Operation expectedOperation : expectedOperations) {
              Operation operation = history.get(i++);
              assertOperationEqual(expectedOperation, startTime, endTime, operation);
              startTime = operation.getTimestamp();
            }
          }

            private void assertOperationEqual(Operation expectedOperation, Date startTime,
                                               Date endTime, Operation operation) {
               assertEquals(expectedOperation.getComments(), operation.getComments());
               assertEquals(expectedOperation.getUser(), operation.getUser());
               assertEquals(expectedOperation.getFromStatus(), operation.getFromStatus());
               assertEquals(expectedOperation.getToStatus(), operation.getToStatus());
               assertFalse(operation.getTimestamp().before(startTime));
                    tF l (      ti     tTi
               assertFalse(operation.getTimestamp().after(endTime));
                                             t    () ft ( dTi     ))
             }

                                                                                                    35
Chris Richardson — Improving tests with Object Mothers and DSLs                                   11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                   © Copyright 2008, Chris Richardson




             Literate assertions with Hamcrest
            Hamcrest is an open-source
            framework
            http://code.google.com/p/hamcrest/
            Readable quot;literatequot; assertions
                       literate
            Rich set of composable matchers
            Literate error messages
                                 g
            Used by Jmock expectations
           import static org.hamcrest.MatcherAssert.assertThat;
           import static org.hamcrest.Matchers.is;
                         org hamcrest Matchers is;
           import static org.hamcrest.Matchers.isOneOf;

            assertThat(project.getStatus(), is(state1));
            assertThat(project.getStatus(), isOneOf(state1, state2));
            assertThat(project.getStatus(), allOf(is(state), not(is(state2))));
                 tTh t(   j t    tSt t () llOf(i ( t t )       t(i ( t t 2))))


                                                                                                           36
Chris Richardson — Improving tests with Object Mothers and DSLs                                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                  © Copyright 2008, Chris Richardson




             Hamcrest custom matchers
        public class ProjectMatchers {

         p
         public static Matcher<Date> withinInclusivePeriod(final Date startTime,
                                                          (                    ,
            final Date endTime) {
           return new TypeSafeMatcher<Date>() {

             public boolean matchesSafely(Date date) {
               return !date.before(startTime) && !date.after(endTime);
             }

             public void describeTo(Description description) {
               description.appendText(String.format(quot;expected to be between <%s> and <%s>quot;,
                 startTime, endTime));
             }
                    import static org.jia.ptrack.domain.ProjectMatchers.withinInclusivePeriod;
                      p             gj p                   j                                 ;
            };
        }           public void testChangeStatus() {

                     assertThat(operation.getTimestamp(),
                                 is(withinInclusivePeriod(startTime, endTime)));
                    }
                                   java.lang.AssertionError:
                                   Expected: is expected to be between <Wed Nov 14 19:39:23 PST 2007> and
                                   <Wed Nov 14 19:39:23 PST 2007>
                                       got: <Wed Dec 31 16:00:00 PST 1969>
                                                 at
                                     g                                    (            j      )
                                   org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:21)




                                                                                                                          37
Chris Richardson — Improving tests with Object Mothers and DSLs                                                         11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Agenda
       Tests - a double-edged sword
                 double edged
       Taming test fixture logic
       Simplifying verification code
       Writing web tests
       Testing Ajax applications




                                                                                           38
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Writing web tests
       Web tests simulate the user
              Fill-in forms
              Click buttons and links
       Assertions:
                 Correct page displayed
                 Correct data is displayed
                 Page elements exist/visible
                 P     l      t    i t/ i ibl



                                                                                           39
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Using Selenium
       Popular web testing
          p               g
       framework
       Launches a browser
       ⇒ full Javascript
       support
       Selenium IDE for
       recording and
       running tests ⇒
            i
       quickly create tests

Chris Richardson — Improving tests with Object Mothers and DSLs                             Slide 40
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Selenium RC
       API for launching and controlling the
       browser
       Supports multiple programming
       language
       API:
              click(), type()
              waitForPageToLoad()
                  iF P      T L d()
              isVisible (), isPresent()


Chris Richardson — Improving tests with Object Mothers and DSLs                             Slide 41
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Selenium RC API + Selenium
                  IDE = trouble
       API is very level:
                 y
              Obscure tests
              Lots of duplication
       You can quickly generate tests with
       Selenium IDE
       The
       Th result:
               l
              Large amounts of difficult to maintain test
              code
              Very fragile tests ⇒ small change to UI, many
              broken tests

                                                                                           42
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                            © Copyright 2008, Chris Richardson




                An example of bad test code
        public class ExampleOfBadWebTests extends AbstractSeleniumTest {
          @Test
          public void testCreateProject() {
             bli    id t tC   t P j t()
           open(quot;/ptrack/quot;);
           type(quot;j_usernamequot;, quot;proj_mgrquot;);
           type(quot;j_passwordquot;, quot;facesquot;);
           clickAndWait(quot;Loginquot;);
           assertTextPresent(quot;(quot; + quot;proj_mgrquot; + quot;)quot;);
           clickAndWait(quot;link=Create Newquot;);
           String projectName = quot;XXX Projectquot; + System.currentTimeMillis();
           type(quot;projectDetails:nameInputquot;, projectName);
           select(quot;projectDetails:typeSelectOnequot;, quot;label=External Desktop Applicationquot;);
            …
           clickAndWait(quot;projectDetails:savequot;);
           assertTextPresent(quot;Inbox - approve or reject projectsquot;);
           assertTextEquals(projectName, quot;inboxPage:inboxTable:2:projectNamequot;);

             clickAndWait(quot;inboxPage:inboxTable:2:detailsquot;);
             assertTextPresent(projectName);
             assertTextPresent(quot;External Desktop Applicationquot;);
                                (                 p pp          );
             assertTextEquals(quot;Sean Sullivanquot;, quot;detailsPage:initiatedByquot;);
             ….
             assertTitle(quot;ProjectTrack - Project detailsquot;);
             clickAndWait(quot;detailsPage:okquot;);
             clickAndWait(quot;link=Logoutquot;);
                                                                   Easy to write – record with Selenium IDE
             assertTextPresent( Welcome
             assertTextPresent(quot;Welcome to Project Trackquot;);
                                                       Track );    But imagine coming back to this three
            }
        }
                                                                  months later ….

                                                                                                                    43
Chris Richardson — Improving tests with Object Mothers and DSLs                                                   11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Improving tests with utility
                  methods
       Write Test Utility methods = A Domain-Specific Language
         Have i t ti
         H     intention revealing names
                               li
         Call Selenium APIs
       Examples:
              login()
              goto…()
              assertOn…Page()
              logout()
       Write tests in terms of those methods
       Move those methods into a common superclass
       when appropriate



                                                                                           44
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                               © Copyright 2008, Chris Richardson




                 Improved example
         public class ImprovedExampleOfTests extends AbstractSeleniumTest {

             @Test                                                private void createProject() {
             public void testCreateProject() {                       clickAndWait(quot;link=Create Newquot;);
               login();                                              projectName = quot;XXX Projectquot; +
                                                                                   System.currentTimeMillis();
                                                                     type( projectDetails:nameInput
                                                                     type(quot;projectDetails:nameInputquot;, projectName);
                 createProject();                                    select(quot;projectDetails:typeSelectOnequot;,
                 assertProjectDisplayedInInbox();                             quot;label=External Desktop Applicationquot;);
                                                                     type(quot;projectDetails:requirementsInputquot;,
                  viewProjectDetails();                                         quot;Chris Richardsonquot;);
                  assertProjectDetailsDisplayed();                   type(quot;projectDetails:requirementsEmailInputquot;,
                                                                      yp ( p j               q                p ,
                                                                              quot;chris@chrisrichardson.netquot;);
                                                                      …
                  returnToInbox();                                   clickAndWait(quot;projectDetails:savequot;);
                  logout();                                        }
             }

         }                                  Test is a lot more readable
                                            Intention is clear

                                            Less duplication
                                            Less fragile
                                                                                                                       45
Chris Richardson — Improving tests with Object Mothers and DSLs                                                      11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Intelligently evolve the language
       Write/record tests using low-level APIs
                                low level
       Use Extract Method refactoring to
       create the utility methods
       Move methods into
              A common superclass
                                l
              Test Helper classes




Chris Richardson — Improving tests with Object Mothers and DSLs                              11/10/2008
                                                                                                 46
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Better ways to handle test data
       Web tests need data too
              Filling in forms
              Asserting the contents of the page
       Data embedded in code
              Test data is sprinkled through application
              Difficult to manage
              Duplication
              D li ti
              …

                                                                                           47
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                Example helper method
           p
           public class ExampleOfWebTests extends AbstractSeleniumTest {
                            p

            private String projectName;

            public void createProject() {
              clickAndWait(quot;link=Create Newquot;);
              projectName = quot;XXX Projectquot; + System.currentTimeMillis();
              type(quot;projectDetails:nameInputquot;, projectName);
              select(quot;projectDetails:typeSelectOnequot;,
                    quot;label=External Desktop Applicationquot;);
              type(quot;projectDetails:requirementsInputquot;, quot;Chris Richardsonquot;);
              …
              clickAndWait(quot;projectDetails:savequot;);
            }
           }



Chris Richardson — Improving tests with Object Mothers and DSLs                             Slide 48
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson


                  Using domain objects in web
                  tests
       Test utility methods:
              Use domain objects created by mothers
              Populate forms
              Verify the contents of a page
       Benefits:
              Improves readability
              Improves management of test data
              I                    t ft td t
              Parameterized methods are reusable

                                                                                           49
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                    © Copyright 2008, Chris Richardson




                A much better example

        public class ExampleOfGoodWebTests extends AbstractSeleniumTest {

            @Test
            public void testCreateProject() {
              login();
              Project
              P j t projectToCreate = ProjectMother.makeNewProject();
                          j tT C    t     P j tM th   k N P j t()

                createProject(projectToCreate);
                assertProjectDisplayedInInbox(projectToCreate);

                 viewProjectDetails(projectToCreate);
                 assertProjectDetailsDisplayed(projectToCreate);

                 returnToInbox();
                 logout();                        i t     id      tP j tD t il Di l
                                                private void assertProjectDetailsDisplayed(Project projectToCreate) {
                                                                                          d(P j t     j tT C    t )
            }                                     assertTextPresent(projectToCreate.getName());
                                                  assertTextPresent(projectToCreate.getType().getDescription());
        }                                         assertTextEquals(projectToCreate.getInitiatedBy().getFullName(),
                                                                    quot;detailsPage:initiatedByquot;);
                                                  …
                                               }


                                                                                                                            50
Chris Richardson — Improving tests with Object Mothers and DSLs                                                           11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Agenda
       Tests - a double-edged sword
                 double edged
       Taming test fixture logic
       Simplifying verification code
       Writing web tests
       Testing Ajax applications




                                                                                           51
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  The challenge of Ajax
       Ajax applications behave differently
        j     pp                          y
       JavaScript executes after the page loads
       ⇒ less deterministic, predictable behavior
       Clicks don't result in page loads
              Triggers an Ajax request that updates the
              same page
       DOM nodes are often hidden rather than
       non-existent
              assertElementPresent() ⇒ true even when the
              element is not visible

                                                                                           52
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Testing Ajax applications
       Bad approach:
              Put lots of long sleeps in your code
              Slows down the tests unnecessarily
       Improved approach:
              Loop testing for element visibility with a
              short sleep
              Use Selenium RC quot;waitquot; feature
                  Selenium-RC wait



                                                                                           53
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                                © Copyright 2008, Chris Richardson




                 Messy Example
           protected void waitForVisibility(String selector) {
                                                                      (        );
             WaitForElementVisible waiter = new WaitForElementVisible(selector);
             try {
               waiter.wait(String.format(quot;Cannot find element <%s>quot;, selector), 3000);
             } catch (Wait.WaitTimedOutException e) {
               return;
             }
           }                                                   public void testSomething()        {
                                                                       …
          class WaitForElementVisible extends Wait {                   waitForVisibility(quot;someFormquot;);
            private final String selector;                             assertTrue(selenium.isVisible(quot;someFormquot;));
               public WaitForElementVisible(String selector) {         …
                 this.selector
                 this selector = selector;
               }                                                   }
               @Override
               public boolean until() {
                 return selenium.isElementPresent(selector) && selenium.isVisible(selector);
               }
           }




                                                          This works but the code quickly becomes
                                                          cluttered with calls to waitForXXX()


Chris Richardson — Improving tests with Object Mothers and DSLs                                                          Slide 54
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Better: Implementation #2
       Encapsulate the waiting/loop within
       Test Utility methods, e.g.:
              assertElementVisible( )
              assertElementVisible(…)
       Benefits:
              Simplifies the test code




                                                                                           55
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                      © Copyright 2008, Chris Richardson




                A simple example
          protected void waitForVisibility(String selector) {
            WaitForElementVisible waiter = new WaitForElementVisible(selector);
            try {
              waiter.wait(String.format(quot;Cannot find element <%s>quot;, selector), 3000);
            } catch (Wait.WaitTimedOutException e) {
              return;
            }
          }                                               public void testSomething() {
                                                            …
         class WaitForElementVisible extends Wait {         assertElementVisible(quot;someFormquot;);
         …                                                …
          }
                                                          }

           public void assertElementVisible(String selector) {
                 i F Vi ibili ( l
             waitForVisibility(selector);)
             assertTrue(selenium.isVisible(selector));
           }

                                                          Simplifies the test code



Chris Richardson — Improving tests with Object Mothers and DSLs                                                Slide 56
Summary of web testing
Colorado Software Summit: October 19 – 24, 2008                            © Copyright 2008, Chris Richardson




                architecture

                                                                  Tests
                                                                  T t
                                Application-specific Utility methods
                                Application specific
                                               e.g. login(), logout(), …

                                               Wrapped selenium APIs
                          e.g. hides Ajax related timing issues etc

                                                             Selenium RC



                                                                                                    57
Chris Richardson — Improving tests with Object Mothers and DSLs                                   11/10/2008
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Some useful frameworks
       Umangite – Selenium web tests
              code.google.com/p/umangite/
       ORMUnit – Persistence tests
              code.google.com/p/ormunit
       Arid POJOs Generic DAO
       A id POJO – G   i DAOs
              code.google.com/p/aridpojos/
       And, others:
              code.google.com/u/chris.e.richardson/

Chris Richardson — Improving tests with Object Mothers and DSLs                             Slide 58
Colorado Software Summit: October 19 – 24, 2008                   © Copyright 2008, Chris Richardson




                  Summary
       Messy tests will kill your application
            y                y     pp
       Aggressively refactor tests to keep them
       simple
       Define classes with fluent interfaces
       Use Object Mothers to avoid duplication
       of test fixture logic
       Aggressively use Test Utility Methods:
              Simplify web tests
              Hide Ajax-related issues


                                                                                           59
Chris Richardson — Improving tests with Object Mothers and DSLs                          11/10/2008
Colorado Software Summit: October 19 – 24, 2008                                   © Copyright 2008, Chris Richardson




                For more information
                                                                    Buy my book ☺
                                                                       Go to
                                                                       G t manning.com
                                                                               i

                                                                    Send email:

                                                                  chris@chrisrichardson.net

                                                                    Visit my website:

                                                                  http://www.chrisrichardson.net

                                                                    Talk to me about consulting
                                                                    and training


                                                                                                           60
Chris Richardson — Improving tests with Object Mothers and DSLs                                          11/10/2008

Contenu connexe

Tendances

Quantum Computing with Amazon Braket
Quantum Computing with Amazon BraketQuantum Computing with Amazon Braket
Quantum Computing with Amazon Braket
Amazon Web Services
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
MongoDB
 

Tendances (20)

Continuous delivery and deployment on AWS
Continuous delivery and deployment on AWSContinuous delivery and deployment on AWS
Continuous delivery and deployment on AWS
 
AZ-204: Monitor, Troubleshoot & Optimize Azure Solutions
AZ-204: Monitor, Troubleshoot & Optimize Azure SolutionsAZ-204: Monitor, Troubleshoot & Optimize Azure Solutions
AZ-204: Monitor, Troubleshoot & Optimize Azure Solutions
 
Microservices Architecture - Cloud Native Apps
Microservices Architecture - Cloud Native AppsMicroservices Architecture - Cloud Native Apps
Microservices Architecture - Cloud Native Apps
 
Azure serverless Full-Stack kickstart
Azure serverless Full-Stack kickstartAzure serverless Full-Stack kickstart
Azure serverless Full-Stack kickstart
 
Quantum Computing with Amazon Braket
Quantum Computing with Amazon BraketQuantum Computing with Amazon Braket
Quantum Computing with Amazon Braket
 
Cluster-as-code. The Many Ways towards Kubernetes
Cluster-as-code. The Many Ways towards KubernetesCluster-as-code. The Many Ways towards Kubernetes
Cluster-as-code. The Many Ways towards Kubernetes
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
 
Elastic Kubernetes Services (EKS)
Elastic Kubernetes Services (EKS)Elastic Kubernetes Services (EKS)
Elastic Kubernetes Services (EKS)
 
Spring cloud config
Spring cloud configSpring cloud config
Spring cloud config
 
Azure Logic Apps
Azure Logic AppsAzure Logic Apps
Azure Logic Apps
 
Why Kubernetes on Azure
Why Kubernetes on AzureWhy Kubernetes on Azure
Why Kubernetes on Azure
 
Microsoft: Multi-tenant SaaS with Azure
Microsoft: Multi-tenant SaaS with AzureMicrosoft: Multi-tenant SaaS with Azure
Microsoft: Multi-tenant SaaS with Azure
 
Building Rich Domain Models
Building Rich Domain ModelsBuilding Rich Domain Models
Building Rich Domain Models
 
GCP IAM.pptx
GCP IAM.pptxGCP IAM.pptx
GCP IAM.pptx
 
Azure governance v4.0
Azure governance v4.0Azure governance v4.0
Azure governance v4.0
 
Azure Monitoring Overview
Azure Monitoring OverviewAzure Monitoring Overview
Azure Monitoring Overview
 
Principles Of Chaos Engineering - Chaos Engineering Hamburg
Principles Of Chaos Engineering - Chaos Engineering HamburgPrinciples Of Chaos Engineering - Chaos Engineering Hamburg
Principles Of Chaos Engineering - Chaos Engineering Hamburg
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
 
Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...
Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...
Securing MongoDB to Serve an AWS-Based, Multi-Tenant, Security-Fanatic SaaS A...
 
Azure automation
Azure automationAzure automation
Azure automation
 

En vedette

En vedette (9)

Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...Building microservices with Scala, functional domain models and Spring Boot (...
Building microservices with Scala, functional domain models and Spring Boot (...
 
Developing and deploying applications with Spring Boot and Docker (@oakjug)
Developing and deploying applications with Spring Boot and Docker (@oakjug)Developing and deploying applications with Spring Boot and Docker (@oakjug)
Developing and deploying applications with Spring Boot and Docker (@oakjug)
 
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
 
Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)
 
Developing event-driven microservices with event sourcing and CQRS (Shanghai)
Developing event-driven microservices with event sourcing and CQRS (Shanghai)Developing event-driven microservices with event sourcing and CQRS (Shanghai)
Developing event-driven microservices with event sourcing and CQRS (Shanghai)
 
Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)Microservices pattern language (microxchg microxchg2016)
Microservices pattern language (microxchg microxchg2016)
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)
 
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...Developing event-driven microservices with event sourcing and CQRS  (svcc, sv...
Developing event-driven microservices with event sourcing and CQRS (svcc, sv...
 

Similaire à Improving Tests With Object Mothers And Internal Dsls

Cloud-Native Fundamentals: Accelerating Development with Continuous Integration
Cloud-Native Fundamentals: Accelerating Development with Continuous IntegrationCloud-Native Fundamentals: Accelerating Development with Continuous Integration
Cloud-Native Fundamentals: Accelerating Development with Continuous Integration
VMware Tanzu
 
Sukumar Nayak-Agile-DevOps-Cloud Management
Sukumar Nayak-Agile-DevOps-Cloud ManagementSukumar Nayak-Agile-DevOps-Cloud Management
Sukumar Nayak-Agile-DevOps-Cloud Management
Sukumar Nayak
 
syllabus.
syllabus.syllabus.
syllabus.
butest
 
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdfLaunching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
Amazon Web Services
 

Similaire à Improving Tests With Object Mothers And Internal Dsls (20)

Deploying Java Applicationson Ec2
Deploying Java Applicationson Ec2Deploying Java Applicationson Ec2
Deploying Java Applicationson Ec2
 
What you can learn from an open-source project with 250 million downloads
What you can learn from an open-source project with 250 million downloadsWhat you can learn from an open-source project with 250 million downloads
What you can learn from an open-source project with 250 million downloads
 
5 Habits of High-Velocity Teams Using Kubernetes
5 Habits of High-Velocity Teams Using Kubernetes5 Habits of High-Velocity Teams Using Kubernetes
5 Habits of High-Velocity Teams Using Kubernetes
 
Cloud-Native Fundamentals: Accelerating Development with Continuous Integration
Cloud-Native Fundamentals: Accelerating Development with Continuous IntegrationCloud-Native Fundamentals: Accelerating Development with Continuous Integration
Cloud-Native Fundamentals: Accelerating Development with Continuous Integration
 
CI/CD Pipelines for Your Infrastructure...as Code!
CI/CD Pipelines for Your Infrastructure...as Code!CI/CD Pipelines for Your Infrastructure...as Code!
CI/CD Pipelines for Your Infrastructure...as Code!
 
Managing Compliance in Container Environments
Managing Compliance in Container EnvironmentsManaging Compliance in Container Environments
Managing Compliance in Container Environments
 
PHPFrameworkDay 2020 - Different software evolutions from Start till Release ...
PHPFrameworkDay 2020 - Different software evolutions from Start till Release ...PHPFrameworkDay 2020 - Different software evolutions from Start till Release ...
PHPFrameworkDay 2020 - Different software evolutions from Start till Release ...
 
"Different software evolutions from Start till Release in PHP product" Oleksa...
"Different software evolutions from Start till Release in PHP product" Oleksa..."Different software evolutions from Start till Release in PHP product" Oleksa...
"Different software evolutions from Start till Release in PHP product" Oleksa...
 
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
 
Testing Rich Domain Models
Testing Rich Domain ModelsTesting Rich Domain Models
Testing Rich Domain Models
 
Sukumar Nayak-Agile-DevOps-Cloud Management
Sukumar Nayak-Agile-DevOps-Cloud ManagementSukumar Nayak-Agile-DevOps-Cloud Management
Sukumar Nayak-Agile-DevOps-Cloud Management
 
Base Logic Inc Solution Offering
Base Logic Inc Solution OfferingBase Logic Inc Solution Offering
Base Logic Inc Solution Offering
 
syllabus.
syllabus.syllabus.
syllabus.
 
DSC NTUE Info Session
DSC NTUE Info SessionDSC NTUE Info Session
DSC NTUE Info Session
 
Business Value of CI, CD, & DevOps(Sec)
Business Value of CI, CD, & DevOps(Sec)Business Value of CI, CD, & DevOps(Sec)
Business Value of CI, CD, & DevOps(Sec)
 
ROI & Business Value of CI, CD, DevOps, DevSecOps, & Microservices
ROI & Business Value of CI, CD, DevOps, DevSecOps, & MicroservicesROI & Business Value of CI, CD, DevOps, DevSecOps, & Microservices
ROI & Business Value of CI, CD, DevOps, DevSecOps, & Microservices
 
Azure DevOps AI
Azure DevOps AIAzure DevOps AI
Azure DevOps AI
 
Performance testing DataHelix | Scott Logic
Performance testing DataHelix | Scott LogicPerformance testing DataHelix | Scott Logic
Performance testing DataHelix | Scott Logic
 
From Monolith to Microservices (And All the Bumps along the Way) (CON360-R1) ...
From Monolith to Microservices (And All the Bumps along the Way) (CON360-R1) ...From Monolith to Microservices (And All the Bumps along the Way) (CON360-R1) ...
From Monolith to Microservices (And All the Bumps along the Way) (CON360-R1) ...
 
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdfLaunching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
Launching your Application the Amazon Way - AWS Startup Day Boston 2018.pdf
 

Plus de Chris Richardson

Plus de Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Dernier

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Dernier (20)

Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Improving Tests With Object Mothers And Internal Dsls

  • 1. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Improving tests with Obj t I i g t t ith Object Mothers and Internal DSLs Chris i h d Ch i Richardson Author of POJOs in Action Founder of Cloud Tools http://www.chrisrichardson.net htt // h i i h d t 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 1
  • 2. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Overview Writingg maintainable tests Copyright (c) 2008 Chris Richardson. All rights 2 Chris Richardson — Improving tests with Object Mothers and DSLs reserved. 11/10/2008
  • 3. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson About Chris Grew up in England and live in Oakland, CA p g , Over twenty years of software development experience Building object-oriented software since 1986 Using Java since 1996 Using J2EE since 1999 Author of POJOs in Action Speaker at JavaOne, SpringOne, NFJS, JavaPolis, Spring Experience, etc. Chair of the eBIG Java SIG in Oakland (www.ebig.org) (www ebig org) Run a consulting and training company that helps organizations build better software faster and deploy it on Amazon EC2 Founder of Cloud Tools, an open-source project for d l i f deploying J Java applications on Amazon EC2: li ti A EC2 http://code.google.com/p/cloudtools Chris Richardson — Improving tests with Object Mothers and DSLs Slide 3
  • 4. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Agenda Tests - a double-edged sword double edged Taming test fixture logic Simplifying verification code Writing web tests Testing Ajax applications 4 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 5. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Why test? Write new code more easily A t t h t Automates what we are doing already - d i l d Right!? Run fast unit tests instead of slower web application Use TDD to incrementally solve a problem Tests are a safety net Confidently change existing code Easier to refactor code to prevent decay Fewer bugs that impact customers AND development Copyright (c) 2008 Chris Richardson. All rights reserved. Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 5
  • 6. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Why test? Increases longevity: g y Testable code is cleaner code Without tests your application will decay y pp y and die Absolutely essential when using a dynamic l d language Compiler can't catch typos Nothing is too simple to test You need unit tests Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 6
  • 7. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson 4 phase tests public class FooTest extends TestCase { public void setUp() { Setupp } Exercise public void testSomething() { // test-specific setup Verify // Exercise the SUT Teardown // Verification // test-specific tear down test specific } public void tearDown() { } } 7 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 8. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Types of tests Domain model tests Easy to write Fast to run Test your domain objects and services In-memory tests Persistence tests Test manipulating persistent objects Service integration tests Test services using database Web tests Automatic tests using Selenium Click and type in the GUI Difficult to write Slow to run 8 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 9. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Example tests Walk through some example ptrack tests 9 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 10. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson The trouble with tests They make software more difficult to y change That's a good thing since they detect bugs But change is inevitable: new features, refactoring If you can't easily change the test code: Slows down the development Tests are removed or abandoned 10 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 11. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Poor quality test code Common test code smells Obscure T t – you can't tell what a test does Ob Tests 't t ll h t t t d Test code duplication – copy and paste tests Badly structured test setup logic Complicated logic to create test fixtures E.g. the test objects (in-memory or in DB) Sprawling web tests p a g b Web test framework APIs are very low-level. Easily end up with large amounts of difficult to maintain code: click(),type(),… (), yp (), Lots of duplication Lots of obscure code 11 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 12. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Excellent testing book Test smells and how to fix them Obscure test Fragile test Test code duplication … Comprehensive pattern language: Four phase test Minimal fixture Test utility method Test helper Humble Objectj … 12 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 13. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Agenda Tests - a double-edged sword double edged Taming test fixture logic Simplifying verification code Writing web tests Testing Ajax applications 13 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 14. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson What s What's a fixture Fixture = everything that needs to be y g in place to test an object/system Object/system we want to test Its collaborators, required test data etc Fixture is created by test fixture y logic: Code in the test methods themselves Junit 3.x setUp() JUnit 4/TestNG @Before* annotations 14 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 15. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson The challenge of test fixtures Creating an object isn't always easy g j y y Objects can have lots of attributes Objects are often aggregate roots new() is often insufficient Test fixtures often create multiple objects E.g. money transfer test needs two accounts f d Multiple tests need the same set of objects • AccountTests, MoneyTransferServiceTests need similar Account objects 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 15
  • 16. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Object graphs can be complicated We need all of these objects to test a Project! 16 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 17. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Constructing individual objects can be tricky Best way to construct an object is to use y j a non-default constructor: Supports objects without setters Supports immutable objects Forces you to supply all required objects Constructor can verify object state Limitations of constructors: Lots of constructor arguments ⇒ code is difficult to read Optional arguments ⇒ multiple constructors 17 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 18. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson The alternative to constructors Project project = new Project(initialStatus); project.setName(quot;Test Project #1quot;); project.setDescription(quot;descriptionquot;); project.setRequirementsContactName(quot;Rick Jonesquot;); project.setRequirementsContactEmail(quot;jones@nowhere.comquot;); project.setType(ProjectType.EXTERNAL_DB); project.setArtifacts(new ArtifactType[] { ArtifactType.ARCHITECTURE, ArtifactType.DEPLOYMENT, ArtifactType.MAINTENANCE }); project.setInitiatedBy(user); Benefits: •Handles optional parameters •Is more readable But •Lots of noise: 'project.set‘ •Breaks encapsulation Breaks •Object is mutable •Cannot validate state 18 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 19. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Constructing objects fluently Project project = new Project(initialStatus) .name(quot;Test P j t #1quot;) (quot;T t Project .description(quot;Excellent projectquot;) .initiatedBy(user) .requirementsContactName(quot;Rick Jonesquot;) .requirementsContactEmail(quot;jones@nowhere.comquot;) i t C t tE il(quot;j @ h quot;) .type(ProjectType.EXTERNAL_DB) .artifact(ArtifactType.ARCHITECTURE) .artifact(ArtifactType.DEPLOYMENT) .artifact(ArtifactType.MAINTENANCE); tif t(A tif tT MAINTENANCE) Chained method calls Benefits: •Less noise •Meaning of each value is clear Meaning Drawbacks: •Breaks encapsulation – objects must have mutators/setters •Doesn't work with immutable objects •No opportunity to validate state No 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 19
  • 20. Fluently creating immutable Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson objects See http://developers.sun.com/learning/javaoneonline http://developers sun com/learning/javaoneonline /2007/pdf/TS-2689.pdf Project project = new Project.ProjectBuilder(initialStatus) .name(quot;Test Project #1quot;) (quot; j .description(quot;descriptionquot;) .initiatedBy(user) .requirementsContactName(quot;Rick Jonesquot;) i C il(quot;j .requirementsContactEmail(quot;jones@nowhere.comquot;) @ h quot;) .type(ProjectType.EXTERNAL_DB) .artifact(ArtifactType.ARCHITECTURE) .artifact(ArtifactType.DEPLOYMENT) .artifact(ArtifactType.MAINTENANCE) tif t(A tif tT MAINTENANCE) .make(); • Initialize the mutable builder • make() instantiates the domain object via a constructor • Allows entity to be immutable • Builder can validate object state This is an internal DSL 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 20
  • 21. Nested Entity Builder Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson example class Project { public static class ProjectBuilder { private String name; … public ProjectBuilder(Status initialStatus) { this.status = status; } ProjectBuilder name(String name) { this.name = name; return this; } public Project make() { // Verify that we have everything j ( ); return new Project(this); } } • Pass builder as the sole constructor argument public Project(ProjectBuilder builder) { this.name = builder.name; this.initiatedBy = builder.initiatedBy; } 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 21
  • 22. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Testing makes your objects smarter Production code often has simple p requirements: Create using default constructor Accesses Java bean properties But tests need smarter objects j E.g. fluent interfaces Counter to the concept of not having test code in production code But this is ok: tests are important 22 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 23. Centralizing test object Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson creation with Object Mothers Fluent interfaces can help but public class ProjectMother { Fixture logic can still be public static Project complex makeProjectInProposalState ( Same object created in Status initialStatus, User user) { ) multiple t t ⇒ d li ti lti l tests duplication … Eliminate duplication: } Centralize object creation in a public static Project test utility class called an makeProjectInRequirementsState( Object Mother Status initialStatus, User user) { Defines factory methods for … creating fully formed } aggregate Different methods for different aggregate states } See: http://www xpuniverse com/2001/pdfs/Testing03 pdf http://www.xpuniverse.com/2001/pdfs/Testing03.pdf 23 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 24. Creating multiple connected Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson aggregates Each Object Mother method creates a th d t single aggregate But some tests need to create multiple aggregates with shared sub- aggregates Must avoid itDepartment = DepartmentMother.makeItDepartment(); duplicating that itProjectManager = UserMother.makeProjectManager(itDepartment); code in multiple itBusinessAnalyst = UserMother.makeBusinessAnalyst(itDepartment); tests projectInCompleteState = ProjectMother.makeProjectInCompleteState(…); projectInRequirementsState = ProjectMother.makeProjectInRequirementsState(…); P j tM th k P j tI R i t St t ( ) … 24 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 25. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Use stateful object mothers Test instantiates object mother Object mother's constructor Creates aggregates (by calling their Object Mothers) Stores them in (public) fields Test gets the data it needs from the object mother 25 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 26. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Example of a stateful mother public class ProjectTests extends TestCase { public class PTrackWorld { private Project project; private User projectManager; private final Department itDepartment; private User businessAnalyst; private final User itProjectManager; protected void setUp() throws Exception { private final User itBusinessAnalyst; PTrackWorld world = new PTrackWorld(); private final Project projectInCompleteState; projectManager = world.getItProjectManager(); businessAnalyst = world.getItBusinessAnalyst(); … project = world.getProjectInProposalState(); } public PTrackWorld() { itDepartment = DepartmentMother.makeItDepartment()' DepartmentMother.makeItDepartment() itProjectManager = UserMother.makeProjectManager(itDepartment); itBusinessAnalyst = UserMother.makeBusinessAnalyst(itDepartment … stateMachine = DefaultStateMachineFactory.makeStateMachine(quot;defaultquot;); initialStatus = stateMachine.getInitialStatus(); projectInCompleteState = ProjectMother.makeProjectInCompleteState(initialStatus, itProjectManager, getAllITDepartmentEmployees()); … } } 26 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 27. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Object Mothers and databases Initialize database public class PtrackDatabaseInitializer using objects i bj t implements InitializingBean, DatabaseInitializer { created by private HibernateTemplate template; private PTrackWorld world; mothers public PtrackDatabaseInitializer(HibernateTemplate Create objects this.template = template; template) { using mothers } Persist them public void afterPropertiesSet() { initializeDatabase(); } Very easy when public void initializeDatabase() { using ORM world = new PTrackWorld(); StateMachine stateMachine = world.getStateMachine(); Avoids difficult to template.save(stateMachine); D t Department itD t t t itDepartment = world.getITDepartment(); ld tITD t t() maintain flat files: template.save(itDepartment); … CSV, SQL, XML } } Chris Richardson — Improving tests with Object Mothers and DSLs Slide 27
  • 28. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Object Mother design Choices Same data each time vs. random data Referenced aggregates as parameters vs vs. create those aggregates too Tip: use descriptive names Bad: makeProject1(), makeProject2(), ... Better: makeProjectIn<State>() … makeProjectIn<State>(), Tip: use Object Mothers from day 1 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 28
  • 29. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Finding balance public void testOptionA() { ShoppingCart cart Sh i C t t Intention revealing = ShoppingCartMother.makeEmptyCart(); But risks duplication cart.add(ProductMother.makeInstockPart(), 1); cart.add(ProductMother.makeBackOrderdPart(), 1); cart.add(ProductMother.makeDiscontinuedPart(), 1); t dd(P d tM th k Di ti dP t() 1) … } OR public void testOptionB() { ShoppingCart cart = ShoppingCartMother.makeWithInstockPartBackorderedPartandDiscontinuedPart(); … } Ridiculously long names??? Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 29
  • 30. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Agenda Tests - a double-edged sword double edged Taming test fixture logic Simplifying verification code Writing web tests Testing Ajax applications 30 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 31. Writing readable verification Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson logic Verification phase verifies that expected outcome h been obtained t has b bt i d State verification makes assertions about: Returned value State of system under test State of collaborators Test frameworks provide the basic assert methods but we must: Ensure readability E d bilit Avoid code duplication 11/10/2008 Chris Richardson — Improving tests with Object Mothers and DSLs 31
  • 32. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Smelly verification code protected void setUp() throws Exception { PTrackWorld world = new PTrackWorld(); p j projectManager = world.getItProjectManager(); g g j g (); project = world.getProjectInProposalState(); startTime = new Date(); state0 = world.getInitialState(); state1 = state0.getApprovalStatus(); state2 = state1.getApprovalStatus(); } public void testChangeStatus() throws InterruptedException { boolean result = project.changeStatus(true, projectManager, quot;Excellentquot;); Date endTime = new Date(); assertTrue(result); assertEquals(state1, project.getStatus()); assertEquals(1, project.getHistory().size()); O ti ti j t tHi t () t(0) Operation operation = project.getHistory().get(0); assertEquals(quot;Excellentquot;, operation.getComments()); Lots of assertions = obscure code assertEquals(projectManager, operation.getUser()); assertEquals(state0, operation.getFromStatus()); Likely code duplication assertEquals(state1, operation.getToStatus()); assertFalse(operation.getTimestamp().before(startTime)); assertFalse(operation.getTimestamp().after(endTime)); assertFalse(operation getTimestamp() after(endTime)); } 32 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 33. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Using Custom Assertions Verification code calls a Test Utility Method that makes assertions Has an Intention Revealing Name Benefits: Makes th M k the code more readable d d bl Eliminates duplication Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 33
  • 34. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Simplified test protected void setUp() throws Exception { … expectedOperation0 = new Operation(null, projectManager, state0, state1, quot;Excellentquot;); } public void testChangeStatus() { boolean result = project.changeStatus(true, projectManager, quot;E j tM quot;Excellentquot;); ll tquot;) Date endTime = new Date(); assertTrue(result); assertEquals(state1, project.getStatus()); q ( ,p j g ()); assertHistoryContains(project, startTime, endTime, expectedOperation0); } 34 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 35. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Custom Assertion Methods private void assertHistoryContains(Project project, Date startTime, Date endTime, Operation... expectedOperations) { int i = 0; List<Operation> history = project.getHistory(); assertEquals(expectedOperations.length, history.size()); for (Operation expectedOperation : expectedOperations) { Operation operation = history.get(i++); assertOperationEqual(expectedOperation, startTime, endTime, operation); startTime = operation.getTimestamp(); } } private void assertOperationEqual(Operation expectedOperation, Date startTime, Date endTime, Operation operation) { assertEquals(expectedOperation.getComments(), operation.getComments()); assertEquals(expectedOperation.getUser(), operation.getUser()); assertEquals(expectedOperation.getFromStatus(), operation.getFromStatus()); assertEquals(expectedOperation.getToStatus(), operation.getToStatus()); assertFalse(operation.getTimestamp().before(startTime)); tF l ( ti tTi assertFalse(operation.getTimestamp().after(endTime)); t () ft ( dTi )) } 35 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 36. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Literate assertions with Hamcrest Hamcrest is an open-source framework http://code.google.com/p/hamcrest/ Readable quot;literatequot; assertions literate Rich set of composable matchers Literate error messages g Used by Jmock expectations import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; org hamcrest Matchers is; import static org.hamcrest.Matchers.isOneOf; assertThat(project.getStatus(), is(state1)); assertThat(project.getStatus(), isOneOf(state1, state2)); assertThat(project.getStatus(), allOf(is(state), not(is(state2)))); tTh t( j t tSt t () llOf(i ( t t ) t(i ( t t 2)))) 36 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 37. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Hamcrest custom matchers public class ProjectMatchers { p public static Matcher<Date> withinInclusivePeriod(final Date startTime, ( , final Date endTime) { return new TypeSafeMatcher<Date>() { public boolean matchesSafely(Date date) { return !date.before(startTime) && !date.after(endTime); } public void describeTo(Description description) { description.appendText(String.format(quot;expected to be between <%s> and <%s>quot;, startTime, endTime)); } import static org.jia.ptrack.domain.ProjectMatchers.withinInclusivePeriod; p gj p j ; }; } public void testChangeStatus() { assertThat(operation.getTimestamp(), is(withinInclusivePeriod(startTime, endTime))); } java.lang.AssertionError: Expected: is expected to be between <Wed Nov 14 19:39:23 PST 2007> and <Wed Nov 14 19:39:23 PST 2007> got: <Wed Dec 31 16:00:00 PST 1969> at g ( j ) org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:21) 37 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 38. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Agenda Tests - a double-edged sword double edged Taming test fixture logic Simplifying verification code Writing web tests Testing Ajax applications 38 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 39. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Writing web tests Web tests simulate the user Fill-in forms Click buttons and links Assertions: Correct page displayed Correct data is displayed Page elements exist/visible P l t i t/ i ibl 39 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 40. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Using Selenium Popular web testing p g framework Launches a browser ⇒ full Javascript support Selenium IDE for recording and running tests ⇒ i quickly create tests Chris Richardson — Improving tests with Object Mothers and DSLs Slide 40
  • 41. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Selenium RC API for launching and controlling the browser Supports multiple programming language API: click(), type() waitForPageToLoad() iF P T L d() isVisible (), isPresent() Chris Richardson — Improving tests with Object Mothers and DSLs Slide 41
  • 42. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Selenium RC API + Selenium IDE = trouble API is very level: y Obscure tests Lots of duplication You can quickly generate tests with Selenium IDE The Th result: l Large amounts of difficult to maintain test code Very fragile tests ⇒ small change to UI, many broken tests 42 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 43. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson An example of bad test code public class ExampleOfBadWebTests extends AbstractSeleniumTest { @Test public void testCreateProject() { bli id t tC t P j t() open(quot;/ptrack/quot;); type(quot;j_usernamequot;, quot;proj_mgrquot;); type(quot;j_passwordquot;, quot;facesquot;); clickAndWait(quot;Loginquot;); assertTextPresent(quot;(quot; + quot;proj_mgrquot; + quot;)quot;); clickAndWait(quot;link=Create Newquot;); String projectName = quot;XXX Projectquot; + System.currentTimeMillis(); type(quot;projectDetails:nameInputquot;, projectName); select(quot;projectDetails:typeSelectOnequot;, quot;label=External Desktop Applicationquot;); … clickAndWait(quot;projectDetails:savequot;); assertTextPresent(quot;Inbox - approve or reject projectsquot;); assertTextEquals(projectName, quot;inboxPage:inboxTable:2:projectNamequot;); clickAndWait(quot;inboxPage:inboxTable:2:detailsquot;); assertTextPresent(projectName); assertTextPresent(quot;External Desktop Applicationquot;); ( p pp ); assertTextEquals(quot;Sean Sullivanquot;, quot;detailsPage:initiatedByquot;); …. assertTitle(quot;ProjectTrack - Project detailsquot;); clickAndWait(quot;detailsPage:okquot;); clickAndWait(quot;link=Logoutquot;); Easy to write – record with Selenium IDE assertTextPresent( Welcome assertTextPresent(quot;Welcome to Project Trackquot;); Track ); But imagine coming back to this three } } months later …. 43 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 44. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Improving tests with utility methods Write Test Utility methods = A Domain-Specific Language Have i t ti H intention revealing names li Call Selenium APIs Examples: login() goto…() assertOn…Page() logout() Write tests in terms of those methods Move those methods into a common superclass when appropriate 44 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 45. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Improved example public class ImprovedExampleOfTests extends AbstractSeleniumTest { @Test private void createProject() { public void testCreateProject() { clickAndWait(quot;link=Create Newquot;); login(); projectName = quot;XXX Projectquot; + System.currentTimeMillis(); type( projectDetails:nameInput type(quot;projectDetails:nameInputquot;, projectName); createProject(); select(quot;projectDetails:typeSelectOnequot;, assertProjectDisplayedInInbox(); quot;label=External Desktop Applicationquot;); type(quot;projectDetails:requirementsInputquot;, viewProjectDetails(); quot;Chris Richardsonquot;); assertProjectDetailsDisplayed(); type(quot;projectDetails:requirementsEmailInputquot;, yp ( p j q p , quot;chris@chrisrichardson.netquot;); … returnToInbox(); clickAndWait(quot;projectDetails:savequot;); logout(); } } } Test is a lot more readable Intention is clear Less duplication Less fragile 45 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 46. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Intelligently evolve the language Write/record tests using low-level APIs low level Use Extract Method refactoring to create the utility methods Move methods into A common superclass l Test Helper classes Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008 46
  • 47. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Better ways to handle test data Web tests need data too Filling in forms Asserting the contents of the page Data embedded in code Test data is sprinkled through application Difficult to manage Duplication D li ti … 47 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 48. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Example helper method p public class ExampleOfWebTests extends AbstractSeleniumTest { p private String projectName; public void createProject() { clickAndWait(quot;link=Create Newquot;); projectName = quot;XXX Projectquot; + System.currentTimeMillis(); type(quot;projectDetails:nameInputquot;, projectName); select(quot;projectDetails:typeSelectOnequot;, quot;label=External Desktop Applicationquot;); type(quot;projectDetails:requirementsInputquot;, quot;Chris Richardsonquot;); … clickAndWait(quot;projectDetails:savequot;); } } Chris Richardson — Improving tests with Object Mothers and DSLs Slide 48
  • 49. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Using domain objects in web tests Test utility methods: Use domain objects created by mothers Populate forms Verify the contents of a page Benefits: Improves readability Improves management of test data I t ft td t Parameterized methods are reusable 49 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 50. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson A much better example public class ExampleOfGoodWebTests extends AbstractSeleniumTest { @Test public void testCreateProject() { login(); Project P j t projectToCreate = ProjectMother.makeNewProject(); j tT C t P j tM th k N P j t() createProject(projectToCreate); assertProjectDisplayedInInbox(projectToCreate); viewProjectDetails(projectToCreate); assertProjectDetailsDisplayed(projectToCreate); returnToInbox(); logout(); i t id tP j tD t il Di l private void assertProjectDetailsDisplayed(Project projectToCreate) { d(P j t j tT C t ) } assertTextPresent(projectToCreate.getName()); assertTextPresent(projectToCreate.getType().getDescription()); } assertTextEquals(projectToCreate.getInitiatedBy().getFullName(), quot;detailsPage:initiatedByquot;); … } 50 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 51. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Agenda Tests - a double-edged sword double edged Taming test fixture logic Simplifying verification code Writing web tests Testing Ajax applications 51 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 52. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson The challenge of Ajax Ajax applications behave differently j pp y JavaScript executes after the page loads ⇒ less deterministic, predictable behavior Clicks don't result in page loads Triggers an Ajax request that updates the same page DOM nodes are often hidden rather than non-existent assertElementPresent() ⇒ true even when the element is not visible 52 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 53. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Testing Ajax applications Bad approach: Put lots of long sleeps in your code Slows down the tests unnecessarily Improved approach: Loop testing for element visibility with a short sleep Use Selenium RC quot;waitquot; feature Selenium-RC wait 53 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 54. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Messy Example protected void waitForVisibility(String selector) { ( ); WaitForElementVisible waiter = new WaitForElementVisible(selector); try { waiter.wait(String.format(quot;Cannot find element <%s>quot;, selector), 3000); } catch (Wait.WaitTimedOutException e) { return; } } public void testSomething() { … class WaitForElementVisible extends Wait { waitForVisibility(quot;someFormquot;); private final String selector; assertTrue(selenium.isVisible(quot;someFormquot;)); public WaitForElementVisible(String selector) { … this.selector this selector = selector; } } @Override public boolean until() { return selenium.isElementPresent(selector) && selenium.isVisible(selector); } } This works but the code quickly becomes cluttered with calls to waitForXXX() Chris Richardson — Improving tests with Object Mothers and DSLs Slide 54
  • 55. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Better: Implementation #2 Encapsulate the waiting/loop within Test Utility methods, e.g.: assertElementVisible( ) assertElementVisible(…) Benefits: Simplifies the test code 55 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 56. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson A simple example protected void waitForVisibility(String selector) { WaitForElementVisible waiter = new WaitForElementVisible(selector); try { waiter.wait(String.format(quot;Cannot find element <%s>quot;, selector), 3000); } catch (Wait.WaitTimedOutException e) { return; } } public void testSomething() { … class WaitForElementVisible extends Wait { assertElementVisible(quot;someFormquot;); … … } } public void assertElementVisible(String selector) { i F Vi ibili ( l waitForVisibility(selector);) assertTrue(selenium.isVisible(selector)); } Simplifies the test code Chris Richardson — Improving tests with Object Mothers and DSLs Slide 56
  • 57. Summary of web testing Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson architecture Tests T t Application-specific Utility methods Application specific e.g. login(), logout(), … Wrapped selenium APIs e.g. hides Ajax related timing issues etc Selenium RC 57 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 58. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Some useful frameworks Umangite – Selenium web tests code.google.com/p/umangite/ ORMUnit – Persistence tests code.google.com/p/ormunit Arid POJOs Generic DAO A id POJO – G i DAOs code.google.com/p/aridpojos/ And, others: code.google.com/u/chris.e.richardson/ Chris Richardson — Improving tests with Object Mothers and DSLs Slide 58
  • 59. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson Summary Messy tests will kill your application y y pp Aggressively refactor tests to keep them simple Define classes with fluent interfaces Use Object Mothers to avoid duplication of test fixture logic Aggressively use Test Utility Methods: Simplify web tests Hide Ajax-related issues 59 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008
  • 60. Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Chris Richardson For more information Buy my book ☺ Go to G t manning.com i Send email: chris@chrisrichardson.net Visit my website: http://www.chrisrichardson.net Talk to me about consulting and training 60 Chris Richardson — Improving tests with Object Mothers and DSLs 11/10/2008