SlideShare une entreprise Scribd logo
1  sur  28
Télécharger pour lire hors ligne
Unit Testing für Dummies
15.11.2009

Lars Jankowfsky, swoodoo AG
Thorsten Rinne, Mayflower GmbH
About me:



            PHP, C++, Developer, Software Architect since 1992

            PHP since 1998

            Many successful projects from 2 to 20 developers

            Running right now three projects using eXtreme
            Programming

            CTO and (Co-)Founder swoodoo AG

            (Co-)Founder OXID eSales AG
About me:



            Diplom-Informatiker (FH)
            Certified Scrum Master
            Zend Certified Engineer

            PHP since 1999

            Many successful projects from 2 to 6 developers
            using Scrum, eXtreme Programming, Crystal Clear

            Senior Developer / Team Lead at Mayflower GmbH

            Master of phpMyFAQ
(c) spackletoe http://www.flickr.com/photos/spackletoe/90811910/)
                                                   (c) aboutpixel.de
Unit Tests?




              PHPUnit   Fixtures



               Stubs    Pitfalls
PHPUnit
http://www.phpunit.de/
PHPUnit                                         PHPUnit



  phpunit myTest

  user@workshop:/var/www/thorsten-zfguestbook/tests/
  application$ phpunit controllers_PostsControllerTest
Fixtures
Fixtures                                                Fixtures


    Make sure that tests don‘t alter fixture

    Fixture is FIXture

    if you feel creating fixtures is too much work - refactor more!

    Do never let tests leave altered tests
Fixtures the Ruby way...                          Fixtures


    Ruby uses YAML

    www.yaml.org

    PHP YAML support done by using Syck

    Syck = YAML + fast

    http://whytheluckystiff.net/syck/

    http://www.frontalaufprall.com/2008/05/05/php-unit-
    database-fixtures-the-ruby-way/
YAML loading                                      Fixtures




  public static function create($fileName)
   {
       $fileName = 'Fixtures'.DIRECTORY_SEPARATOR.$fileName;
       ob_start();
       include $fileName;
       $fileContents = ob_get_contents();
       ob_clean();
       $yamlData = syck_load($fileContents);
       return $yamlData;
   }
YAML storing                                                      Fixtures



public static function load($fixtures, $tableName)
    {
        if (is_array($fixtures) && count($fixtures)) {
            foreach ($fixtures as $fixture) {
                if (is_array($fixture) && is_array(current($fixture))) {
                    Fixtures::load($fixture, $tableName);
                }

                $fields = array_keys($fixture);
                $statement = "INSERT INTO $tableName (" . implode(', ',
$fields) . ") VALUES (:" . implode(", :", $fields) . ")";
                $stmt = self::$_db->prepare($statement);
                if (count($fixture)) {
                    foreach ($fixture as $key => $value ) {
                        $stmt->bindValue(':'.$key, $value);
                    }
                }
                $stmt->execute();

                self::$_usedTables[$tableName] = $tableName;               }
        }
    }
YAML - cleanup                                                Fixtures




if (!empty(self::$_usedTables)) {
            foreach (array_reverse(self::$_usedTables) as $tableName) {
                    self::$_db->execute("TRUNCATE TABLE $tableName");
            }
        }
Fixtures the other side ...                        Fixtures


    manual fixtures are too much work

    use a test database

    think about automatic creation of YAML files
Stubs
Mocking stubs?                                          Stubs


   Unittesting is about testing a unit of work, not a complete
   workflow

   isolates your code from external dependencies

   can be done with PHPUnit, but you don‘t need to
Mocking stubs The PHPUnit way                                   Stubs


/**
  * A simple stub providing a simple result directly instead of using the
database
  */
class UserModelStub extends UserModel
{
     public getUserCount()
     {
         return 10;
     }
}

UserModelStub extends PHPUnit_Framework_Testcase
{
    public function testGetUserCount()
    {
        $stub = $this->getMock(‘UserModel‘);
        $stub->expects($this->any())->method(‘getUserCount‘)->will($this-
>returnValue(10));
    }
}
Pitfalls
Code the unit test first.   Pitfalls


     OOP, public, private

     Globals

     Superglobals

     Sessions

     Cookies
Dependencies ...                                    Pitfalls


    Separate logic from view

    create accessors, add all parameters in calls
Dependency Example                                                        Pitfalls




