Test-Oriented Languages: is
          it time for a new era?
          Ben Stopford : The Royal Bank of Scotland




Friday, 25 March 2011
Mocking is fundamental part
          of Test Driven Development



Friday, 25 March 2011
But how much further can
          we go in current imperative
          languages?



Friday, 25 March 2011
What might we improve if
            we were not inhibited by
            current mainstream
            compilers?


Friday, 25 March 2011
What might we do with a
          blank slate?




Friday, 25 March 2011
Quilt




Friday, 25 March 2011
How is Quilt Different


               Stub methods not classes
               Compiler significantly reduces the amount of test code
               that must be written to provide isolation




Friday, 25 March 2011
Taking step back...



Friday, 25 March 2011
What are the motivations for
           mock driven development?




Friday, 25 March 2011
State based tests inevitably
          overlap
                                     !"#$%&'($%




                        !"#$%&'($%




Friday, 25 March 2011
This makes it hard to
         diagnose the source of a
         break.            !"#$%&'($%




                        !"#$%&'($%




Friday, 25 March 2011
The solution is to use mock
         objects to provide substitute
         interactions that we can
         assert from our test    !"#$%&'($%




              !"#$%&'($%




Friday, 25 March 2011
Current Challenges




Friday, 25 March 2011
Coupling between test and
          source



Friday, 25 March 2011
“I've always been a old
          
 
 
 
 fashioned classic TDDer
          and thus far I don't see any
          reason to change. I don't see any
          compelling benefits for mockist
          TDD, and am concerned about
          the consequences of coupling
          tests to implementation.”
Friday, 25 March 2011
The JMock Era




Friday, 25 March 2011
Mock Interactions




Friday, 25 March 2011
All interactions must be
          explicitly coded in the test


              !"#$%&'($%



Friday, 25 March 2011
The Mockito Era




Friday, 25 March 2011
Only mock interactions you
          care about


         !"#$%&'($%



Friday, 25 March 2011
This reduces coupling
          between test and class




Friday, 25 March 2011
Quilt takes this concept
          further by only requiring
          methods to be stubbed not
          whole objects (but more on
          that later)



Friday, 25 March 2011
The Testing Barrier



               To do Mock-Driven development you need to test first




Friday, 25 March 2011
Should it be like this?




Friday, 25 March 2011
In quilt it’s as easy to test
          after as it is to test first


                        !"#$%&'($%




Friday, 25 March 2011
What Makes Quilt Different?




Friday, 25 March 2011
The complier isolates
          testable units for you.

          Where it needs your input it
          requires that you provide it.


Friday, 25 March 2011
So when you run a test the
          compiler will restrict the
          execution scope, say to a
          single class

                        !"#$%&'($%


Friday, 25 March 2011
If that class under test calls
          other classes the compiler
          will automatically isolate the
          interactions

                        !"#$%&'($%




Friday, 25 March 2011
If those interactions return
          state then the compiler
          requires that a active stub
          be declared in the test

                        !"#$%&'($%



Friday, 25 March 2011
So quilt creates seams
          around the testable unit
          isolating the functionality
          under test         !"#$%&




Friday, 25 March 2011
Methods are Stubbed not
          Objects


                        !"#$%&'($%




Friday, 25 March 2011
Testing units can be one or
          many classes: a Patch
             91,''#'%,2#%)2.60#5%   +,&-"#'%,2#%'#0,2,&#5%
             *$&.%,%:+,&-";%        78%:<#,/';%




   !"#$%&#'($)%&"*'%+,&-"%&"#%
   -./0*1#2%3*11%4.2-#%&"#%
   5#-1,2,(.$%.4%,%'&677#5%
   2#&62$%&80#%4.2%&"*'%/#&".5%
Friday, 25 March 2011
There is no need for
          dependency injection for the
          purpose of testing




Friday, 25 March 2011
The barrier for testing is
          lowered




Friday, 25 March 2011
Looking more closely




Friday, 25 March 2011
Compilation Ensures that
          Stubs are Required only if
          they Affect the Output of the
          Test.




Friday, 25 March 2011
class ConstructionSite{
          	 Digger digger = new Digger();
          	 Mixer mixer = new CementMixer();                           !"#$%&'(($
          	 Foreman foreman = new Foreman();
          	       ConstructionSite(){}

          	       ConstructionSite(Digger d, Mixer m, Foreman f){
          	       	 digger = d;
          	       	 mixer = m;
          	       	 foreman = f;
          	       }
          	       	
