SlideShare a Scribd company logo
Test in Action – Week 3
      Stub / Mock
      Hubert Chan
Back to Basics
• Wikipedia said unit testing is
  – A software verification and validation method in
    which a programmer tests if individual units of
    source code are fit for use.
Dependency in the Test
• System Under Test (SUT) Dependency
  – SUT need another module to perform its task
     • Handler need a $dbmodel to perform query
     • $handler = new Handler($dbmodel);
Real Object is Hard to Test
• Real object
  – Supplies non-deterministic results
     • (e.g. the current temperature)
  – Difficult to create or reproduce (e.g. network fail)
  – Slow (e.g. database)
  – Does not yet exist or may change behavior
Substitute Dependency
• Using Fake
  – Fake is anything not real
• Fake techniques
  – Mock object
  – Stub object
  – Fake object
Stub Objects
• Stub Objects
  – Stubs provide canned answers to calls made
    during the test
  – Usually not responding at all to anything outside
    what's programmed in for the test
Fake Objects
• Fake Objects
  – Fake objects have working implementations
  – Usually take some shortcut, which makes them
    not suitable for production.
  – Example
     • An in-memory file system
     • An in-memory registry manager
Example: AlertSystem
Example: AlertSystem
• Component Overview
  – AlertSystem
     • Send notification to the targets, such as e-mail or SMS
       notifier.
  – NotifierInterface instance
     • Send actually notification to the target
  – NotifierTargetProviderInterface instance
     • Provide a target array to send notification
AlertSystem Test
• Dependency Analysis
  – Collaboration Classes
     • NotifierInterface
     • NotifierTargetProviderInterface

• Tests should
  – Only focus on AlertSystem
  – Fake the dependency
Make a Fake?
• FileNotifyTargetProvider
class FileNotifyTargetProvider
    implements NotifyTargetProviderInterface {

    function __construct($filename) {
        $this->_filename = $filename;
    }

    public function get_targets() {
        $targets = array();
        $handle = @fopen($this->_filename, "r");

        while (($target = fgets($handle)) !== FALSE) {
            $targets[] = $target;
        }
        return $targets;
    }
}
Make a Stub?
• StubNotifier
class StubNotifier implements NotifierInterface {
    public function notify($target, $content) {
    }
}
Example: Test Code
• Test Code
class AlertSystemTest extends PHPUnit_Framework_TestCase {
    public function test_sendNotify_FakeNStub_NoException() {
        $target_file = __DIR__ . '/data/targets.txt';

        $notifier = new StubNotifier();
        $provider = new FileNotifyTargetProvider($target_file);

        $alert_system = new AlertSystem(
            $notifier,
            $provider
        );
        $alert_system->send_notify('Alert!!');
    }
}
Manual Fake or Stub
• Pros
  – Fake or stub can be used as library
  – Shared implementation
• Cons
  – Different scenarios need different implementation
  – Testing class explosion
Manual Stub or Fake
• Cons
  – Need extra efforts/logics for behaviors
     • Setting return value
     • Setting thrown exception
  – Hard to validate
     • Calling sequence of functions
     • Passing arguments for functions
     • The method should be called
Test Doubles
• Using manual stub and mock
  – Is $notifier->notify() be called?
  – Does the target of $notifier->notify equal to
    expect target?
  – Does the content of $notifier->notify equal
    to expect target?
Mock objects
• Mock Objects
  – Mocks are objects pre-programmed with
    expectations, which form a specification of the
    calls they are expected to receive.
Mock Object Example
• Mock Object Example
 public function test_sendNotify_Mock_NoException() {

     $notify_content = 'fake_content';
     $mock_notifier = $this->getMock('NotifierInterface');
     $mock_notifier->expects($this->once())
                   ->method('notify')
                   ->with($this->anything(),
                          $this->equalTo($notify_content));

     $alert_system = new AlertSystem(
       $mock_notifier,
       $stub_provider
     );
     $alert_system->send_notify('Alert!!');
 }
Mock Object Example
• Mock Object Verification
  – $notifier->notify is called only once
  – $notifier->notify 1st parameter can be
    anything
  – $notifier->notify 2nd parameter should be
    equal to $notify_content
