Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing Legacy Troubles
Search
konrad_126
April 13, 2022
Programming
55
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Testing Legacy Troubles
konrad_126
April 13, 2022
More Decks by konrad_126
See All by konrad_126
Build the right thing
konrad_126
0
120
Build the right thing
konrad_126
0
110
Just D(DD)o it!
konrad_126
0
180
Sailing briefing
konrad_126
0
200
Git under the hood
konrad_126
0
200
No Jira, No Cry
konrad_126
0
190
remotewithlove
konrad_126
0
83
Domain storytelling
konrad_126
0
130
Get, set... STOP
konrad_126
0
200
Other Decks in Programming
See All in Programming
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
440
霧の中の代数的エフェクト
funnyycat
1
460
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
200
VibeCodingからAgenticWorkflowへ
starfish719
0
190
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.4k
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
750
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
160
「人を評価する AI」の設計と実装
ryoyanara
0
150
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
280
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
2.8k
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
4
1.6k
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
170
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
3.9k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Become a Pro
speakerdeck
PRO
31
6.1k
Balancing Empowerment & Direction
lara
6
1.2k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Rails Girls Zürich Keynote
gr2m
96
14k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
270
Being A Developer After 40
akosma
91
590k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
240
Building AI with AI
inesmontani
PRO
1
1.1k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
200
Transcript
TESTING LEGACY TROUBLES @konrad_126
LEGACY CODE? NO TESTS.
THE CASE OF AN IRRITATING PARAMETER
<?php class CalculatePrice { public function __construct(private VatDotComClient $vatProvider) {
} public function calculate(Product $product) : float { $taxRate = $this->vatProvider->getRate($product->countryCode()); // some business logic to calculate price } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public function __construct(private VatDotComClient $vatProvider) <?php 1 2 class CalculatePrice 3 { 4 5 { 6 } 7 8 public function calculate(Product $product) : float 9 { 10 $taxRate = $this->vatProvider->getRate($product->countryCode()); 11 // some business logic to calculate price 12 } 13 } 14 $taxRate = $this->vatProvider->getRate($product->countryCode()); <?php 1 2 class CalculatePrice 3 { 4 public function __construct(private VatDotComClient $vatProvider) 5 { 6 } 7 8 public function calculate(Product $product) : float 9 { 10 11 // some business logic to calculate price 12 } 13 } 14 // some business logic to calculate price <?php 1 2 class CalculatePrice 3 { 4 public function __construct(private VatDotComClient $vatProvider) 5 { 6 } 7 8 public function calculate(Product $product) : float 9 { 10 $taxRate = $this->vatProvider->getRate($product->countryCode()); 11 12 } 13 } 14
<?php class CalculatePriceTest { public function itAppliesTheTaxRate() { $calculateTax =
new CalculatePrice( new VatDotComClient('api-key', 'secret') ); // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 $calculateTax = new CalculatePrice( <?php 1 2 class CalculatePriceTest 3 { 4 public function itAppliesTheTaxRate() 5 { 6 7 new VatDotComClient('api-key', 'secret') 8 ); 9 // ... 10 } 11 } 12 new VatDotComClient('api-key', 'secret') <?php 1 2 class CalculatePriceTest 3 { 4 public function itAppliesTheTaxRate() 5 { 6 $calculateTax = new CalculatePrice( 7 8 ); 9 // ... 10 } 11 } 12
<?php class CalculatePriceTest { public function itAppliesTheTaxRate() { // ...
} public function itAppliesDiscount() { // ... } public function itAppliesVoucher() { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vat.com
<?php class CalculatePriceTest { public function itAppliesTheTaxRate() { // ...
} public function itAppliesDiscount() { // ... } public function itAppliesVoucher() { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 dummy VAT provider
<?php class CalculatePrice { public function __construct(private VatDotComClient $vatProvider) {
} public function calculate(Product $product) { $taxRate = $this->vatProvider->getRate($product->countryCode()); // some business logic to calculate price } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public function __construct(private VatDotComClient $vatProvider) <?php 1 2 class CalculatePrice 3 { 4 5 { 6 } 7 8 public function calculate(Product $product) 9 { 10 $taxRate = $this->vatProvider->getRate($product->countryCode()); 11 // some business logic to calculate price 12 } 13 } 14
<?php interface VatProvider { public function getRate(string $countryCode): float; }
1 2 3 4 5 6 Extract Interface
<?php class CalculatePrice { public function __construct(private VatProvider $vatProvider) {
} public function calculate(Product $product) { $taxRate = $this->vatProvider->getRate($product->countryCode()); // some business logic to calculate price } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public function __construct(private VatProvider $vatProvider) <?php 1 2 class CalculatePrice 3 { 4 5 { 6 } 7 8 public function calculate(Product $product) 9 { 10 $taxRate = $this->vatProvider->getRate($product->countryCode()); 11 // some business logic to calculate price 12 } 13 } 14
<?php class TestProvider implements VatProvider { public function __construct(private float
$rate) { } public function getRate(string $countryCode) { return $this->rate; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 class TestProvider implements VatProvider <?php 1 2 3 { 4 public function __construct(private float $rate) 5 { 6 } 7 8 public function getRate(string $countryCode) 9 { 10 return $this->rate; 11 } 12 } 13 public function __construct(private float $rate) <?php 1 2 class TestProvider implements VatProvider 3 { 4 5 { 6 } 7 8 public function getRate(string $countryCode) 9 { 10 return $this->rate; 11 } 12 } 13 return $this->rate; <?php 1 2 class TestProvider implements VatProvider 3 { 4 public function __construct(private float $rate) 5 { 6 } 7 8 public function getRate(string $countryCode) 9 { 10 11 } 12 } 13
<?php public function itAppliesTheTaxRate() { $calculateTax = new CalculatePrice( new
TestProvider(0.25) ); // ... Assert price what expected (with 0.25 tax rate) } 1 2 3 4 5 6 7 8 9 10 $calculateTax = new CalculatePrice( <?php 1 2 public function itAppliesTheTaxRate() 3 { 4 5 new TestProvider(0.25) 6 ); 7 8 // ... Assert price what expected (with 0.25 tax rate) 9 } 10 new TestProvider(0.25) <?php 1 2 public function itAppliesTheTaxRate() 3 { 4 $calculateTax = new CalculatePrice( 5 6 ); 7 8 // ... Assert price what expected (with 0.25 tax rate) 9 } 10
THE CASE HIDDEN DEPENDENCY
<?php class ProcessPayment { public function __construct() { // ...
} public function process(Payment $payment) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public function __construct() <?php 1 2 class ProcessPayment 3 { 4 5 { 6 // ... 7 } 8 9 public function process(Payment $payment) 10 { 11 // ... 12 } 13 } 14
<?php public function itRecordsThePayment() { $payment = new Payment(340, 'EUR',
12); $processPayment = new ProcessPayment(); $processpayments->process($payment); // ... Assert stuff } 1 2 3 4 5 6 7 8 9 10 11
<?php class ProcessPayment { public function __construct() { // some
code $this->mailer = new Mailer('api-key', 'secret'); // some code } public function process(Payment $payment) { // ... $this->mailer->send( $payment->receiver(), new PaymentNotificationMessage($payment) ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $this->mailer = new Mailer('api-key', 'secret'); <?php 1 2 class ProcessPayment 3 { 4 public function __construct() 5 { 6 // some code 7 8 // some code 9 } 10 11 public function process(Payment $payment) 12 { 13 // ... 14 15 $this->mailer->send( 16 $payment->receiver(), 17 new PaymentNotificationMessage($payment) 18 ); 19 20 } 21 } 22 $this->mailer->send( $payment->receiver(), new PaymentNotificationMessage($payment) ); } } <?php 1 2 class ProcessPayment 3 { 4 public function __construct() 5 { 6 // some code 7 $this->mailer = new Mailer('api-key', 'secret'); 8 // some code 9 } 10 11 public function process(Payment $payment) 12 { 13 // ... 14 15 16 17 18 19 20 21 22
<?php class ProcessPayment { public function __construct() { $this->mailer =
new Mailer('api-key', 'secret'); } public function process(Payment $payment) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
<?php class ProcessPayment { public function __construct(Mailer $mailer) { $this->mailer
= $mailer; } public function process(Payment $payment) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Parameterize Constructor (Extract Interface)
DESIGN?
dependency injection principle strategy design pattern depend on abstract not
a concrete
MORE ADVICE?
THANK YOU @konrad_126