          	       boolean buildFoundation(Bricks bricks){
          	       	
          	       	 Cement cement = mixer.mix();
          	       	 Foundation foundation = digger.dig();
          	       	 BrickLayer layer = foreman.getLayer();
          	
          	       	     if(!cement.isSolid() && bricks.size()> 100){
          	       	     	 Posts posts = layer.lay(bricks, cement);
          	       	     	 foundation.fill(posts);
          	       	     	 return true;
          	       	     }
          	       	     return false;
          	       }
          }

Friday, 25 March 2011
!"#$!#%&$
                                                                          '()*)+$
          @Test
          shouldBuildFoundationsWithLotsOfBricksAndSlowDryingCement(){
          	 Digger digger = mock(Digger.class);
          	 CementMixer mixer = mock(CementMixer.class);
          	 Foreman foreman = mock(Foreman.class);
          	 Cement cement = mock(Cement.class);
          	 BrickLayer layer = mock(BrickLayer.class);
          	 Foundation foundation = mock(Foundation.class);
          	       when(mixer.mix()).thenReturn(cement);
          	       when(digger.dig()).thenReturn(foundation);
          	       when(cement.isSolid	 ()).thenReturn(Boolean.FALSE);
          	       when(foreman.getLayer()).thenReturn(layer);
          	
          	       ConstructionSite site = new ConstructionSite(digger, mixer, foreman);
          	       assertTrue(site.buildFoundation(new Bricks(101)))
          }




Friday, 25 March 2011
In all this mock/stub setup only two parts
          are actually pertinent to the test:

             @Test
             shouldBuildFoundationsWithLotsOfBricksAndSlowDryingCement(){
             	 Digger digger = mock(Digger.class);
             	 CementMixer mixer = mock(CementMixer.class);
             	 Foreman foreman = mock(Foreman.class);
             	 Cement cement = mock(Cement.class);
             	 BrickLayer layer = mock(BrickLayer.class);
             	 Foundation foundation = mock(Foundation.class);
             	          when(mixer.mix()).thenReturn(cement);
             	          when(digger.dig()).thenReturn(foundation);
             	          when(cement.isSolid	 ()).thenReturn(Boolean.FALSE);
             	          when(foreman.getLayer()).thenReturn(layer);
             	
             	          ConstructionSite site = new ConstructionSite(digger, mixer, foreman);
             	          assertTrue(site.buildFoundation(new Bricks(101)))
             }


Friday, 25 March 2011
!"#$!#%&$
                                                       '()*+&,$

          shouldBuildFoundationsWithLotsOfBricksAndSlowDryi
          ngCement(){
          	 Seam:
          	 	 cement.isSolid() returns false;
          	 	 bricks.size returns 100;
          	 AssertTrue:
          	 	 new ConstructionSite().buildFoundation(..);
          	
          }}



Friday, 25 March 2011
No need to set up stub objects
          shouldBuildFoundationsWithLotsOfBricksAndSlowDryi
          ngCement(){
          	 Seam:
          	 	 cement.isSolid() returns false;
          	 	 bricks.size returns 100;
          	 AssertTrue:
          	 	 new ConstructionSite().buildFoundation(..);
          	
          }}



Friday, 25 March 2011
Stub Methods not Objects
          shouldBuildFoundationsWithLotsOfBricksAndSlowDryi
          ngCement(){
          	 Seam:
          	 	 cement.isSolid() returns false;
          	 	 bricks.size returns 100;
          	 AssertTrue:
          	 	 new ConstructionSite().buildFoundation(..);
          	
          }}



Friday, 25 March 2011
Avoiding mock object chains


         input.do().do().do() returns “foo”;




Friday, 25 March 2011
Static analysis lies at the
          heart of the Quilt compiler

               The compiler tracks the state used in the class under
               test.
               A bottom up analysis technique allows the compiler to
               exclude cross seam calls that cannot affect the test
               output.




Friday, 25 March 2011
The unit under test should
          be more than one class
             91,''#'%,2#%)2.60#5%   +,&-"#'%,2#%'#0,2,&#5%
             *$&.%,%:+,&-";%        78%:<#,/';%




   !"#$%&#'($)%&"*'%+,&-"%&"#%
   -./0*1#2%3*11%4.2-#%&"#%
   5#-1,2,(.$%.4%,%'&677#5%
   2#&62$%&80#%4.2%&"*'%/#&".5%
Friday, 25 March 2011
Quilt Test: Running multiple
          patches together


            !"#$%&'()%&




