SlideShare a Scribd company logo
1 of 95
Getting Started with Test-
Driven Development
Scott Keck-Warren
@scottKeckWarren
PHPdevelopers.tv
Scott Keck-Warren
• Director of Technology at
WeCare Connect
• Host at
http://PHPdevelopers.tv
What Are You Going to Learn?
1. What Is Test-Driven Development
2. Why You Should Be Using Test-
Driven Development
3. How To Do Test-Driven Development
4. How To Get Started On Your Project
5. Common Gotchas
What is Test-Driven
Development?
What is Test-Driven
Development?
• Abbreviated TDD
• Test-first software development process
• Create suite of automated tests
• Short cycles of 5 phases
• < Minute
What is Test-Driven
Development?
• “Rediscovered” by Kent Beck
• “Test Driven Development: By
Example”
What is Test-Driven
Development?
• “Best” for greenfield
• Works well for brownfield
• Check out “Working Effectively
with Legacy Code” by Michael
Feathers for brownfield
Why You Should Be
Using TDD
TDD Gives Us Confidence
to Make Changes
Why You Should Be Using
TDD
• 4PM on before long weekend
• Boss asks for “little” change
• What do you do?
Photo by Yan Krukov from Pexels
Why You Should Be Using
TDD
• TDD gives us confidence
• Automated Tests Pass
• Push to Production
• Go Have Fun
Photo by Min An from Pexels
How Do You Use Test
Driven Development?
How Do You Use Test Driven
Development?
• 5 Phases
• Each < 10 lines of code modified
#1. Add A New Test
• Write a failing test
• Should be succinct
• Goal: how does a single
change affect our code
# 2. Run All Tests and See
The New One Fail
• Make sure the
new test fails
# 2. Run All Tests and See
The New One Fail
• Run All Tests?
#3. Make A Little Change
• Smallest amount of
change to get test to pass
• Doesn’t need to be perfect
• “Perfect” comes later
#4. Run All Tests and See
Them All Succeed
• Make sure all the tests
succeed
• If not jump back to phase
#3
#5. Refactor to Remove
Duplication
• Refactor: Restructure so
as to improve operation
without altering
functionality.
#5. Refactor to Remove
Duplication
• Are the
method/class/variables
easy to read?
• Do they express
intent?
• Will future me
understand them?
#5. Refactor to Remove
Duplication
• Can we move logic into
the superclass?
• Can we move logic into
a shared trait?
Repeat
Red, Green, Refactor
• 3 Phase Version
• Red -> Failing
• Green -> Passing
• Refactor
PHPUnit
PHPUnit
• Test Framework
• De Facto Testing Framework
for PHP
• Written by Sebastian
Bergmann
• All tests are written in PHP
Photo by RF._.studio from Pexels
PHPUnit
• Organization is easy
• All test files inside a tests
folder
• A test is a PHP class method
Photo by Anete Lusina from Pexels
PHPUnit
public function testAStringCausesIsEmptyToReturnFalse(): void
{
$item = new SuperString('Test Data');
$this->assertFalse($item->isEmpty());
}
PHPUnit
public function testAStringCausesIsEmptyToReturnFalse(): void
{
$item = new SuperString('Test Data');
$this->assertFalse($item->isEmpty());
}
/**
* @test
*/
public function aStringCausesIsEmptyToReturnFalse(): void
{
$item = new SuperString('Test Data');
PHPUnit
•Each test contains one or more asserts
$this->assertFalse($value);
$this->assertEquals($expectedValue, $value);
$this->assertGreaterThan($number, $value);
PHPUnit
• A PHP class groups similar tests together
• Ideally a test class for each application class with logic
• A test class for common initial conditions
• Each class ends with “Test”
PHPUnit
• Installed using composer
• Can install globally or per project
• Per project is the way to go
PHPUnit
• Command line tool
• Super powerful
• phpunit
• phpunit tests/Unit/SuperStringTest.php
• phpunit —filter User
• PHPUnit + IDE = More efficient
PHPUnit
• From the command line:
• ./vendor/bin/phpunit tests/Unit/SuperStringTest.php
SuperString
SuperString
class SuperString
{
private $string = null;
public function __construct(string $string)
{
$this->string = $string;
}
}
isEmpty()
isEmpty() - Add Test
• Create tests/Unit/SuperStringTest.php
isEmpty() - Add Test
<?php
isEmpty() - Add Test
<?php
namespace TestsUnit;
class SuperStringTest
{
isEmpty() - Add Test
<?php
namespace TestsUnit;
use PHPUnitFrameworkTestCase;
class SuperStringTest extends TestCase
{
isEmpty() - Add Test
<?php
namespace TestsUnit;
use PHPUnitFrameworkTestCase;
class SuperStringTest extends TestCase
{
public function testBlankStringCausesIsEmptyToReturnTrue(): void
{
isEmpty() - Add Test
<?php
namespace TestsUnit;
use AppSuperString;
use PHPUnitFrameworkTestCase;
class SuperStringTest extends TestCase
{
public function testBlankStringCausesIsEmptyToReturnTrue(): void
{
$item = new SuperString('');
isEmpty() - Add Test
<?php
namespace TestsUnit;
use AppSuperString;
use PHPUnitFrameworkTestCase;
class SuperStringTest extends TestCase
{
public function testBlankStringCausesIsEmptyToReturnTrue(): void
{
$item = new SuperString('');
isEmpty() - Run Tests
isEmpty() - Run Tests
isEmpty() - Make A Change
// in SuperString
public function isEmpty(): bool
{
return true;
}
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
isEmpty() - Make A Change
// in SuperString
public function isEmpty(): bool
{
return true;
}
isEmpty() - Run Tests
isEmpty() - Refactor
!isEmpty()
!isEmpty() - Add Test
// in SuperStringTest
public function testBlankStringCausesIsEmptyToReturnTrue(): void
{
$item = new SuperString('');
$this->assertTrue($item->isEmpty());
}
!isEmpty() - Add Test
// in SuperStringTest
public function testBlankStringCausesIsEmptyToReturnTrue(): void
{
$item = new SuperString('');
$this->assertTrue($item->isEmpty());
}
public function testAStringCausesIsEmptyToReturnFalse(): void
{
$item = new SuperString('Test Data');
$this->assertFalse($item->isEmpty());
}
!isEmpty() - Run Tests
!isEmpty() - Make a Change
// in SuperString
public function isEmpty(): bool
{
return true;
}
!isEmpty() - Make a Change
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
!isEmpty() - Run Tests
!isEmpty() - Refactor
isNotEmpty()
isNotEmpty() - Add Test
// in SuperStringTest
public function testBlankStringCausesIsNotEmptyToReturnFalse(): void
{
$item = new SuperString('');
$this->assertFalse($item->isNotEmpty());
}
isNotEmpty() - Run Tests
isNotEmpty() - Make A
Change
// in SuperString
public function isNotEmpty(): bool
{
return mb_strlen($this->string) != 0;
}
isNotEmpty() - Run Tests
isNotEmpty() -
Refactor
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
public function isNotEmpty(): bool
{
return mb_strlen($this->string) != 0;
}
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
public function isNotEmpty(): bool
{
return mb_strlen($this->string) != 0;
}
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
public function isNotEmpty(): bool
{
return mb_strlen($this->string) != 0;
}
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return $this->length() == 0;
}
public function isNotEmpty(): bool
{
return $this->length() != 0;
}
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
public function isNotEmpty(): bool
{
return mb_strlen($this->string) != 0;
}
isNotEmpty() - Refactor
// in SuperString
public function isEmpty(): bool
{
return mb_strlen($this->string) == 0;
}
public function isNotEmpty(): bool
{
return !$this->isEmpty();
}
isNotEmpty() - Refactor
Integration Tests
Integration Tests
Unit
Single Class
Integration Tests
Unit ?
Single Class Multiple Classes
Integration Tests
Unit Integration
Single Class Multiple Classes
Integration Tests
Unit Integration
Single Class Multiple Classes
Faster Slower
Integration Tests
Unit Integration
Single Class Multiple Classes
Faster Slower
Targeted Broad
Integration Tests
public function testCanAccessCategoriesRoute(): void
{
$response = $this->get('/categories');
$response->assertOk();
}
How To Get Started
On Your Project
Getting Started By Yourself
1. Just start doing it
2. Talk to manager first
Photo by Andrea Piacquadio from Pexels
Getting Started With
Your Team
Getting Started With Your
Team
1. Get management buy in
2. Get everyone using TDD
Photo by Fauxels from Pexels
Getting Started With Your
Team
1. Book recommendations
1. “Test Driven
Development: By
Example” by Kent Beck
2. “Working Effectively with
Legacy Code” by Michael
Feathers
Photo by Liza Summer from Pexels
Getting Started With Your
Team
1. Basic Training on TDD with
your code base
2. Code Reviews with TDD as
the keystone
3. Pair Programming
Photo by Christina Morillo from Pexels
Common Gotchas
Neglecting to Run
Tests
Creating Too Many
Tests At Once
Creating Large Tests
Creating Trivial Tests
Review
Review
• TDD: test-first software development process
• Five short phases
• Each of the phases happens very quickly
• Don’t neglect to refactor
Review
Review
• Use PHPUnit
• Write clear and concise tests
Review
• It may seem complicated/confusing but just start
Review
• Avoid
• Neglecting to Run Tests
• Creating Too Many Tests At Once
• Creating Large Tests
• Creating Trivial Tests
Questions & More
Information
@scottKeckWarren
http://PHPdevelopers.tv
Image From @pixabay

More Related Content

What's hot

Das Frontend richtig Testen – mit Jest @Developer Week 2018
Das Frontend richtig Testen – mit Jest @Developer Week 2018Das Frontend richtig Testen – mit Jest @Developer Week 2018
Das Frontend richtig Testen – mit Jest @Developer Week 2018Holger Grosse-Plankermann
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projectsVincent Massol
 
Interpreter RPG to Java
Interpreter RPG to JavaInterpreter RPG to Java
Interpreter RPG to Javafarerobe
 
Droidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineDroidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineJavier de Pedro López
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails AppsRabble .
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slidesericholscher
 
Principles and patterns for test driven development
Principles and patterns for test driven developmentPrinciples and patterns for test driven development
Principles and patterns for test driven developmentStephen Fuqua
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkArulalan T
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best PracticesDavid Wheeler
 
Unit Testing RPG with JUnit
Unit Testing RPG with JUnitUnit Testing RPG with JUnit
Unit Testing RPG with JUnitGreg.Helton
 
RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG Greg.Helton
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleNoam Kfir
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentMark Niebergall
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummiesHarry Potter
 
How to test models using php unit testing framework?
How to test models using php unit testing framework?How to test models using php unit testing framework?
How to test models using php unit testing framework?satejsahu
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for OracleJacek Gebal
 

What's hot (19)

Spring hibernate jsf_primefaces_intergration
Spring hibernate jsf_primefaces_intergrationSpring hibernate jsf_primefaces_intergration
Spring hibernate jsf_primefaces_intergration
 
Das Frontend richtig Testen – mit Jest @Developer Week 2018
Das Frontend richtig Testen – mit Jest @Developer Week 2018Das Frontend richtig Testen – mit Jest @Developer Week 2018
Das Frontend richtig Testen – mit Jest @Developer Week 2018
 
New types of tests for Java projects
New types of tests for Java projectsNew types of tests for Java projects
New types of tests for Java projects
 
Interpreter RPG to Java
Interpreter RPG to JavaInterpreter RPG to Java
Interpreter RPG to Java
 
Droidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineDroidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offline
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under Test
 
Testing Legacy Rails Apps
Testing Legacy Rails AppsTesting Legacy Rails Apps
Testing Legacy Rails Apps
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slides
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
Principles and patterns for test driven development
Principles and patterns for test driven developmentPrinciples and patterns for test driven development
Principles and patterns for test driven development
 
Testing in-python-and-pytest-framework
Testing in-python-and-pytest-frameworkTesting in-python-and-pytest-framework
Testing in-python-and-pytest-framework
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best Practices
 
Unit Testing RPG with JUnit
Unit Testing RPG with JUnitUnit Testing RPG with JUnit
Unit Testing RPG with JUnit
 
RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black Hole
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 
How to test models using php unit testing framework?
How to test models using php unit testing framework?How to test models using php unit testing framework?
How to test models using php unit testing framework?
 
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracleprohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
prohuddle-utPLSQL v3 - Ultimate unit testing framework for Oracle
 

Similar to Getting Started with Test-Driven Development (TDD

Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Mark Niebergall
 
Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Scott Keck-Warren
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1Yi-Huan Chan
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Mark Niebergall
 
Automated Unit Testing
Automated Unit TestingAutomated Unit Testing
Automated Unit TestingMike Lively
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)Jen Wong
 
Test Driven Development with PHPUnit
Test Driven Development with PHPUnitTest Driven Development with PHPUnit
Test Driven Development with PHPUnitMindfire Solutions
 
Getting Started with Test-Driven Development at PHPtek 2023
Getting Started with Test-Driven Development at PHPtek 2023Getting Started with Test-Driven Development at PHPtek 2023
Getting Started with Test-Driven Development at PHPtek 2023Scott Keck-Warren
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFXHendrik Ebbers
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticLB Denker
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentationThanh Robi
 
Unit testing php-unit - phing - selenium_v2
Unit testing   php-unit - phing - selenium_v2Unit testing   php-unit - phing - selenium_v2
Unit testing php-unit - phing - selenium_v2Tricode (part of Dept)
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2Yi-Huan Chan
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Chris Weldon
 
Modernizing Legacy Applications in PHP, por Paul Jones
Modernizing Legacy Applications in PHP, por Paul JonesModernizing Legacy Applications in PHP, por Paul Jones
Modernizing Legacy Applications in PHP, por Paul JonesiMasters
 
Fighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnitFighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnitJames Fuller
 
(Unit )-Testing for Joomla
(Unit )-Testing for Joomla(Unit )-Testing for Joomla
(Unit )-Testing for JoomlaDavid Jardin
 

Similar to Getting Started with Test-Driven Development (TDD (20)

Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022Leveling Up With Unit Testing - LonghornPHP 2022
Leveling Up With Unit Testing - LonghornPHP 2022
 
Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023
 
Automated Unit Testing
Automated Unit TestingAutomated Unit Testing
Automated Unit Testing
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
 
Test Driven Development with PHPUnit
Test Driven Development with PHPUnitTest Driven Development with PHPUnit
Test Driven Development with PHPUnit
 
Getting Started with Test-Driven Development at PHPtek 2023
Getting Started with Test-Driven Development at PHPtek 2023Getting Started with Test-Driven Development at PHPtek 2023
Getting Started with Test-Driven Development at PHPtek 2023
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Unit testing php-unit - phing - selenium_v2
Unit testing   php-unit - phing - selenium_v2Unit testing   php-unit - phing - selenium_v2
Unit testing php-unit - phing - selenium_v2
 
Unit testing
Unit testingUnit testing
Unit testing
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010
 
Modernizing Legacy Applications in PHP, por Paul Jones
Modernizing Legacy Applications in PHP, por Paul JonesModernizing Legacy Applications in PHP, por Paul Jones
Modernizing Legacy Applications in PHP, por Paul Jones
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 
Fighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnitFighting Fear-Driven-Development With PHPUnit
Fighting Fear-Driven-Development With PHPUnit
 
(Unit )-Testing for Joomla
(Unit )-Testing for Joomla(Unit )-Testing for Joomla
(Unit )-Testing for Joomla
 
Unit testing
Unit testingUnit testing
Unit testing
 

More from Scott Keck-Warren

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Scott Keck-Warren
 
Static Code Analysis PHP[tek] 2023
Static Code Analysis PHP[tek] 2023Static Code Analysis PHP[tek] 2023
Static Code Analysis PHP[tek] 2023Scott Keck-Warren
 
Developing a Culture of Quality Code at Givelify (Tech Talk)
Developing a Culture of Quality Code at Givelify (Tech Talk)Developing a Culture of Quality Code at Givelify (Tech Talk)
Developing a Culture of Quality Code at Givelify (Tech Talk)Scott Keck-Warren
 
Developing a Culture of Quality Code (Midwest PHP 2020)
Developing a Culture of Quality Code (Midwest PHP 2020)Developing a Culture of Quality Code (Midwest PHP 2020)
Developing a Culture of Quality Code (Midwest PHP 2020)Scott Keck-Warren
 

More from Scott Keck-Warren (6)

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023Getting Started with Test-Driven Development at Longhorn PHP 2023
Getting Started with Test-Driven Development at Longhorn PHP 2023
 
Static Code Analysis PHP[tek] 2023
Static Code Analysis PHP[tek] 2023Static Code Analysis PHP[tek] 2023
Static Code Analysis PHP[tek] 2023
 
Developing a Culture of Quality Code at Givelify (Tech Talk)
Developing a Culture of Quality Code at Givelify (Tech Talk)Developing a Culture of Quality Code at Givelify (Tech Talk)
Developing a Culture of Quality Code at Givelify (Tech Talk)
 
Developing a Culture of Quality Code (Midwest PHP 2020)
Developing a Culture of Quality Code (Midwest PHP 2020)Developing a Culture of Quality Code (Midwest PHP 2020)
Developing a Culture of Quality Code (Midwest PHP 2020)
 

Recently uploaded

Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 

Recently uploaded (20)

Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 

Getting Started with Test-Driven Development (TDD

Editor's Notes

  1. Professional PHP Developer for 11 years // supervisor for 6 of those 11 Currently Director of Technology at WeCare Connect Survey solutions to improve employee and resident retention at skilled nursing facilities Use PHP for our backend Host of PHP Developers TV on YouTube Discuss topics helpful for PHP developers Can get to our channel using phpdevelopers.tv
  2. Could spend hours discussing automated testing with you all. It’s one of my favorite PHP adjacent topics but we only have 40 minutes. My goals are to always have you leave one of my sessions with something you can use the next day you’re going to work and how you can implement this with your team
  3. TDD is a test-first software development process that uses short development cycles to write very specific test cases and then modify our code so the tests pass. TDD consists of five phases that we will repeat as we modify our code. Each of the phases happens very quickly and we might go through all five phases in less than a minute.
  4. TDD was "rediscovered" by Kent Beck while working on the SmallTalk language and has been documented extensively in his book "Test Driven Development: By Example". The book is an excellent primer for working with TDD as it works through several examples of how to use TDD and also explains some techniques for improving code. One of few physical books I have
  5. While TDD works best for greenfield applications, it's a benefit to anyone working on a brownfield application as well. Brownfield applications tend to require a little more finesse to get them set up for automated testing so don't get discouraged if it's frustrating at first. “Working Effectively with Legacy Code” by Michael Feathers is a helpful book in this regard
  6. Let's say it's 4 PM before a long weekend and your boss comes to you and asks you to make a small change to your codebase to meet a client requirement. How confident are you that if you make the change you're not going to get a call on Sunday?
  7. Because TDD forces you to create tests, you'll have the confidence that when you make the change And the test pass you can push to production and know that your weekend isn't going to be interrupted with a new bug from your change.
  8. TDD consists of 5 phases Each phase should be small with, at most, ten new lines of code being modified. If we find ourselves doing more than that we're working on too large a change and we need to break it into smaller pieces.
  9. 1. Add a new test The first thing we're going to do is write a failing test. We'll use this failing test to help determine when we've achieved our expected functionality. It's important that the test is succinct and that it's looking at how a **single** change will affect our code.
  10. 2. Run all tests and see the new one fail In this step, we're going to run the test to make sure our test fails before we move on to the next phase. It's very easy to write a test that doesn't fail so we **always** run our test to verify it's failing before moving to the next phase. If it’s not failing we don’t know if our change actually did anything
  11. As a small aside, the wording for this phase says "run all the tests" but as our test suite (a collection of tests) grows this will take an unproductively large amount of time. Current code base takes 25 minutes to run whole suite. We'll want to short circuit this and only run the test file or just our new test. Many IDEs can run a single file or even a single test and it's worth spending time figuring out how to get this working as it will make us more productive. Some are built in like PHP Storm but some require extensions like VS Code.
  12. 3. Make a little change Now our goal is to change the smallest amount of code possible to get that test to pass. We don't want to change any more than is necessary because that extra bit of change wasn't made using TDD and is potentially not tested. We don't need perfect code in this phase we just need code that makes the test pass. It's very easy to get caught up in making sure everything is perfect but that's not the goal here. Perfect comes later.
  13. 4. Run all tests and see them all succeed Now that we've made our change we can run our test and see that it passes new test and any other tests. If it doesn't then we just jump back to phase #3 and keep making small changes until it does.
  14. 5. Refactor to remove duplication Now that we have our tests passing we're going to take a break and inspect both our test code and our code under test to see where we can make changes so it's easier for future developers to read, understand, and maintain. This is called Refactoring and it’s: restructure code so as to improve operation without altering functionality. We're using TDD so changes are painless because we can quickly run our unit tests again to make sure we didn't make a mistake.
  15. Other things we should look for as we're doing this process: Are the method/class/variables easy to read? Do they express intent? -> We can name a function getTheValue but it doesn’t explain what fnt does and will cause confusion Will future me understand them? A week? A Year? If I can’t how can anyone else who wasn’t in my head space
  16. Other things we should look for as we're doing this process: Can we move logic into the superclass so other classes can use it? Can we move logic into a shared trait? Favorite from of reuse is when we can apply same function to multiple trees of inheritance
  17. Now that we've completed a single TDD cycle we can start back at the beginning with a new test.
  18. If you google TDD There’s also a three phase version Called Red, green, refactor Red and green come from colored messages we get from our testing tool Basically group phases 1 and 2 and 3 and 4. I like 5 phases for demos because it gives explicit steps
  19. We’re going to work through some example TDD cycles. Our examples uses PHPUnit to run our tests so we going to do a Quick intro on PHPUnit
  20. In case you don’t know Testing Framework De Facto Testing Framework for PHP Written by Sebastian Bergmann All tests are written in PHP so we don’t need to learn anything new
  21. Organization is easy All test files are placed inside a tests folder at the root of the project A test is a PHP class method
  22. Each test function starts with “test” or …
  23. Each test function starts with “test” or uses the @test annotation This is a personal preference thing. I learned PHPUnit before annoation option so I default to prefixing tests with test. Also uses less vertical space which helpful for presentations
  24. Each test function contains one or more asserts Asserts tell PHPUnit to compare an expected value to the value we got from our code $this->assertFalse($value); $this->assertEquals($expectedValue, $value); $this->assertGreaterThan($number, $value);
  25. A PHP class groups similar tests together Ideally a test class for each application class with logic. Don’t need tests for classes with no logic. A test class for common initial conditions Might have class for tests involving a standard user and another class for administrator users Each class ends with “Test” super important and PHPunit won’t “autoload” them.
  26. Installed using composer Can install globally or per project Some people on the internet say to install globally but it’s not great Might have two projects that need different versions and won’t work with opposite version Per project is the way to go PHPUnit website even says not to even though it gives instructions
  27. Our examples today mostly command line Running using ./vendor/bin/phpunit tests/FileTest.php
  28. Let’s talk about our example
  29. One of the things I feel like PHP is missing is a string class Always end up using a string class library and it’s a good example of something easy to understand that isn’t a blog so we can discuss it easily. This is what the class looks like initially Taking a string and storing it inside itself and then we have to add methods to act on that string
  30. First thing check to see if a our string has no length
  31. 1. Add a new test Start from the beginning assuming no tests for SuperString First step is to create the test file Laravel places tests that operate on single classes in a unit folder Want to use that here so create tests/Unit/SuperStringTest.php
  32. Next fill in the file
  33. Create class Class name needs to match the file name -> new PHPunit doesn’t like mismatch
  34. Extends PHPUnit\Framework\TestCase . TestCase class gives us asserts and setup logic we need
  35. Create the test function. We’re going to name the function based on what we’re testing to it’s easier to understand when future us comes back to it.
  36. Create Our Initial Conditions
  37. Test our result from the function. Calling our isEmpty function and asserting it’s returning true Notice how small the actual test is. We're giving the test a very specific functionality to test and we're only asserting one thing. If we have more than one assert per test we run the risk of making it difficult to debug later when something breaks.
  38. 2. Run all tests and see the new one fail Now we'll run PHPUnit to see that we do indeed get a failing test.
  39. In this case, we haven't yet defined the method so we get an "undefined method" error. Red message -> in an error state like we saw in red/green/refactor
  40. 3. Make a little change To reiterate, our goal in this phase is to make the smallest change we can to allow our tests to pass. Two options here: add in the obvious implementation Obvious means is a few lines that we can’t possibility mess up the logic for This case just call to mb_strlen (click) Make the smallest possible change by returning true always. (click) It doesn't cover all the possible inputs but the goal in this step isn't to cover all the inputs it's to get our test to pass. We'll cover more inputs later.
  41. We’re going to want to show another cycle of TDD so we’re going to just return true
  42. 4. Run all tests and see them all succeed Now we run our test and verify that our test passes. Notice green from red/green/refactor
  43. 5. Refactor to remove duplication Our code currently doesn't contain any duplication but it's important not to get lazy and skip this step.
  44. Our simple implementation of `isEmpty()` is going to be wrong most of the time because of its current implementation. Now we need to add another test that checks for other cases where the string isn't empty. As a general rule, it's a good idea to have tests for normal input, the extremes of inputs (very large or very small), and spots where we can think of oddities happening obviously very domain specific We’re going to check for a case where the string isn’t empty to add an addition testing point
  45. Add a new test What we have currently
  46. Add in the opposite
  47. 2. Run all tests and see the new one fail This time we get a failure assertion that true is false
  48. 3. Make a little change Look at our original code Could change to return false but that would cause other tests to fail
  49. Back to the obvious implementation we had before
  50. 4. Run all tests and see them all succeed
  51. 5. Refactor to remove duplication Again due to the simple nature of our example there isn't any duplication in our code at this point.
  52. Starting to get the hang of this Adding a test now to check for a string that isn’t empty. Could do !isEmpty() but isNotEmpty is actually easier for us to process as programmers so it’s nice to have
  53. 1. Add a new test Again small Again written so we know what’s going on quickly
  54. 2. Run all tests and see the new one fail
  55. 3. Make a little change In this case instead of returning `false` and then creating another test so we can write the functionality by going through all the TDD steps, we're just going to trust ourselves and create the obvious implementation of the `isNotEmpty()` function.
  56. 4. Run all tests and see them all succeed Oh good we didn’t make any mistakes
  57. 5. Refactor to remove duplication Now here is where it gets interesting. The last two times we've hit this step we haven't had anything to do but now look at our `isEmpty()` and `isNotEmpty()` functions.
  58. We can see some minor duplication in the two calls to `mb_strlen($this->string)`. Now we just need to determine how we want to resolve this. 2 options Option 1 is to extract that duplication into a new function.
  59. Extracting a new function is favorite refactor because it makes the code more readable and because we'll most likely need the same logic again.
  60. Now The replace the calls with the new function
  61. The second solution is to realize that `isNotEmpty()` returns the boolean opposite of `isEmpty()` and just use it
  62. If I hadn’t been working through this example just to get to this who cares example I think I would have done this automatically. The first option gives us the best flexibility for future expansion but second less code. Always a fond of less code
  63. Finally, we need to run our tests again to verify that no accidents crept into our code as we made these changes.
  64. In our example, we worked out an example of tests where we only tested a single class. This is know as a unit test.
  65. Unit tests are exceptionally good for testing each piece of our application but what if we want to test how all of the units work together? For example, we may want to test a request against our API endpoints so we can make sure they meet our specs.
  66. Integration tests allow us to do this. But they come with a dark side
  67. Integration tests tend to be slower because we’ll be initializing 100s of classes and might be interacting with a database which is generally the slowest part of the application stack. Really going to depend on your application but Unit test might take tenth of a second and an integration might take a second. So it’s not a tenth of second vs 50 seconds In the long run they add up but it’s so easy to throw additional resources at our testing servers that it can be worth it.
  68. Because the integration tests are testing several components at once it may not be quickly apparent what caused the test to fail. For example, our integration test might hit a dashboard endpoint and one of the components fails because of a poorly written query. The result might just be that an error occurred and not tell us what the error was. Personally feel they’re worth every bit of time spent on them. Every integration test that fails before it get’s to a customer is one less bug ticket. I use TDD to develop these tests and it can be a dream.
  69. Several PHP frameworks provide facilities that allow tests to simulate an entire web request and validate the output. This is a laravel example, request /categories page using an HTTP get request Check to make sure we get a 200 based response code and not a redirect or error message. I’m a fan of doing integration tests on any endpoint where we’re creating or updating data because they tend to be hard to manually test.
  70. Now that you understand the basics of TDD you can start to use it in our daily work. It’s one of those need to start using it to understand it. Start doing it. Spent years not fully understanding the benefit and it wasn’t until I committed myself that it really clicked. Check with manager first - don’t want to get your fired If we're working by ourselves this can be an easy process because we can easily develop and maintain the test suite.
  71. Using TDD with your team can be more of a challenge
  72. As we're getting started with TDD in our teams we must have management support. Without the organization believing that TDD will help improve the application it might look to the leaders in your organization that the time spent writing tests has been wasted when it could have been spent adding new features. I argue it’s always time well spent We'll also want to make sure everyone on our team is coding using TDD. By having everyone invested in using TDD we'll quickly build up a huge test suite and give everyone the confidence to make changes to other people's code. It also allows everyone to feel ownership of the tests and keep up with the maintenance of them instead of it falling on the shoulders of a few people.
  73. Recommend doing a group read of the two books on the screen. I’ve done this a couple times with different groups of developers. It’s helpful to setup a schedule depending and then have a quick discussion about what people found interesting/hard to understand about the assigned reading. This can be super quick or more slow. I’ve had a new developer read both books in two weeks and I’ve had a team read them over two quarters. It’s all going to depend on your needs.
  74. There are several actions that our team can take to get everyone invested in TDD. The first is to have training on the basics of TDD and how to get started using our codebase. Pick two people to get TDD working well in your codebase and then have a group training to show people how to do it. The second is to start having code reviews and make sure every code review starts with answering the question “Is this change driven by a test”. If not, the review stops until it is. The final thing is to have developers that are more consistently using TDD pair program with the developers that aren’t. This will allow for more hands-on experience for the less experienced engineer.
  75. As the suite of tests grows it starts to become part of the maintenance overhead of our project. To that end, we'll need to make sure we prevent running into some of these common gotchas to make our lives easier.
  76. As the amount of time it takes to run the full suite of tests increases the likelihood that we don't run the whole suite also increases. Because of this, it's very easy to get to a point where so many of the tests are broken that nobody feels confident in them. It's a best practice to set up a Continuous Integration server like Jenkins, TravisCI, or CircleCI to automatically run all the tests and report back any errors. We can even set them up to prevent new code from reaching our servers if any of the tests fail. Ideally, all of the automated tests would be run every time a new commit is created but we’ve really commonly combined them into a PR so
  77. When we're setting up our tests it's very easy for us to create `testBlankStringCausesIsEmptyToReturnTrue()` and then immediately create `testValidStringCausesIsEmptyToReturnFalse()` without making sure the former passes before creating the later. This will make it harder for us to get back to the state where all of the tests pass and will make it harder for us to progress because we're trying to solve two problems at the same time. It's always best to write a single test and get it passing before moving on to another.
  78. Individual tests should aspire to only have a single assert function in each test. There's nothing in PHPUnit that prevents us from setting up a single test with 100 assertions but that is an indication that the test is doing too much. We won't be able to quickly look at the test and see what we've done or how to fix it because the test is so large. Small tests allow us to quickly determine why something has broken and quickly adjust to get it passing again.
  79. Finally One of the things new practitioners of TDD tend to do is to create tests for trivial functionality. For example, we'll see tests that are set up to test new getters and setters. These tests tend to not be beneficial to our test suite because trivial functions don't change frequently and because the trivial code is usually being run as part of another test.
  80. 1. Add a new test 2. Run all tests and see the new one fail 3. Make a little change 4. Run all tests and see them all succeed 5. Refactor to remove duplication