class displayUserDetails()
{
    /**
     * Processes input and sends user first name, last name to display;
     */
    function show() {
        global $dbLink;
        global $templateEngine;
        $itemId = (int) $_REQUEST['user_id'];

        $firstName = $dbLink->getOne("select first_name from users where id =
$itemId");
        $lastName = $dbLink->getOne("select last_name from users where id = $itemId");

        $templateEngine->addTemplateVar('firstName', $firstName);
        $templateEngine->addTemplateVar('lastName', $lastName);
        $templateEngine->display();
    }
}
Dependency Example                                                                       Pitfalls


/**
  * A view class responsible for displaying user details.
  */
class userView()
{
     /**
       * Loads user object and sends first name, last name to display
       */
     public function show()
     {
          $userId = $this->_inputProcessor->getParameter("user_id");

        $this->templateEngine->addTemplateVar('user', $this->model->loadUser(userId));
        $this->templateEngine->display();
    }
}

/**
  * And the corresponding model
  */
class userModel()
{
         public function loadUser($userId)
         {
              $user = new User( $userId );

            return array('firstName' => $user->getFirstName(),
                         'lastName' => $user->getLastName());
        }
}
STOP
Layer Example                                                 Pitfalls


class someOtherClass {
    var $setting;

    function calculateSomething($a, $b) {
        return $a+$b;
    }
}

class myOldNastyClass {

    function needToTestThisFunction() {

        $class = new someOtherClass();

        $z = $_GET['input'];

        // ....

        return $class->calculateSomething( $class->setting, $z);
    }
}
Layer Example                                                              Pitfalls


class someOtherClass {
    private $setting;

    public function calculateSomething($a, $b) {
        return $a+$b;
    }

    public function setSetting($set) {
        $this->setting = $set;
    }

    public function getSetting() {
        return $this->setting;
    }
}

class myInput {
    public function getParameter($name) {
        return $_GET[$name];
    }
}

class myOldNastyClass {

    private $input; // set e.g. in constructor

    public function needToTestThisFunction(someOtherClass &$class, $z) {

        $z = $input->getParameter('input');
        // ....

        return $class->calculateSomething( $class->getSetting(), $z);
    }
}
(c) istockphoto
„Questions?“

Contenu connexe

Tendances

Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
Bill Chang
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
Wildan Maulana
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
Fabien Potencier
 

Tendances (20)

PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Lithium Best
Lithium Best Lithium Best
Lithium Best
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
PHP Traits
PHP TraitsPHP Traits
PHP Traits
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 

En vedette

Mobile App Tracking - How it Works
Mobile App Tracking - How it WorksMobile App Tracking - How it Works
Mobile App Tracking - How it Works
MobileAppTracking
 
Theory and practice – migrating your legacy code into our modern test drive...
Theory and practice – migrating your  legacy code into our modern test  drive...Theory and practice – migrating your  legacy code into our modern test  drive...
Theory and practice – migrating your legacy code into our modern test drive...
Lars Jankowfsky
 

En vedette (7)

Mobile App Tracking - How it Works
Mobile App Tracking - How it WorksMobile App Tracking - How it Works
Mobile App Tracking - How it Works
 
Theory and practice – migrating your legacy code into our modern test drive...
Theory and practice – migrating your  legacy code into our modern test  drive...Theory and practice – migrating your  legacy code into our modern test  drive...
Theory and practice – migrating your legacy code into our modern test drive...
 
Agile Development with PHP in Practice
Agile Development with PHP in PracticeAgile Development with PHP in Practice
Agile Development with PHP in Practice
 
Agile Entwicklung OXID Commons
Agile Entwicklung OXID CommonsAgile Entwicklung OXID Commons
Agile Entwicklung OXID Commons
 
Why Architecture in Web Development matters
Why Architecture in Web Development mattersWhy Architecture in Web Development matters
Why Architecture in Web Development matters
 
Caching, sharding, distributing - Scaling best practices
Caching, sharding, distributing - Scaling best practicesCaching, sharding, distributing - Scaling best practices
Caching, sharding, distributing - Scaling best practices
 
Google Mobile App Analytics
Google Mobile App AnalyticsGoogle Mobile App Analytics
Google Mobile App Analytics
 

Similaire à Unittests für Dummies

international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
smueller_sandsmedia
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware
 

Similaire à Unittests für Dummies (20)

Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Using the Windows 8 Runtime from C++
Using the Windows 8 Runtime from C++Using the Windows 8 Runtime from C++
Using the Windows 8 Runtime from C++
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Dernier (20)

A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 

Unittests für Dummies

