why your test suite sucks
TRANSCRIPT
![Page 1: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/1.jpg)
Why$Your$Test$Suite$Sucks(and%what%you%can%do%about%it)
by#Ciaran&McNulty#at#PHPUK&2015
![Page 2: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/2.jpg)
It’s%not%working%for%me
===
TDD#must#suck1
1"BIT.LY/1LEF0GI"&"BIT.LY/1SLFGTQ"
![Page 3: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/3.jpg)
The$problem$is$not$TDD
![Page 4: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/4.jpg)
The$problem$is$your%suite
![Page 5: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/5.jpg)
Value!=!Benefits!)!Costs
![Page 6: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/6.jpg)
Suites'suck'when'you'aren’t'ge)ng'all'the'benefits'of'TDD
![Page 7: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/7.jpg)
Suites'suck'when'the'tests'are$hard$to$maintain
![Page 8: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/8.jpg)
Reason'1:You$don't$have$a$test$suite
![Page 9: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/9.jpg)
The$Evolu*on$of$a$TDD$Team
![Page 10: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/10.jpg)
Maturity(model
• Manual"tes&ng
• Automated"tes&ng
• Test.first"development
• Test.driven"development
![Page 11: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/11.jpg)
Manual&tes*ng
• Design"an"implementa+on
• Implement"that"design
• Manually"test
![Page 12: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/12.jpg)
Growing(from(Manual(to(Automated
• “When'we'make%changes,'it'breaks'things!”
• “We'spend'a%lot%of%/me'on'manual'tes:ng”
• “Bugs'keep'making'it'into'produc:on”
Enabled(by:+(Tutorials,(training+(Team(policies
![Page 13: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/13.jpg)
Automated)tes+ng
• Design"an"implementa+on
• Implement"that"design
• Write.tests"to"verify"it
![Page 14: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/14.jpg)
Growing(from(Automated(to(Test3first
• “It’s'a'pain'having'to'write'tests'once'I’m'done”
• “My'test'suite'is'bri'le”
• “Maintaining'the'suite'is'hard”'
• ”TDD/Doesn’t/Work!”
Supported)by:-)Coaching,)pairing-)Leadership
![Page 15: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/15.jpg)
Test%first(development
• Design"an"implementa+on
• Write*tests"to"verify"that"implementa+on
• Implement"that"design
![Page 16: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/16.jpg)
Growing(from(Test/first(to(Test/driven
• “Test'suite'is's"ll'bri,le”
• “Maintaining'the'suite'is's"ll'hard”'
• ”TDD'Doesn’t'Work!”
Supported)by:-)Prac1ce
![Page 17: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/17.jpg)
Test%driven+development
• Write&tests"that"describe"behaviour
• Implement"a"system"that"has"that"behaviour
Problems:*+“I+don’t+know+what+to+do+with+all+this+spare&'me!”*+“Where+should+we+keep+this+extra&money?”
![Page 18: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/18.jpg)
Reason'2:You$are$tes*ng$implementa*on
![Page 19: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/19.jpg)
Problem:)Mocking)Queries
• A#query#is#a#method#that#returns'a'value'without'side'effects#
• We#shouldn’t'care#how#many#4mes#(if#any)#a#query#is#called
• Specifying#that#detail#makes'change'harder
![Page 20: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/20.jpg)
function testItGreetsPeopleByName(){ $user = $this->getMock('User');
$user->expects($this->once()) ->method('getName') ->willReturn('Ciaran');
$greeting = $this->greeter->greet($user);
$this->assertEquals('Hello, Ciaran!', $greeting);}
![Page 21: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/21.jpg)
function testItGreetsPeopleByName(){ $user = $this->getMock('User');
$user->method('getName') ->willReturn('Ciaran');
$greeting = $this->greeter->greet($user);
$this->assertEquals('Hello, Ciaran!', $greeting);}
![Page 22: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/22.jpg)
Don’t&mock&queries,"just"use"stubsDo#you#really#care#how#many#/mes#it's#called?
![Page 23: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/23.jpg)
Problem:)Tes,ng)the)sequence)of)calls
• Most&of&the&*me&we&don’t&care&what%order%calls%are%made%in
• Tes*ng&the&sequence&makes&it&hard%to%change
![Page 24: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/24.jpg)
public function testBasketTotals(){ $priceList = $this->getMock('PriceList');
$priceList->expect($this->at(0)) ->method('getPrices') ->willReturn(120);
$priceList->expect($this->at(1)) ->method('getPrices') ->willReturn(200);
$this->basket->add('Milk', 'Bread'); $total = $this->basket->calculateTotal();
$this->assertEqual(320, $total);}
![Page 25: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/25.jpg)
public function testBasketTotals(){ $priceList = $this->getMock('PriceList');
$priceList->method('getPrices') ->will($this->returnValueMap([ ['Milk', 120], ['Bread', 200] ]));
$this->basket->add('Milk', 'Bread'); $total = $this->basket->calculateTotal();
$this->assertEqual(320, $total);}
![Page 26: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/26.jpg)
Test%behaviour%you%care%about,"don’t"test"implementa/on
PROTIP:!The!best!way!to!do!this!is!to!not!have!an!implementa3on!yet
![Page 27: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/27.jpg)
Reason'3:Because'your'design'sucks
![Page 28: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/28.jpg)
Problem:)Too)many)Doubles
• It$is$painful$to$have$to$double,lots,of,objects$in$your$test
• It$is$a$signal$your$object,has,too,many,dependencies$
![Page 29: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/29.jpg)
public function setUp(){ $chargerules = $this->getMock('ChargeRules'); $chargetypes = $this->getMock('ChargeTypes'); $notifier = $this->getMockBuilder('Notifier') ->disableOriginalConstructor()->getMock();
$this->processor = new InvoiceProcessor( $chargerules, $chargetypes, $notifier ); }
![Page 30: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/30.jpg)
class InvoiceProcessor{ public function __construct( ChargeRules $chargeRules, ChargeTypes $chargeTypes, Notifier $notifier ) { $this->chargeRules = $chargeRules; $this->chargeTypes = $chargeTypes; $this->notifier = $notifier; }
// …
![Page 31: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/31.jpg)
Too#many#doubles!in!your!test!mean!your!class!has!too#many#
dependencies
![Page 32: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/32.jpg)
Problem:)Stubs)returning)stubs
• A#related#painful#issue#is#stubs%returning%a%stubs
• It#is#a#signal#our#object#does%not%have%the%right%dependencies
![Page 33: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/33.jpg)
public function it_notifies_the_user( User $user, Contact $contact, Email $email, Emailer $emailer){ $this->beConstructedWith($emailer);
$user->getContact()->willReturn($contact); $contact->getEmail()->willReturn($email);
$this->notify($user);
$emailer->sendTo($email)->shouldHaveBeenCalled();}
![Page 34: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/34.jpg)
class Notifier{ public function __construct(Emailer $emailer) { // … }
public function notify(User $user) { $email = $user->getContact()->getEmail()
$this->emailer->sendTo($email); }}
![Page 35: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/35.jpg)
class Notifier{ public function __construct(Emailer $emailer) { // … }
public function notify(User $user) { $this->emailer->sendTo($user); }}
![Page 36: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/36.jpg)
class Notifier{ public function __construct(Emailer $emailer) { // … }
public function notify(Email $email) { $this->emailer->sendTo($email); }}
![Page 37: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/37.jpg)
public function it_notifies_the_user( Email $email, Emailer $emailer){ $this->beConstructedWith($emailer);
$this->notify($email);
$emailer->sendTo($email)->shouldHaveBeenCalled();}
![Page 38: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/38.jpg)
Stubs&returning&stubs&indicate&dependencies(are(not(correctly(
defined
![Page 39: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/39.jpg)
Problem:)Par+ally)doubling)the)object)under)test
• A#common%ques*on#is#“how#can#I#mock#methods#on#the#SUT?”#
• Easy#to#do#in#some#tools,#impossible%in%others
• It#is#a#signal#our%object%has%too%many%responsibili*es
![Page 40: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/40.jpg)
class Form{ public function handle($data) { if ($this->validate($data)) { return 'Valid'; }
return 'Invalid'; }
protected function validate($data) { // do something complex }}
![Page 41: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/41.jpg)
function testItOutputsMessageOnValidData(){ $form = $this->getMock('Form', ['validate']); $form->method('validate')->willReturn(true);
$result = $form->handle([]);
$this->assertSame('Valid', $result);}
![Page 42: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/42.jpg)
class Form{ protected function __construct(Validator $validator) { // … }
public function handle($data) { if ($this->validator->validate($data)) { return 'Valid'; }
return 'Invalid'; }}
![Page 43: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/43.jpg)
function testItOutputsMessageOnValidData(){ $validator = $this->getMock(‘Validator’); $validator->method('validate')->willReturn(true);
$form = new Form($validator);
$result = $form->handle([]);
$this->assertSame('Valid', $result);}
![Page 44: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/44.jpg)
If#you#want#to#mock#part#of#the#SUT#it#means#you$should$really$have$
more$than$one$object
![Page 45: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/45.jpg)
How$to$be$a$be)er$so,ware$designer:
• Stage&1:#Think#about#your#code#before#you#write#it#
• Stage&2:#Write#down#those#thoughts
• Stage&3:#Write#down#those#thoughts#as#code#
![Page 46: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/46.jpg)
How$long$will$it$take$without$TDD?
• 1"hour"thinking"about"how"it"should"work"
• 30"mins"Implemen6ng"it
• 30"mins"Checking"it"works"
![Page 47: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/47.jpg)
How$long$will$it$take$with$TDD?
• 1"hour"Thinking"in"code"about"how"it"should"work
• 30"mins"Implemen8ng"it
• 1"min"Checking"it"works"
![Page 48: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/48.jpg)
Use$your$test$suite$as$a$way$to$reason'about'the'code
![Page 49: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/49.jpg)
Customers)should)not)dictate)your)design'process
![Page 50: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/50.jpg)
Reason'4:You$are$unit$tes,ng$across$domain$
boundaries
![Page 51: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/51.jpg)
Problem:)Tes,ng)3rd)party)code
• When&we&extend&a&library&or&framework&we&use$other$people’s$code
• To&test&our&code&we&end&up&tes.ng$their$code&too
• This&:me&is&wasted&–&we&should&trust&their&code&works&
![Page 52: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/52.jpg)
class UserRepository extends \Framework\Repository{ public function findByEmail($email) { $this->find(['email' => $email]); }}
![Page 53: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/53.jpg)
public function it_finds_the_user_by_email( \Framework\DatabaseConnection $db, \Framework\SchemaCreator $schemaCreator, \Framework\Schema $schema, User $user){ $this->beConstructedWith($db, $schemaCreator);
$schemaCreator->getSchema()->willReturn($schema); $schema->getMappings()->willReturn('email'=>'email');
$user = $this->findByEmail('[email protected]');
$user->shouldHaveType('User');}
![Page 54: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/54.jpg)
class UserRepository{ private $repository;
public function __construct(\Framework\Repository $repository) { $this->repository = $repository; }
public function findByEmail($email) { return $this->repository->find(['email' => $email]); }}
![Page 55: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/55.jpg)
public function it_finds_the_user_by_email( Repository $repository, User $user){ $this->beConstructedWith($repository);
$repository->find(['email' => '[email protected]') ->willReturn($user);
$this->findByEmail('[email protected]'); ->shouldEqual($user);}
![Page 56: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/56.jpg)
When%you%extend%third%party%code,%you%take%responsibility%for%its%
design%decisions
![Page 57: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/57.jpg)
Favour'composi'on'over'inheritance
![Page 58: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/58.jpg)
Problem:)Doubling)3rd)party)code• Test&Doubles&(Mocks,&Stubs,&Fakes)&are&used&to&test&communica(on&between&objects&
• Tes:ng&against&a&Double&of&a&3rd&party&object&does,not,give,us,confidence&that&we&have&described&the&communica:on&correctly
![Page 59: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/59.jpg)
class FileHandlerSpec extends ObjectBehaviour{ public function it_uploads_data_to_the_cloud_when_valid( CloudApi $client, FileValidator $validator, File $file ) { $this->beConstructedWith($client, $validator);
$validator->validate($file)->willReturn(true);
$client->startUpload()->shouldBeCalled(); $client->uploadData(Argument::any())->shouldBeCalled(); $client->uploadSuccessful()->willReturn(true);
$this->process($file)->shouldReturn(true); }}
![Page 60: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/60.jpg)
Coupled(architecture
![Page 61: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/61.jpg)
Coupled(architecture
![Page 62: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/62.jpg)
Layered'architecture
![Page 63: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/63.jpg)
Tes$ng'layered'architecture
![Page 64: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/64.jpg)
class FileHandlerSpec extends ObjectBehaviour{ public function it_uploads_data_to_the_cloud_when_valid( FileStore $filestore, FileValidator $validator, File $file ) { $this->beConstructedWith($filestore, $validator); $validator->validate($file)->willReturn(true);
$this->process($file);
$filestore->store($file)->shouldHaveBeenCalled(); }}
![Page 65: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/65.jpg)
Tes$ng'layered'architecture
![Page 66: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/66.jpg)
class CloudFilestoreTest extends PHPUnit_Framework_TestCase{ function testItStoresFiles() { $testCredentials = … $file = new File(…);
$apiClient = new CloudApi($testCredentials); $filestore = new CloudFileStore($apiClient);
$filestore->store($file);
$this->assertTrue($apiClient->fileExists(…)); }}
![Page 67: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/67.jpg)
Tes$ng'layered'architecture
![Page 68: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/68.jpg)
Don’t&test&other&people’s&codeYou$don't$know$how$it's$supposed$to$behave
![Page 69: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/69.jpg)
Don’t&test&how&you&talk&to&other&people’s&code
You$don't$know$how$it's$supposed$to$respond
![Page 70: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/70.jpg)
Pu#ng&it&all&together
• Use%TDD%to%drive&development
• Use%TDD%to%replace&exis1ng&prac1ces,%not%as%a%new%extra%task%
![Page 71: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/71.jpg)
Pu#ng&it&all&together
Don’t&ignore&tests&that&suck,&improve&them:&
• Is$the$test$too$!ed$to$implementa!on?
• Does$the$design$of$the$code$need$to$improve?$
• Are$you$tes!ng$across$domain$boundaries?$
![Page 72: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/72.jpg)
Image&credits
• Human&Evolu+on"by"Tkgd2007h-p://bit.ly/1DdLvy1"(CC"BY=SA"3.0)
• Oops"by"Steve"and"Sara"Emry"h-ps://flic.kr/p/9Z1EEd"(CC"BY=NC=SA"2.0)
• Blueprints&for&Willborough&Home"by"Brian"Tobin"h-ps://flic.kr/p/7MP9RU"(CC"BY=NC=ND"2.0)
• Border"by"Giulia"van"Pelt"h-ps://flic.kr/p/9YT1c5"(CC"BY=NC=ND"2.0)
![Page 73: Why Your Test Suite Sucks](https://reader033.vdocuments.mx/reader033/viewer/2022052509/55a5242f1a28ab50018b4602/html5/thumbnails/73.jpg)
Thank&you!
h"ps://joind.in/13393h"ps://github.com/ciaranmcnultyh"p://www.slideshare.net/CiaranMcNulty@ciaranmcnulty