SlideShare une entreprise Scribd logo
1  sur  29
Télécharger pour lire hors ligne
TDD By Example
            Piya Lumyong
In the past
●   Chaos


             Design not clear
             Communication
             Quality
Evolution
                                       TDD

 Automated Testing

                                             BDD




Dirty Hacking
                     Test-First Dev.
         ...
Requirements engineering process
analysis
An essential user interface prototype
                        prototype

                                    CRC card
The Workshop
●   Requirement
        –   RESTful WS สำหรับการโอนเงิน
The Workshop
●   Raw need

                 ในการโอนเงินแต่ละครั้ง ผู้ใช้จะต้องระบุหมายเลขบัญชี

     ปลายทางที่ต้องการโอน โดยยอดเงินที่โอนต้องไม่ต่ำกว่ายอดเงินขั้นต่ำ

     ในการโอนซึ่งถูกกำหนดโดยเจ้าหน้าที่ และในการโอนเงินลูกค้า

     จะถูกหักค่าธรรมเนียมตามอัตราที่ธนาคารกำหนด




                                                      And etc.
The Workshop
●   Which is our domain model?




         Account
                                  TransferReceipt

                     Lab Step1
Service
●   Which is our service?

                 ในการโอนเงินแต่ละครั้ง ผู้ใช้จะต้องระบุหมายเลขบัญชี
                  FeePolicy
                                                                          AccRepository(DAO)
     ปลายทางที่ต้องการโอน โดยยอดเงินที่โอนต้องไม่ต่ำกว่ายอดเงินขั้นต่ำ
                                          >>
                                        ncy
                                   nde
                                epe
                            < D หน้าที่ และในการโอนเงินลูกค้า
     ในการโอนซึ่งถูกกำหนดโดยเจ้า
                           <


     จะถูกหักค่าธรรมเนียมตามอัตราที่ธนาคารกำหนด
                                                   << Depe
                                                           n   dency >
                                                                      >




      TransferService
Jigsaw
How do we know what our service should be like if we don't try to use it?


       FeePolicy                                   use
                                        ?                    AccRepository(DAO)
                           >
                                            test                   test
                         y>
                    ndenc
                Depe
             <<
                                                         ?
                               << Depe
                                       ndency
                                              >>
                                                                    test
                                        use

TransferService
                                                    FeePolicy

                               Lab Step2 ->
Lab2
●   Draft FeePolicy

        public interface FeePolicy {

                public double calculateFee(double transferAmount);
        }




●   Write FlatFeePolicyTest
●   Write interface FeePolicy
●   Implement FlatFeePolicy
Service
●   What's next?

               FeePolicy
                                                               AccRepository(DAO)
                                   >>
                               ncy
                           nde
                       Depe
                    <<

           ?
                                        << Depe
                                                n   dency >
                                                           >




      TransferService
Trouble
●   How to write unit test which result not depend on dependency?


               FeePolicy
                                                      ?        AccRepository(DAO)
                                   >>
                               ncy
                           nde
                       Depe
                    <<

           ?
                                        << Depe
                                                n   dency >
                                                           >
                                                                   ?

      TransferService
                                  Able to control.
Solution
●   Use anything that I can control.
        –   Static stub (utility, fake, dummy class)
        –   Dynamic stub




                         Lab Step3 ->
Lab3
●   Draft TransferService
      public interface TransferService {
           TransferReceipt transfer(double amount, String srcAcctId, String destAcctId);
           void setMinimumTransferAmount(double minimumTransferAmount);
      }


●   Write DefaultTransferServiceTest
●   Write interface TransferService
●   Draft AccountRepository
                            public interface AccountRepository {
                                Account findById(String srcAcctId);
                                void updateBalance(Account dstAcct);
                            }


●   Write interface AccountRepository
●   Implement all static stub
●   Implement DefaultTransferService
Trouble
●   Additional need.



              ค่าธรรมเนียมการโอน 100 - 1,000 ไม่เสียค่าโอน
              1,001 - 1,000,000 เสียเป็น %
              ส่วน 1,000,001 จะเสียเป็น Flat Rate
Solution




interface
The Workshop

       FeePolicy
                                                          AccRepository(DAO)
                              >>
                       de ncy
                   n
               Depe
            <<



                                   << Depe
                                           n   dency >
                                                      >




TransferService
            New implemention of interface FeePolicy !!
            All right I'm ok. FeePolicy was depended on me through interface.

                                   Lab Step4
Trouble
●   Additional need.



     ลูกค้าจะไม่สามารถทำรายการโอนได้หลังสี่ทุ่มเป็นต้นไปจนถึงหกโมงเช้า
     (รู้เหตุผลแต่ไม่อยากบอก)
The Workshop
                                                      FeePolicy
