Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Testing Legacy Troubles
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
konrad_126
April 13, 2022
Programming
60
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
130
Build the right thing
konrad_126
0
120
Just D(DD)o it!
konrad_126
0
180
Sailing briefing
konrad_126
0
220
Git under the hood
konrad_126
0
210
No Jira, No Cry
konrad_126
0
220
remotewithlove
konrad_126
0
88
Domain storytelling
konrad_126
0
140
Get, set... STOP
konrad_126
0
210
Other Decks in Programming
See All in Programming
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
1.9k
Event is what happens
moro
2
1.6k
Seven New Principles of Software Engineering
yegor256
0
310
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
1.1k
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
130
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
120
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
370
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.8k
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
1k
GraphQL の onError と Nullability のこれから
quramy
0
180
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
320
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
0
150
Featured
See All Featured
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
300
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
940
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Designing for Timeless Needs
cassininazir
1
530
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
580
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
540
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
900
Google's AI Overviews - The New Search
badams
0
1.6k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.5k
Odyssey Design
rkendrick25
PRO
2
890
The Invisible Side of Design
smashingmag
301
52k
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