Upload
-
View
5.613
Download
2
Embed Size (px)
Citation preview
TDD By Example
Piya Lumyong
In the past
● Chaos
Design not clearCommunicationQuality
Evolution
Dirty Hacking
Automated Testing
Test-First Dev.
TDD
BDD
...
Requirements engineering process
analysis
An essential user interface prototypeprototype
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?
TransferService
FeePolicyAccRepository(DAO)
ในการโอนเงนแตละครง ผใชจะตองระบหมายเลขบญช
ปลายทางทตองการโอน โดยยอดเงนทโอนตองไมตำกวายอดเงนขนตำ
ในการโอนซงถกกำหนดโดยเจาหนาท และในการโอนเงนลกคา
จะถกหกคาธรรมเนยมตามอตราทธนาคารกำหนด<< Dependency >>
<< Dependency >>
Jigsaw
TransferService
FeePolicyAccRepository(DAO)
<< Dependency >>
<< Dependency >>
?
How do we know what our service should be like if we don't try to use it?
?
use
usetest
testtest
Lab Step2 ->
TransferService
FeePolicyAccRepository(DAO)
<< Dependency >>
<< Dependency >>
FeePolicy
Lab2
● Draft FeePolicy
● Write FlatFeePolicyTest
● Write interface FeePolicy
● Implement FlatFeePolicy
public interface FeePolicy {
public double calculateFee(double transferAmount);
}
Service
● What's next?
TransferService
FeePolicyAccRepository(DAO)
<< Dependency >>
<< Dependency >>
?
Trouble
● How to write unit test which result not depend on dependency?
TransferService
FeePolicyAccRepository(DAO)
<< Dependency >>
<< Dependency >>
?
?
?
Able to control.
Solution
● Use anything that I can control.– Static stub (utility, fake, dummy class)
– Dynamic stub
Lab Step3 ->
Lab3
● Draft TransferService
● Write DefaultTransferServiceTest
● Write interface TransferService
● Draft AccountRepository
● Write interface AccountRepository
● Implement all static stub
● Implement DefaultTransferService
public interface TransferService {TransferReceipt transfer(double amount, String srcAcctId, String destAcctId);void setMinimumTransferAmount(double minimumTransferAmount);
}
public interface AccountRepository { Account findById(String srcAcctId); void updateBalance(Account dstAcct);}
Trouble
● Additional need.
คาธรรมเนยมการโอน 100 - 1,000 ไมเสยคาโอน1,001 - 1,000,000 เสยเปน %สวน 1,000,001 จะเสยเปน Flat Rate
Solution
interface
TransferService
FeePolicyAccRepository(DAO)
<< Dependency >>
<< Dependency >>
The Workshop
New implemention of interface FeePolicy !!All right I'm ok. FeePolicy was depended on me through interface.
Lab Step4
Trouble
● Additional need.
ลกคาจะไมสามารถทำรายการโอนไดหลงสทมเปนตนไปจนถงหกโมงเชา(รเหตผลแตไมอยากบอก)
The Workshop
TransferService
FeePolicy
AccRepository(DAO)
<< Dependency >>
<< Dependency >>
Services at present
?
?
<< Dependency >>
TimeService
Lab Step5 >
Lab5
● Draft TimeService
● Write DefaultTimeServiceTest
● Write interface TimeService
● Implement DefaultTimeService
public interface TimeService {boolean isServiceAvailable(LocalTime testTime);
}
Service
TransferService
FeePolicy
AccRepository(DAO)
<< Dependency >>
<< Dependency >>
Services at present
?
<< Dependency >>
TimeService
use
usetest
testtest
TimeService
Use the Service
Caller ?
TimeServiceTransferService
Must change
Caller
TimeService
TransferService
Proxy
Refactoring
AOP
Refactoring
use
usetest
testtest
TimeService
I'm sure about my work.
?
TransferService
Call
TransferServiceTest
How do I verify TransferService calling TimeService right?
TransferServiceTest
Trouble● How do I know ?
– TransferService call TimeService really.
– In the test, I can't control 'time', TransferService sents to TimeService.
TransferReceipt transfer(...) {...if (timeService.isServiceAvailable(new LocalTime())) {
...}
}
TransferService
Call
Test call
TimeService
Can't control
Solution
● Use anything that I can control.– Static mock (special class)
– Dynamic mock
The Workshop
?
TransferService
Call
TransferServiceTest
?
TimeService
Able to capture TransferService behaviorLab Step6 >
AOP