Using PHPUnit Stub
• Return Value
public function test_sendNotify_Mock_NoException() {

    $stub_provider = $this->getMock('NotifyTargetProviderInterface');
    $targets = array('hubert');
    $stub_provider->expects($this->any())
                  ->method('get_targets')
                  ->will($this->returnValue($targets));

    $alert_system = new AlertSystem(
      $mock_notifier,
      $stub_provider
    );
    $alert_system->send_notify('Alert!!');
}
Using PHPUnit Stub
• Return one of the arguments
public function testReturnArgumentStub() {
  // Create a stub for the SomeClass class.
  $stub = $this->getMock('SomeClass');

    // Configure the stub.
    $stub->expects($this->any())
         ->method('doSomething')
         ->will($this->returnArgument(0));

    // $stub->doSomething('foo') returns 'foo'
    $this->assertEquals('foo', $stub->doSomething('foo'));

    // $stub->doSomething('bar') returns 'bar'
    $this->assertEquals('bar', $stub->doSomething('bar'));
}
Using PHPUnit Stub
• Return a value from a callback
     – Useful for “out” parameter
public function testReturnCallbackStub() {
  // Create a stub for the SomeClass class.
  $stub = $this->getMock('SomeClass');

    // Configure the stub.
    $stub->expects($this->any())
         ->method('doSomething')
         ->will($this->returnCallback('str_rot13'));

    // $stub->doSomething($argument) returns str_rot13($argument)
    $this->assertEquals('fbzrguvat', $stub->doSomething('something'));
}
PHPUnit Stub
• Throw Exception
public function testThrowExceptionStub() {
  // Create a stub for the SomeClass class.
  $stub = $this->getMock('SomeClass');

    // Configure the stub.
    $stub->expects($this->any())
         ->method('doSomething')
         ->will($this->throwException(new Exception));

    // $stub->doSomething() throws Exception
    $stub->doSomething();
}
Misconception About Mocks
• Mocks are just Stubs
  – Mock is behavior verification
     • Is the function called?
     • Is the parameter passed correctly?
  – Stub is used for state verification
  – References
     • Mocks Aren’t Stubs
        – http://martinfowler.com/articles/mocksArentStubs.html
Is it HARD to use stub/mock?
• Untestable code
  – Make Your Own Dependencies
  – Heavy Duty Constructors
  – Depend on Concrete Classes
  – Use Statics
  – Using Singleton Everywhere
  – Look for Everything You Need
Dependency Injection
• Without dependency injection
  – Use “new” operator inside your class
  – Make mock object injection difficult
• Dependency Injection
  – Inject dependencies through injectors
  – Injection method
     • Constructor
     • Setter
     • Dependency Injection Framework
AlertSystem again
• AlertSystem (Hard to Test)
     – Concrete classes
     – Make Your Own Dependencies
 class AlertSystem {

     public function send_notify($content) {
       $target_provider = new FileNotifyTargetProvider('data.txt');
       $notifier = new EmailNotifier('user', 'pass', $port);

         $notify_targets = $target_provider->get_targets();
         foreach ($notify_targets as $target) {
           $notifier->notify($target, $content);
         }
     }
 }
AlertSystem constructor injection
• Constructor Injection
class AlertSystem {

     protected $_notifier;
     protected $_target_provider;

     function __construct (
         NotifierInterface $notifier,
         NotifyTargetProviderInterface $provider
     ) {
         $this->_notifier = $notifier;
         $this->_target_provider = $provider;
     }

     public function send_notify($content) {
         $notify_targets = $this->_target_provider->get_targets();
         foreach ($notify_targets as $target) {
             $this->_notifier->notify($target, $content);
         }
     }
}
Not only for testing
• Single Responsibility Principle
  – Should alert system holds notifier and data
    provider logic?
  – Ex. Should the class read registry directly?
• Dependency Inversion Principle
• Open Close Principle
The Law of Demeter
• Definition
  – Each unit should have only limited knowledge
    about other units: only units "closely" related to
    the current unit.
  – Each unit should only talk to its friends; don't talk
    to strangers.
  – Only talk to your immediate friends.
Violation of the Law
• How do you test for?
  – Mock for mock object, for another mock object
  – Like Looking for a Needle in the Haystack
  class Monitor {
    SparkPlug sparkPlug;
    Monitor(Context context) {
      this.sparkPlug = context.
        getCar().getEngine().
        getPiston().getSparkPlug();
    }
  }