Friday, 25 March 2011
Quilt: A new approach to
          testing
               Compiler stubs as much   There is no need to
               as possible              create mock or stub
                                        objects and inject them
               Compiler forces the
                                        into the test
               isolation of the code
               under test               Developer needs to write
                                        the absolute minimum
               Methods are mocked not
                                        amount of test code
               objects
                                        Can even test an existing
                                        class


Friday, 25 March 2011

Test-Oriented Languages: Is it time for a new era?

  • 1.
    Test-Oriented Languages: is it time for a new era? Ben Stopford : The Royal Bank of Scotland Friday, 25 March 2011
  • 2.
    Mocking is fundamentalpart of Test Driven Development Friday, 25 March 2011
  • 3.
    But how muchfurther can we go in current imperative languages? Friday, 25 March 2011
  • 4.
    What might weimprove if we were not inhibited by current mainstream compilers? Friday, 25 March 2011
  • 5.
    What might wedo with a blank slate? Friday, 25 March 2011
  • 6.
  • 7.
    How is QuiltDifferent Stub methods not classes Compiler significantly reduces the amount of test code that must be written to provide isolation Friday, 25 March 2011
  • 8.
  • 9.
    What are themotivations for mock driven development? Friday, 25 March 2011
  • 10.
    State based testsinevitably overlap !"#$%&'($% !"#$%&'($% Friday, 25 March 2011
  • 11.
    This makes ithard to diagnose the source of a break. !"#$%&'($% !"#$%&'($% Friday, 25 March 2011
  • 12.
    The solution isto use mock objects to provide substitute interactions that we can assert from our test !"#$%&'($% !"#$%&'($% Friday, 25 March 2011
  • 13.
  • 14.
    Coupling between testand source Friday, 25 March 2011
  • 15.
    “I've always beena old fashioned classic TDDer and thus far I don't see any reason to change. I don't see any compelling benefits for mockist TDD, and am concerned about the consequences of coupling tests to implementation.” Friday, 25 March 2011
  • 16.
    The JMock Era Friday,25 March 2011
  • 17.
  • 18.
    All interactions mustbe explicitly coded in the test !"#$%&'($% Friday, 25 March 2011
  • 19.
  • 20.
    Only mock interactionsyou care about !"#$%&'($% Friday, 25 March 2011
  • 21.
    This reduces coupling between test and class Friday, 25 March 2011
  • 22.
    Quilt takes thisconcept further by only requiring methods to be stubbed not whole objects (but more on that later) Friday, 25 March 2011
  • 23.
    The Testing Barrier To do Mock-Driven development you need to test first Friday, 25 March 2011
  • 24.
    Should it belike this? Friday, 25 March 2011
  • 25.
    In quilt it’sas easy to test after as it is to test first !"#$%&'($% Friday, 25 March 2011
  • 26.
    What Makes QuiltDifferent? Friday, 25 March 2011
  • 27.
    The complier isolates testable units for you. Where it needs your input it requires that you provide it. Friday, 25 March 2011
  • 28.
    So when yourun a test the compiler will restrict the execution scope, say to a single class !"#$%&'($% Friday, 25 March 2011
  • 29.
    If that classunder test calls other classes the compiler will automatically isolate the interactions !"#$%&'($% Friday, 25 March 2011
  • 30.
    If those interactionsreturn state then the compiler requires that a active stub be declared in the test !"#$%&'($% Friday, 25 March 2011
  • 31.
    So quilt createsseams around the testable unit isolating the functionality under test !"#$%& Friday, 25 March 2011
  • 32.
    Methods are Stubbednot Objects !"#$%&'($% Friday, 25 March 2011
  • 33.
    Testing units canbe one or many classes: a Patch 91,''#'%,2#%)2.60#5% +,&-"#'%,2#%'#0,2,&#5% *$&.%,%:+,&-";% 78%:<#,/';% !"#$%&#'($)%&"*'%+,&-"%&"#% -./0*1#2%3*11%4.2-#%&"#% 5#-1,2,(.$%.4%,%'&677#5% 2#&62$%&80#%4.2%&"*'%/#&".5% Friday, 25 March 2011
  • 34.
    There is noneed for dependency injection for the purpose of testing Friday, 25 March 2011
  • 35.
    The barrier fortesting is lowered Friday, 25 March 2011
  • 36.
  • 37.
    Compilation Ensures that Stubs are Required only if they Affect the Output of the Test. Friday, 25 March 2011
  • 38.
    class ConstructionSite{ Digger digger = new Digger(); Mixer mixer = new CementMixer(); !"#$%&'(($ Foreman foreman = new Foreman(); ConstructionSite(){} ConstructionSite(Digger d, Mixer m, Foreman f){ digger = d; mixer = m; foreman = f; } boolean buildFoundation(Bricks bricks){ Cement cement = mixer.mix(); Foundation foundation = digger.dig(); BrickLayer layer = foreman.getLayer(); if(!cement.isSolid() && bricks.size()> 100){ Posts posts = layer.lay(bricks, cement); foundation.fill(posts); return true; } return false; } } Friday, 25 March 2011
  • 39.
    !"#$!#%&$ '()*)+$ @Test shouldBuildFoundationsWithLotsOfBricksAndSlowDryingCement(){ Digger digger = mock(Digger.class); CementMixer mixer = mock(CementMixer.class); Foreman foreman = mock(Foreman.class); Cement cement = mock(Cement.class); BrickLayer layer = mock(BrickLayer.class); Foundation foundation = mock(Foundation.class); when(mixer.mix()).thenReturn(cement); when(digger.dig()).thenReturn(foundation); when(cement.isSolid ()).thenReturn(Boolean.FALSE); when(foreman.getLayer()).thenReturn(layer); ConstructionSite site = new ConstructionSite(digger, mixer, foreman); assertTrue(site.buildFoundation(new Bricks(101))) } Friday, 25 March 2011
  • 40.
    In all thismock/stub setup only two parts are actually pertinent to the test: @Test shouldBuildFoundationsWithLotsOfBricksAndSlowDryingCement(){ Digger digger = mock(Digger.class); CementMixer mixer = mock(CementMixer.class); Foreman foreman = mock(Foreman.class); Cement cement = mock(Cement.class); BrickLayer layer = mock(BrickLayer.class); Foundation foundation = mock(Foundation.class); when(mixer.mix()).thenReturn(cement); when(digger.dig()).thenReturn(foundation); when(cement.isSolid ()).thenReturn(Boolean.FALSE); when(foreman.getLayer()).thenReturn(layer); ConstructionSite site = new ConstructionSite(digger, mixer, foreman); assertTrue(site.buildFoundation(new Bricks(101))) } Friday, 25 March 2011
  • 41.
    !"#$!#%&$ '()*+&,$ shouldBuildFoundationsWithLotsOfBricksAndSlowDryi ngCement(){ Seam: cement.isSolid() returns false; bricks.size returns 100; AssertTrue: new ConstructionSite().buildFoundation(..); }} Friday, 25 March 2011
  • 42.
    No need toset up stub objects shouldBuildFoundationsWithLotsOfBricksAndSlowDryi ngCement(){ Seam: cement.isSolid() returns false; bricks.size returns 100; AssertTrue: new ConstructionSite().buildFoundation(..); }} Friday, 25 March 2011
  • 43.
    Stub Methods notObjects shouldBuildFoundationsWithLotsOfBricksAndSlowDryi ngCement(){ Seam: cement.isSolid() returns false; bricks.size returns 100; AssertTrue: new ConstructionSite().buildFoundation(..); }} Friday, 25 March 2011
  • 44.
    Avoiding mock objectchains input.do().do().do() returns “foo”; Friday, 25 March 2011
  • 45.
    Static analysis liesat the heart of the Quilt compiler The compiler tracks the state used in the class under test. A bottom up analysis technique allows the compiler to exclude cross seam calls that cannot affect the test output. Friday, 25 March 2011
  • 46.
    The unit undertest should be more than one class 91,''#'%,2#%)2.60#5% +,&-"#'%,2#%'#0,2,&#5% *$&.%,%:+,&-";% 78%:<#,/';% !"#$%&#'($)%&"*'%+,&-"%&"#% -./0*1#2%3*11%4.2-#%&"#% 5#-1,2,(.$%.4%,%'&677#5% 2#&62$%&80#%4.2%&"*'%/#&".5% Friday, 25 March 2011
  • 47.
    Quilt Test: Runningmultiple patches together !"#$%&'()%& Friday, 25 March 2011
  • 48.
    Quilt: A newapproach to testing Compiler stubs as much There is no need to as possible create mock or stub objects and inject them Compiler forces the into the test isolation of the code under test Developer needs to write the absolute minimum Methods are mocked not amount of test code objects Can even test an existing class Friday, 25 March 2011