TimeService

              Services at present?
                           >>
                      cy
                   den
                 en
              Dep
           <<                              >
                                    ency >
                           << Depend


     ?
                   <<
                        De
                           pe
                              nd
                                en
                                  cy
                                       >>      AccRepository(DAO)

TransferService


                                                  Lab Step5 >
Lab5
●   Draft TimeService

           public interface TimeService {
               boolean isServiceAvailable(LocalTime testTime);
           }




●   Write DefaultTimeServiceTest
●   Write interface TimeService
●   Implement DefaultTimeService
Service
                                                   Services at present
TimeService                                        TimeService
                                          use                      FeePolicy
                               >
                             y>
                        nc                       test
                    nde       test
                 pe
              De
           <<

                              << Dependency >>

     ?
                     <<
                        De
                           pe
                              nd                   test
                       use ency
                                     >>
                                                          AccRepository(DAO)

TransferService
Use the Service
                                        TransferService     TimeService
Refactoring


              Caller                ?


                                            Must change

                            TransferService
   AOP                                                    Proxy


                       Caller




                                              TimeService
Refactoring
                                                                TimeService

 TransferServiceTest                        use
                                     test                   test


            ?               Call




                                                                test
                                   use
TransferService

                                                   I'm sure about my work.


   How do I verify TransferService calling TimeService right?
Trouble
●   How do I know ?
          –    TransferService call TimeService really.
          –    In the test, I can't control 'time', TransferService sents to
                  TimeService.
                                                       TimeService
    TransferServiceTest
                                    TransferService
       Test call


                                                         all
                                                         C
                   TransferReceipt transfer(...) {
                        ...
                        if (timeService.isServiceAvailable(new LocalTime())) {
                             ...
                        }
                   }
                                                                          Can't control
Solution
●   Use anything that I can control.
        –   Static mock (special class)
        –   Dynamic mock
The Workshop


                       TransferServiceTest

                                Call

                   ?                            ?



                 TransferService       TimeService




Able to capture TransferService behavior
                                                     Lab Step6 >
AOP

Contenu connexe

Plus de ทวิร พานิชสมบัติ

Plus de ทวิร พานิชสมบัติ (20)

Legacy Code For Management
Legacy Code For ManagementLegacy Code For Management
Legacy Code For Management
 
Security As A Code :
Security As A Code : Security As A Code :
Security As A Code :
 
ATDD
ATDDATDD
ATDD
 
กระบวนการเชิงประจักษ์ (Empirical Process)
กระบวนการเชิงประจักษ์ (Empirical Process)กระบวนการเชิงประจักษ์ (Empirical Process)
กระบวนการเชิงประจักษ์ (Empirical Process)
 
Geeky Ademy Schedule 2nd Batch
Geeky Ademy Schedule 2nd BatchGeeky Ademy Schedule 2nd Batch
Geeky Ademy Schedule 2nd Batch
 
การทำซอฟท์แวร์ภายใน 30 วัน
การทำซอฟท์แวร์ภายใน 30 วันการทำซอฟท์แวร์ภายใน 30 วัน
การทำซอฟท์แวร์ภายใน 30 วัน
 
Geek Academy Schedule
Geek Academy ScheduleGeek Academy Schedule
Geek Academy Schedule
 
Kku2011
Kku2011Kku2011
Kku2011
 
Scrum version3
Scrum version3Scrum version3
Scrum version3
 
Geeky academy
Geeky academyGeeky academy
Geeky academy
 
Agile
AgileAgile
Agile
 
Bdd bug day2013
Bdd bug day2013Bdd bug day2013
Bdd bug day2013
 
Scrum Version 3
Scrum Version 3Scrum Version 3
Scrum Version 3
 
Fixie atbarcampbangkok5
Fixie atbarcampbangkok5Fixie atbarcampbangkok5
Fixie atbarcampbangkok5
 
Scrum version2
Scrum version2Scrum version2
Scrum version2
 
Agile V2
Agile V2Agile V2
Agile V2
 
Start upandagile final
Start upandagile finalStart upandagile final
Start upandagile final
 
Scrum by roofimon
Scrum by roofimonScrum by roofimon
Scrum by roofimon
 
Power of pair programming
Power of pair programmingPower of pair programming
Power of pair programming
 
Introduction to Agile for SIPA
Introduction to Agile for SIPAIntroduction to Agile for SIPA
Introduction to Agile for SIPA
 