Law of Demeter - Explicit
• Explicit
   – We should not need to know the details of
     collaborators
    class Mechanic {
      Engine engine;
      Mechanic(Engine engine) {
        this.engine = engine;
       }
    }
Guide – Write Testable Code
• Bad smell for non-testable Code
  – Constructor does real work
  – Digging into collaborators
  – Brittle Global State & Singletons
  – Class Does Too Much
• References
  – Guide – Write Testable Code
  – http://misko.hevery.com/attachments/Guide-
    Writing%20Testable%20Code.pdf
Conclusion
• Writing good unit tests is hard
• Good OO design brings good testability
• Using stub/mock from mocking framework
Q&A
PHPUnit Log File
• Junit Format
<testsuites>
  <testsuite name="AlertSystemTest"
file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTe
st.php" tests="2" assertions="0" failures="1" errors="0"
time="0.031119">
    <testcase name="test_sendNotify_FakeNStub_NoException"
class="AlertSystemTest"
file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTe
st.php" line="8" assertions="0" time="0.006881"/>
  </testsuite>
</testsuites>
PHPUnit Coverage
• PHPUnit Coverage
  – Need Xdebug
  – HTML format

More Related Content

PPTX
Test in action week 4
PPTX
Test in action week 2
PPTX
Test in action – week 1
PDF
Building Testable PHP Applications
PPTX
Unit Testng with PHP Unit - A Step by Step Training
KEY
Developer testing 101: Become a Testing Fanatic
PDF
Beginning PHPUnit
PPT
Phpunit testing
Test in action week 4
Test in action week 2
Test in action – week 1
Building Testable PHP Applications
Unit Testng with PHP Unit - A Step by Step Training
Developer testing 101: Become a Testing Fanatic
Beginning PHPUnit
Phpunit testing

What's hot (20)

PPT
Test driven development_for_php
PDF
SOLID Principles
PDF
PHP: 4 Design Patterns to Make Better Code
ODP
Interaction testing using mock objects
PDF
Unit Testing in SilverStripe
PDF
Unit testing PHP apps with PHPUnit
PPTX
PHP 7 Crash Course
PPT
Advanced PHPUnit Testing
ODP
Getting to Grips with SilverStripe Testing
PPTX
Java best practices
PDF
SilverStripe CMS JavaScript Refactoring
PPT
Mocking Dependencies in PHPUnit
PPTX
Unit Testing Presentation
PDF
Workshop quality assurance for php projects - ZendCon 2013
PDF
Typed Properties and more: What's coming in PHP 7.4?
PDF
Why Your Test Suite Sucks - PHPCon PL 2015
PDF
Advanced php testing in action
PDF
Unit testing with PHPUnit - there's life outside of TDD
PDF
UA testing with Selenium and PHPUnit - PFCongres 2013
ODP
Testing in Laravel
Test driven development_for_php
SOLID Principles
PHP: 4 Design Patterns to Make Better Code
Interaction testing using mock objects
Unit Testing in SilverStripe
Unit testing PHP apps with PHPUnit
PHP 7 Crash Course
Advanced PHPUnit Testing
Getting to Grips with SilverStripe Testing
Java best practices
SilverStripe CMS JavaScript Refactoring
Mocking Dependencies in PHPUnit
Unit Testing Presentation
Workshop quality assurance for php projects - ZendCon 2013
Typed Properties and more: What's coming in PHP 7.4?
Why Your Test Suite Sucks - PHPCon PL 2015
Advanced php testing in action
Unit testing with PHPUnit - there's life outside of TDD
UA testing with Selenium and PHPUnit - PFCongres 2013
Testing in Laravel
Ad

Viewers also liked (20)