  • 1. Unit Testing für Dummies 15.11.2009 Lars Jankowfsky, swoodoo AG Thorsten Rinne, Mayflower GmbH
  • 2. About me: PHP, C++, Developer, Software Architect since 1992 PHP since 1998 Many successful projects from 2 to 20 developers Running right now three projects using eXtreme Programming CTO and (Co-)Founder swoodoo AG (Co-)Founder OXID eSales AG
  • 3. About me: Diplom-Informatiker (FH) Certified Scrum Master Zend Certified Engineer PHP since 1999 Many successful projects from 2 to 6 developers using Scrum, eXtreme Programming, Crystal Clear Senior Developer / Team Lead at Mayflower GmbH Master of phpMyFAQ
  • 5. Unit Tests? PHPUnit Fixtures Stubs Pitfalls
  • 7. PHPUnit PHPUnit phpunit myTest user@workshop:/var/www/thorsten-zfguestbook/tests/ application$ phpunit controllers_PostsControllerTest
  • 9. Fixtures Fixtures Make sure that tests don‘t alter fixture Fixture is FIXture if you feel creating fixtures is too much work - refactor more! Do never let tests leave altered tests
  • 10. Fixtures the Ruby way... Fixtures Ruby uses YAML www.yaml.org PHP YAML support done by using Syck Syck = YAML + fast http://whytheluckystiff.net/syck/ http://www.frontalaufprall.com/2008/05/05/php-unit- database-fixtures-the-ruby-way/
  • 11. YAML loading Fixtures public static function create($fileName) { $fileName = 'Fixtures'.DIRECTORY_SEPARATOR.$fileName; ob_start(); include $fileName; $fileContents = ob_get_contents(); ob_clean(); $yamlData = syck_load($fileContents); return $yamlData; }
  • 12. YAML storing Fixtures public static function load($fixtures, $tableName) { if (is_array($fixtures) && count($fixtures)) { foreach ($fixtures as $fixture) { if (is_array($fixture) && is_array(current($fixture))) { Fixtures::load($fixture, $tableName); } $fields = array_keys($fixture); $statement = "INSERT INTO $tableName (" . implode(', ', $fields) . ") VALUES (:" . implode(", :", $fields) . ")"; $stmt = self::$_db->prepare($statement); if (count($fixture)) { foreach ($fixture as $key => $value ) { $stmt->bindValue(':'.$key, $value); } } $stmt->execute(); self::$_usedTables[$tableName] = $tableName; } } }
  • 13. YAML - cleanup Fixtures if (!empty(self::$_usedTables)) { foreach (array_reverse(self::$_usedTables) as $tableName) { self::$_db->execute("TRUNCATE TABLE $tableName"); } }
  • 14. Fixtures the other side ... Fixtures manual fixtures are too much work use a test database think about automatic creation of YAML files
  • 15. Stubs
  • 16. Mocking stubs? Stubs Unittesting is about testing a unit of work, not a complete workflow isolates your code from external dependencies can be done with PHPUnit, but you don‘t need to
  • 17. Mocking stubs The PHPUnit way Stubs /** * A simple stub providing a simple result directly instead of using the database */ class UserModelStub extends UserModel { public getUserCount() { return 10; } } UserModelStub extends PHPUnit_Framework_Testcase { public function testGetUserCount() { $stub = $this->getMock(‘UserModel‘); $stub->expects($this->any())->method(‘getUserCount‘)->will($this- >returnValue(10)); } }
  • 19. Code the unit test first. Pitfalls OOP, public, private Globals Superglobals Sessions Cookies
  • 20. Dependencies ... Pitfalls Separate logic from view create accessors, add all parameters in calls
  • 21. Dependency Example Pitfalls class displayUserDetails() { /** * Processes input and sends user first name, last name to display; */ function show() { global $dbLink; global $templateEngine; $itemId = (int) $_REQUEST['user_id']; $firstName = $dbLink->getOne("select first_name from users where id = $itemId"); $lastName = $dbLink->getOne("select last_name from users where id = $itemId"); $templateEngine->addTemplateVar('firstName', $firstName); $templateEngine->addTemplateVar('lastName', $lastName); $templateEngine->display(); } }
  • 22. Dependency Example Pitfalls /** * A view class responsible for displaying user details. */ class userView() { /** * Loads user object and sends first name, last name to display */ public function show() { $userId = $this->_inputProcessor->getParameter("user_id"); $this->templateEngine->addTemplateVar('user', $this->model->loadUser(userId)); $this->templateEngine->display(); } } /** * And the corresponding model */ class userModel() { public function loadUser($userId) { $user = new User( $userId ); return array('firstName' => $user->getFirstName(), 'lastName' => $user->getLastName()); } }
  • 23. STOP
  • 24.
  • 25. Layer Example Pitfalls class someOtherClass { var $setting; function calculateSomething($a, $b) { return $a+$b; } } class myOldNastyClass { function needToTestThisFunction() { $class = new someOtherClass(); $z = $_GET['input']; // .... return $class->calculateSomething( $class->setting, $z); } }
  • 26. Layer Example Pitfalls class someOtherClass { private $setting; public function calculateSomething($a, $b) { return $a+$b; } public function setSetting($set) { $this->setting = $set; } public function getSetting() { return $this->setting; } } class myInput { public function getParameter($name) { return $_GET[$name]; } } class myOldNastyClass { private $input; // set e.g. in constructor public function needToTestThisFunction(someOtherClass &$class, $z) { $z = $input->getParameter('input'); // .... return $class->calculateSomething( $class->getSetting(), $z); } }