Tdd by exam 2

  • 1. TDD By Example Piya Lumyong
  • 2. In the past ● Chaos Design not clear Communication Quality
  • 3. Evolution TDD Automated Testing BDD Dirty Hacking Test-First Dev. ...
  • 6. An essential user interface prototype prototype CRC card
  • 7. The Workshop ● Requirement – RESTful WS สำหรับการโอนเงิน
  • 8. The Workshop ● Raw need ในการโอนเงินแต่ละครั้ง ผู้ใช้จะต้องระบุหมายเลขบัญชี ปลายทางที่ต้องการโอน โดยยอดเงินที่โอนต้องไม่ต่ำกว่ายอดเงินขั้นต่ำ ในการโอนซึ่งถูกกำหนดโดยเจ้าหน้าที่ และในการโอนเงินลูกค้า จะถูกหักค่าธรรมเนียมตามอัตราที่ธนาคารกำหนด And etc.
  • 9. The Workshop ● Which is our domain model? Account TransferReceipt Lab Step1
  • 10. Service ● Which is our service? ในการโอนเงินแต่ละครั้ง ผู้ใช้จะต้องระบุหมายเลขบัญชี FeePolicy AccRepository(DAO) ปลายทางที่ต้องการโอน โดยยอดเงินที่โอนต้องไม่ต่ำกว่ายอดเงินขั้นต่ำ >> ncy nde epe < D หน้าที่ และในการโอนเงินลูกค้า ในการโอนซึ่งถูกกำหนดโดยเจ้า < จะถูกหักค่าธรรมเนียมตามอัตราที่ธนาคารกำหนด << Depe n dency > > TransferService
  • 11. Jigsaw How do we know what our service should be like if we don't try to use it? FeePolicy use ? AccRepository(DAO) > test test y> ndenc Depe << ? << Depe ndency >> test use TransferService FeePolicy Lab Step2 ->
  • 12. Lab2 ● Draft FeePolicy public interface FeePolicy { public double calculateFee(double transferAmount); } ● Write FlatFeePolicyTest ● Write interface FeePolicy ● Implement FlatFeePolicy
  • 13. Service ● What's next? FeePolicy AccRepository(DAO) >> ncy nde Depe << ? << Depe n dency > > TransferService
  • 14. Trouble ● How to write unit test which result not depend on dependency? FeePolicy ? AccRepository(DAO) >> ncy nde Depe << ? << Depe n dency > > ? TransferService Able to control.
  • 15. Solution ● Use anything that I can control. – Static stub (utility, fake, dummy class) – Dynamic stub Lab Step3 ->
  • 16. Lab3 ● Draft TransferService public interface TransferService { TransferReceipt transfer(double amount, String srcAcctId, String destAcctId); void setMinimumTransferAmount(double minimumTransferAmount); } ● Write DefaultTransferServiceTest ● Write interface TransferService ● Draft AccountRepository public interface AccountRepository { Account findById(String srcAcctId); void updateBalance(Account dstAcct); } ● Write interface AccountRepository ● Implement all static stub ● Implement DefaultTransferService
  • 17. Trouble ● Additional need. ค่าธรรมเนียมการโอน 100 - 1,000 ไม่เสียค่าโอน 1,001 - 1,000,000 เสียเป็น % ส่วน 1,000,001 จะเสียเป็น Flat Rate
  • 19. The Workshop FeePolicy AccRepository(DAO) >> de ncy n Depe << << Depe n dency > > TransferService New implemention of interface FeePolicy !! All right I'm ok. FeePolicy was depended on me through interface. Lab Step4
  • 20. Trouble ● Additional need. ลูกค้าจะไม่สามารถทำรายการโอนได้หลังสี่ทุ่มเป็นต้นไปจนถึงหกโมงเช้า (รู้เหตุผลแต่ไม่อยากบอก)
  • 21. The Workshop FeePolicy TimeService Services at present? >> cy den en Dep << > ency > << Depend ? << De pe nd en cy >> AccRepository(DAO) TransferService Lab Step5 >
  • 22. Lab5 ● Draft TimeService public interface TimeService { boolean isServiceAvailable(LocalTime testTime); } ● Write DefaultTimeServiceTest ● Write interface TimeService ● Implement DefaultTimeService
  • 23. Service Services at present TimeService TimeService use FeePolicy > y> nc test nde test pe De << << Dependency >> ? << De pe nd test use ency >> AccRepository(DAO) TransferService
  • 24. Use the Service TransferService TimeService Refactoring Caller ? Must change TransferService AOP Proxy Caller TimeService
  • 25. Refactoring TimeService TransferServiceTest use test test ? Call test use TransferService I'm sure about my work. How do I verify TransferService calling TimeService right?
  • 26. Trouble ● How do I know ? – TransferService call TimeService really. – In the test, I can't control 'time', TransferService sents to TimeService. TimeService TransferServiceTest TransferService Test call all C TransferReceipt transfer(...) { ... if (timeService.isServiceAvailable(new LocalTime())) { ... } } Can't control
  • 27. Solution ● Use anything that I can control. – Static mock (special class) – Dynamic mock
  • 28. The Workshop TransferServiceTest Call ? ? TransferService TimeService Able to capture TransferService behavior Lab Step6 >
  • 29. AOP