PDF
PHPUnit Cheat Sheet
PDF
Legal analysis of source code
PPT
Susan and Marco\'s Trip to Obama 2009 Inauguration
PDF
Work History
PDF
USMEP Presentation
PPTX
Tiger shark powerpoint
PDF
IAサミットは誰のものか
PPTX
Banking on Mobile!
PPT
Theme 1 Eye of the Storm vocabulary
PPT
La bamba vocabulary_pp jan 2013
PPTX
Theme 2 mae jemison vocabulary flash cards mod 2013 pholt
PPTX
Lesson 13 vocab
KEY
T3dallas typoscript
PPTX
Proyek penciptaan dan digitalisasi konten
PDF
Geokit In Social Apps
PPT
Balanced Scorecard system: Strategy Map
ODP
Projducció i consum d'energia AitoooR
PPT
Theme 1 Volcanoes Vocabulary Natures Fury
DOC
Capstone Project EDAM5039
PPT
Rules Of Brand Fiction from @BettyDraper and @Roger_Sterling
PHPUnit Cheat Sheet
Legal analysis of source code
Susan and Marco\'s Trip to Obama 2009 Inauguration
Work History
USMEP Presentation
Tiger shark powerpoint
IAサミットは誰のものか
Banking on Mobile!
Theme 1 Eye of the Storm vocabulary
La bamba vocabulary_pp jan 2013
Theme 2 mae jemison vocabulary flash cards mod 2013 pholt
Lesson 13 vocab
T3dallas typoscript
Proyek penciptaan dan digitalisasi konten
Geokit In Social Apps
Balanced Scorecard system: Strategy Map
Projducció i consum d'energia AitoooR
Theme 1 Volcanoes Vocabulary Natures Fury
Capstone Project EDAM5039
Rules Of Brand Fiction from @BettyDraper and @Roger_Sterling
Ad

Similar to Test in action week 3 (20)

PPTX
Mocking
PPTX
Integration and Unit Testing in Java using Test Doubles like mocks and stubs
PPT
Mocking Dependencies in PHPUnit
PDF
CBDW2014 - MockBox, get ready to mock your socks off!
PPT
Unit testing
PPTX
Getting started-php unit
PDF
PHPunit and you
KEY
Php Unit With Zend Framework Zendcon09
PDF
Testing untestable code - phpday
PDF
Testing untestable code - ConFoo13
PDF
Introduction to Unit Testing with PHPUnit
PDF
Testing untestable code - IPC12
PDF
Testing untestable code - phpconpl11
PDF
Understanding Mocks
PDF
Testing untestable code - oscon 2012
PPTX
Unit testing and mocking in Python - PyCon 2018 - Kenya
PDF
Mocking Demystified
PPT
Integration testing
PDF
Just Mock It - Mocks and Stubs
PPTX
Type mock isolator
Mocking
Integration and Unit Testing in Java using Test Doubles like mocks and stubs
Mocking Dependencies in PHPUnit
CBDW2014 - MockBox, get ready to mock your socks off!
Unit testing
Getting started-php unit
PHPunit and you
Php Unit With Zend Framework Zendcon09
Testing untestable code - phpday
Testing untestable code - ConFoo13
Introduction to Unit Testing with PHPUnit
Testing untestable code - IPC12
Testing untestable code - phpconpl11
Understanding Mocks
Testing untestable code - oscon 2012
Unit testing and mocking in Python - PyCon 2018 - Kenya
Mocking Demystified
Integration testing
Just Mock It - Mocks and Stubs
Type mock isolator

Recently uploaded (20)

PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Big Data Technologies - Introduction.pptx
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Empathic Computing: Creating Shared Understanding
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
MIND Revenue Release Quarter 2 2025 Press Release
Diabetes mellitus diagnosis method based random forest with bat algorithm
Reach Out and Touch Someone: Haptics and Empathic Computing
“AI and Expert System Decision Support & Business Intelligence Systems”
Encapsulation_ Review paper, used for researhc scholars
NewMind AI Weekly Chronicles - August'25 Week I
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Programs and apps: productivity, graphics, security and other tools
Per capita expenditure prediction using model stacking based on satellite ima...
Big Data Technologies - Introduction.pptx
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Empathic Computing: Creating Shared Understanding
sap open course for s4hana steps from ECC to s4
Building Integrated photovoltaic BIPV_UPV.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Digital-Transformation-Roadmap-for-Companies.pptx
The AUB Centre for AI in Media Proposal.docx
Chapter 3 Spatial Domain Image Processing.pdf
20250228 LYD VKU AI Blended-Learning.pptx

Test in action week 3

  • 1. Test in Action – Week 3 Stub / Mock Hubert Chan
  • 2. Back to Basics • Wikipedia said unit testing is – A software verification and validation method in which a programmer tests if individual units of source code are fit for use.
  • 3. Dependency in the Test • System Under Test (SUT) Dependency – SUT need another module to perform its task • Handler need a $dbmodel to perform query • $handler = new Handler($dbmodel);
  • 4. Real Object is Hard to Test • Real object – Supplies non-deterministic results • (e.g. the current temperature) – Difficult to create or reproduce (e.g. network fail) – Slow (e.g. database) – Does not yet exist or may change behavior
  • 5. Substitute Dependency • Using Fake – Fake is anything not real • Fake techniques – Mock object – Stub object – Fake object
  • 6. Stub Objects • Stub Objects – Stubs provide canned answers to calls made during the test – Usually not responding at all to anything outside what's programmed in for the test
  • 7. Fake Objects • Fake Objects – Fake objects have working implementations – Usually take some shortcut, which makes them not suitable for production. – Example • An in-memory file system • An in-memory registry manager
  • 9. Example: AlertSystem • Component Overview – AlertSystem • Send notification to the targets, such as e-mail or SMS notifier. – NotifierInterface instance • Send actually notification to the target – NotifierTargetProviderInterface instance • Provide a target array to send notification
  • 10. AlertSystem Test • Dependency Analysis – Collaboration Classes • NotifierInterface • NotifierTargetProviderInterface • Tests should – Only focus on AlertSystem – Fake the dependency
  • 11. Make a Fake? • FileNotifyTargetProvider class FileNotifyTargetProvider implements NotifyTargetProviderInterface { function __construct($filename) { $this->_filename = $filename; } public function get_targets() { $targets = array(); $handle = @fopen($this->_filename, "r"); while (($target = fgets($handle)) !== FALSE) { $targets[] = $target; } return $targets; } }
  • 12. Make a Stub? • StubNotifier class StubNotifier implements NotifierInterface { public function notify($target, $content) { } }
  • 13. Example: Test Code • Test Code class AlertSystemTest extends PHPUnit_Framework_TestCase { public function test_sendNotify_FakeNStub_NoException() { $target_file = __DIR__ . '/data/targets.txt'; $notifier = new StubNotifier(); $provider = new FileNotifyTargetProvider($target_file); $alert_system = new AlertSystem( $notifier, $provider ); $alert_system->send_notify('Alert!!'); } }
  • 14. Manual Fake or Stub • Pros – Fake or stub can be used as library – Shared implementation • Cons – Different scenarios need different implementation – Testing class explosion
  • 15. Manual Stub or Fake • Cons – Need extra efforts/logics for behaviors • Setting return value • Setting thrown exception – Hard to validate • Calling sequence of functions • Passing arguments for functions • The method should be called
  • 16. Test Doubles • Using manual stub and mock – Is $notifier->notify() be called? – Does the target of $notifier->notify equal to expect target? – Does the content of $notifier->notify equal to expect target?
  • 17. Mock objects • Mock Objects – Mocks are objects pre-programmed with expectations, which form a specification of the calls they are expected to receive.
  • 18. Mock Object Example • Mock Object Example public function test_sendNotify_Mock_NoException() { $notify_content = 'fake_content'; $mock_notifier = $this->getMock('NotifierInterface'); $mock_notifier->expects($this->once()) ->method('notify') ->with($this->anything(), $this->equalTo($notify_content)); $alert_system = new AlertSystem( $mock_notifier, $stub_provider ); $alert_system->send_notify('Alert!!'); }
  • 19. Mock Object Example • Mock Object Verification – $notifier->notify is called only once – $notifier->notify 1st parameter can be anything – $notifier->notify 2nd parameter should be equal to $notify_content
  • 20. Using PHPUnit Stub • Return Value public function test_sendNotify_Mock_NoException() { $stub_provider = $this->getMock('NotifyTargetProviderInterface'); $targets = array('hubert'); $stub_provider->expects($this->any()) ->method('get_targets') ->will($this->returnValue($targets)); $alert_system = new AlertSystem( $mock_notifier, $stub_provider ); $alert_system->send_notify('Alert!!'); }
  • 21. Using PHPUnit Stub • Return one of the arguments public function testReturnArgumentStub() { // Create a stub for the SomeClass class. $stub = $this->getMock('SomeClass'); // Configure the stub. $stub->expects($this->any()) ->method('doSomething') ->will($this->returnArgument(0)); // $stub->doSomething('foo') returns 'foo' $this->assertEquals('foo', $stub->doSomething('foo')); // $stub->doSomething('bar') returns 'bar' $this->assertEquals('bar', $stub->doSomething('bar')); }
  • 22. Using PHPUnit Stub • Return a value from a callback – Useful for “out” parameter public function testReturnCallbackStub() { // Create a stub for the SomeClass class. $stub = $this->getMock('SomeClass'); // Configure the stub. $stub->expects($this->any()) ->method('doSomething') ->will($this->returnCallback('str_rot13')); // $stub->doSomething($argument) returns str_rot13($argument) $this->assertEquals('fbzrguvat', $stub->doSomething('something')); }
  • 23. PHPUnit Stub • Throw Exception public function testThrowExceptionStub() { // Create a stub for the SomeClass class. $stub = $this->getMock('SomeClass'); // Configure the stub. $stub->expects($this->any()) ->method('doSomething') ->will($this->throwException(new Exception)); // $stub->doSomething() throws Exception $stub->doSomething(); }
  • 24. Misconception About Mocks • Mocks are just Stubs – Mock is behavior verification • Is the function called? • Is the parameter passed correctly? – Stub is used for state verification – References • Mocks Aren’t Stubs – http://martinfowler.com/articles/mocksArentStubs.html
  • 25. Is it HARD to use stub/mock? • Untestable code – Make Your Own Dependencies – Heavy Duty Constructors – Depend on Concrete Classes – Use Statics – Using Singleton Everywhere – Look for Everything You Need
  • 26. Dependency Injection • Without dependency injection – Use “new” operator inside your class – Make mock object injection difficult • Dependency Injection – Inject dependencies through injectors – Injection method • Constructor • Setter • Dependency Injection Framework
  • 27. AlertSystem again • AlertSystem (Hard to Test) – Concrete classes – Make Your Own Dependencies class AlertSystem { public function send_notify($content) { $target_provider = new FileNotifyTargetProvider('data.txt'); $notifier = new EmailNotifier('user', 'pass', $port); $notify_targets = $target_provider->get_targets(); foreach ($notify_targets as $target) { $notifier->notify($target, $content); } } }
  • 28. AlertSystem constructor injection • Constructor Injection class AlertSystem { protected $_notifier; protected $_target_provider; function __construct ( NotifierInterface $notifier, NotifyTargetProviderInterface $provider ) { $this->_notifier = $notifier; $this->_target_provider = $provider; } public function send_notify($content) { $notify_targets = $this->_target_provider->get_targets(); foreach ($notify_targets as $target) { $this->_notifier->notify($target, $content); } } }
  • 29. Not only for testing • Single Responsibility Principle – Should alert system holds notifier and data provider logic? – Ex. Should the class read registry directly? • Dependency Inversion Principle • Open Close Principle
  • 30. The Law of Demeter • Definition – Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. – Each unit should only talk to its friends; don't talk to strangers. – Only talk to your immediate friends.
  • 31. Violation of the Law • How do you test for? – Mock for mock object, for another mock object – Like Looking for a Needle in the Haystack class Monitor { SparkPlug sparkPlug; Monitor(Context context) { this.sparkPlug = context. getCar().getEngine(). getPiston().getSparkPlug(); } }
  • 32. Law of Demeter - Explicit • Explicit – We should not need to know the details of collaborators class Mechanic { Engine engine; Mechanic(Engine engine) { this.engine = engine; } }
  • 33. Guide – Write Testable Code • Bad smell for non-testable Code – Constructor does real work – Digging into collaborators – Brittle Global State & Singletons – Class Does Too Much • References – Guide – Write Testable Code – http://misko.hevery.com/attachments/Guide- Writing%20Testable%20Code.pdf
  • 34. Conclusion • Writing good unit tests is hard • Good OO design brings good testability • Using stub/mock from mocking framework
  • 35. Q&A
  • 36. PHPUnit Log File • Junit Format <testsuites> <testsuite name="AlertSystemTest" file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTe st.php" tests="2" assertions="0" failures="1" errors="0" time="0.031119"> <testcase name="test_sendNotify_FakeNStub_NoException" class="AlertSystemTest" file="/usr/home/hubert/own/work/trend/process/CI/php/tests/AlertSystemTe st.php" line="8" assertions="0" time="0.006881"/> </testsuite> </testsuites>
  • 37. PHPUnit Coverage • PHPUnit Coverage – Need Xdebug – HTML format

Editor's Notes

  • #26: http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/
  • #27: http://tutorials.jenkov.com/dependency-injection/index.html
  • #31: https://secure.wikimedia.org/wikipedia/en/wiki/Law_of_Demeter