PHPunit
Episode IV.III!
Return of the tests
A long time ago,
in a code base not so far away…
For years people have been advocating the
usage of unit tests and slowly developers
around the world have adopted the skills to write
good tests. But since the crisis businesses have
been battling for customers and profits, leaving
less room for proper QA and testing. In this race
for money, things are looking dim and
unfavourable for businesses that have cut
corners and went straight for the gold.
Fortunately it’s not to late for development teams
to turn the tide and reclaim their honour and
ensure businesses aren’t disposing money out of
the window because of easily preventable
failures. The gloves are on and developers take
action to test what’s most important: the core of
the applications!
Auth ACL
Products
Customer
Details
Front-End
Back-End
Business
Logic
External
Services
RDBMS
Files
NoSQL
Streams
Auth ACL
Business
Logic
External
Services
Auth ACL
Business
Logic
External
Services
Mocked!
External!
Services
https://www.flickr.com/photos/noodlepie/3886519163
https://www.flickr.com/photos/cseeman/11101920756
https://www.flickr.com/photos/st3f4n/3752994778
Your class contains 10K lines!
I sense lots of anger in you
https://www.flickr.com/photos/clement127/16162227260
• createOrder
• updateOrder
• payOrder
• cancelOrder
• findOrderById
• findOrderByCustomerId
• findOrderByPaymentId
• createOrder
• updateOrder
• payOrder
• findOrderByPaymentId
• findOrderByCustomerId
• findOrderById
• cancelOrder
} High importance
} Normal importance
} Low importance
    /** "
     * Creates an order based on provided data "
     * "
     * @param array $data Associative array with order information "
     * @return bool|int Will return the order ID if storage was successful "
     * or false when storage failed "
     */ "
    public function createOrder($data) "
    { "
        $db = Registry::getInstance()->get('db'); "
        $sql = sprintf( "
            'INSERT INTO `order` (`productId`, `customerId`, "
            `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "
            $data['productId'], $data['customerId'], "
            $data['productPrice'], $data['quantity'] "
        ); "
        $id = false; "
        try { "
            $id = $db->exec($sql); "
        } catch (Exception $e) { "
            Registry::get('logger')->log($e->getMessage(), CRIT); "
            Registry::get('logger')->log($e->getTraceAsString(), INFO); "
        } "
        return $id; "
    }
https://www.flickr.com/photos/simononly/16445278475
/** "
 * Creates an order based on provided data "
 * "
 * @param array $data Associative array with order information "
 * @return bool|int Will return the order ID if storage was successful  "
 * or false when storage failed "
 */ "
public function createOrder($data) "
{ "
    $db = Registry::get('db'); "
    $sql = sprintf( "
        'INSERT INTO `order` (`productId`, `customerId`,  "
        `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "
        $data['productId'], $data['customerId'],  "
        $data['productPrice'], $data['quantity'] "
    ); "
    $id = false; "
    try { "
        $id = $db->query($sql); "
    } catch (Exception $e) { "
        Registry::get('logger')->log($e->getMessage(), CRIT); "
        Registry::get('logger')->log($e->getTraceAsString(), INFO); "
    } "
    return $id; "
}
/** "
 * Creates an order based on provided data "
 * "
 * @param array $data Associative array with order information "
 * @return bool|int Will return the order ID if storage was successful  "
 * or false when storage failed "
 */ "
public function createOrder($data) "
{ "
    $db = Registry::get('db'); "
    $sql = sprintf( "
        'INSERT INTO `order` (`productId`, `customerId`,  "
        `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "
        $data['productId'], $data['customerId'],  "
        $data['productPrice'], $data['quantity'] "
    ); "
    $id = false; "
    try { "
        $id = $db->query($sql); "
    } catch (Exception $e) { "
        Registry::get('logger')->log($e->getMessage(), CRIT); "
        Registry::get('logger')->log($e->getTraceAsString(), INFO); "
    } "
    return $id; "
}
/** "
 * Creates an order based on provided data "
 * "
 * @param array $data Associative array with order information "
 * @return bool|int Will return the order ID if storage was successful  "
 * or false when storage failed "
 */ "
public function createOrder($data) "
{ "
    $db = Registry::get('db'); "
    $sql = sprintf( "
        'INSERT INTO `order` (`productId`, `customerId`,  "
        `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "
        $data['productId'], $data['customerId'],  "
        $data['productPrice'], $data['quantity'] "
    ); "
    $id = false; "
    try { "
        $id = $db->query($sql); "
    } catch (Exception $e) { "
        Registry::get('logger')->log($e->getMessage(), CRIT); "
        Registry::get('logger')->log($e->getTraceAsString(), INFO); "
    } "
    return $id; "
}
What do we know?
What do we know?
• We provide an array with values in
What do we know?
• We provide an array with values in
• We get inserted ID or false back
What do we know?
• We provide an array with values in
• We get inserted ID or false back
• The code is crappy
class OrderTest extends PHPUnit_Framework_TestCase "
{ "
    public function testCreateOrder() "
    { "
        $data = array ( "
            'productId' => 1, "
            'customerId' => 1, "
            'productPrice' => 4.95, "
            'quantity' => 2, "
        ); "
        $order = new Order(); "
        $result = $order->createOrder($data); "
        $this->assertGreaterThanOrEqual(1, $result); "
    } "
}
    public function testCreateOrder() "
    { "
        $db = new PDO('sqlite::memory:'); "
        $db->exec('CREATE TABLE `order` ( "
          `orderId` INTEGER PRIMARY KEY NOT NULL, "
          `productId` INTEGER NOT NULL, "
          `customerId` INTEGER NOT NULL, "
          `productPrice` REAL NOT NULL DEFAULT 0.0, "
          `quantity` REAL NOT NULL DEFAULT 1.0);'); "
        Registry::getInstance()->register('db', $db); "
        $data = array ( "
            'productId' => 1, "
            'customerId' => 1, "
            'productPrice' => 4.95, "
            'quantity' => 2, "
        ); "
        $order = new Order(); "
        $result = $order->createOrder($data); "
        $this->assertGreaterThanOrEqual(1, $result); "
    }
https://www.flickr.com/photos/jurvetson/83176915
    public function testCreateOrder() "
    { "
        $db = $this->getMock('PDO',  "
            array ('exec'), array ('sqlite::memory:')); "
        $db->expects($this->once()) "
            ->method('exec') "
            ->will($this->returnValue(2)); "
!
        Registry::getInstance()->register('db', $db); "
        $data = array ( "
            'productId' => 1, "
            'customerId' => 1, "
            'productPrice' => 4.95, "
            'quantity' => 2, "
        ); "
        $order = new Order(); "
        $result = $order->createOrder($data); "
        $this->assertGreaterThanOrEqual(1, $result); "
    }
https://www.flickr.com/photos/legofenris/4578453569
    /** "
     * @var PDO "
     */ "
    protected $db; "
!
    /** "
     * @return PDO "
     */ "
    public function getDb() "
    { "
        if (null === $this->db) { "
            // fallback to old functions using this method "
            $this->setDb(Registry::getInstance()->get('db')); "
        } "
        return $this->db; "
    } "
!
    /** "
     * @param PDO $db "
     */ "
    public function setDb($db) "
    { "
        $this->db = $db; "
    }
    /** "
     * Creates an order based on provided data "
     * "
     * @param array $data Associative array with order information "
     * @return bool|int Will return the order ID if storage was successful "
     * or false when storage failed "
     */ "
    public function createOrder($data) "
    { "
        $db = $this->getDb(); "
        $sql = sprintf( "
            'INSERT INTO `order` (`productId`, `customerId`, "
            `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "
            $data['productId'], $data['customerId'], "
            $data['productPrice'], $data['quantity'] "
        ); "
        $id = false; "
        try { "
            $id = $db->exec($sql); "
        } catch (Exception $e) { "
            Registry::get('logger')->log($e->getMessage(), CRIT); "
            Registry::get('logger')->log($e->getTraceAsString(), INFO); "
        } "
        return $id; "
    }
https://www.flickr.com/photos/pasukaru76/5152497973
Michelangelo van Dam
dragonbe@gmail
T DragonBe
F DragonBe
www.dragonbe.com
Intergalactic PHP Ninja Consultant
https://www.flickr.com/photos/130160246@N02/16465367556
joind.in/event/view/3701
Rate my talk
If you liked it, thanks.
If you don’t, tell me how to improve it
https://www.flickr.com/photos/toomuchdew/14508564745

PHPUnit Episode iv.iii: Return of the tests

  • 1.
  • 2.
    A long timeago, in a code base not so far away…
  • 3.
    For years peoplehave been advocating the usage of unit tests and slowly developers around the world have adopted the skills to write good tests. But since the crisis businesses have been battling for customers and profits, leaving less room for proper QA and testing. In this race for money, things are looking dim and unfavourable for businesses that have cut corners and went straight for the gold.
  • 4.
    Fortunately it’s notto late for development teams to turn the tide and reclaim their honour and ensure businesses aren’t disposing money out of the window because of easily preventable failures. The gloves are on and developers take action to test what’s most important: the core of the applications!
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
    • createOrder • updateOrder •payOrder • cancelOrder • findOrderById • findOrderByCustomerId • findOrderByPaymentId
  • 16.
    • createOrder • updateOrder •payOrder • findOrderByPaymentId • findOrderByCustomerId • findOrderById • cancelOrder } High importance } Normal importance } Low importance
  • 17.
        /** "      * Creates an order based on provided data "      *"      * @param array $data Associative array with order information "      * @return bool|int Will return the order ID if storage was successful "      * or false when storage failed "      */ "     public function createOrder($data) "     { "         $db = Registry::getInstance()->get('db'); "         $sql = sprintf( "             'INSERT INTO `order` (`productId`, `customerId`, "             `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "             $data['productId'], $data['customerId'], "             $data['productPrice'], $data['quantity'] "         ); "         $id = false; "         try { "             $id = $db->exec($sql); "         } catch (Exception $e) { "             Registry::get('logger')->log($e->getMessage(), CRIT); "             Registry::get('logger')->log($e->getTraceAsString(), INFO); "         } "         return $id; "     }
  • 18.
  • 19.
    /** "  * Creates an order based on provided data "  *"  * @param array $data Associative array with order information "  * @return bool|int Will return the order ID if storage was successful  "  * or false when storage failed "  */ " public function createOrder($data) " { "     $db = Registry::get('db'); "     $sql = sprintf( "         'INSERT INTO `order` (`productId`, `customerId`,  "         `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "         $data['productId'], $data['customerId'],  "         $data['productPrice'], $data['quantity'] "     ); "     $id = false; "     try { "         $id = $db->query($sql); "     } catch (Exception $e) { "         Registry::get('logger')->log($e->getMessage(), CRIT); "         Registry::get('logger')->log($e->getTraceAsString(), INFO); "     } "     return $id; " }
  • 20.
    /** "  * Creates an order based on provided data "  *"  * @param array $data Associative array with order information "  * @return bool|int Will return the order ID if storage was successful  "  * or false when storage failed "  */ " public function createOrder($data) " { "     $db = Registry::get('db'); "     $sql = sprintf( "         'INSERT INTO `order` (`productId`, `customerId`,  "         `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "         $data['productId'], $data['customerId'],  "         $data['productPrice'], $data['quantity'] "     ); "     $id = false; "     try { "         $id = $db->query($sql); "     } catch (Exception $e) { "         Registry::get('logger')->log($e->getMessage(), CRIT); "         Registry::get('logger')->log($e->getTraceAsString(), INFO); "     } "     return $id; " }
  • 21.
    /** "  * Creates an order based on provided data "  *"  * @param array $data Associative array with order information "  * @return bool|int Will return the order ID if storage was successful  "  * or false when storage failed "  */ " public function createOrder($data) " { "     $db = Registry::get('db'); "     $sql = sprintf( "         'INSERT INTO `order` (`productId`, `customerId`,  "         `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "         $data['productId'], $data['customerId'],  "         $data['productPrice'], $data['quantity'] "     ); "     $id = false; "     try { "         $id = $db->query($sql); "     } catch (Exception $e) { "         Registry::get('logger')->log($e->getMessage(), CRIT); "         Registry::get('logger')->log($e->getTraceAsString(), INFO); "     } "     return $id; " }
  • 22.
  • 23.
    What do weknow? • We provide an array with values in
  • 24.
    What do weknow? • We provide an array with values in • We get inserted ID or false back
  • 25.
    What do weknow? • We provide an array with values in • We get inserted ID or false back • The code is crappy
  • 26.
    class OrderTest extends PHPUnit_Framework_TestCase " { "     public function testCreateOrder()"     { "         $data = array ( "             'productId' => 1, "             'customerId' => 1, "             'productPrice' => 4.95, "             'quantity' => 2, "         ); "         $order = new Order(); "         $result = $order->createOrder($data); "         $this->assertGreaterThanOrEqual(1, $result); "     } " }
  • 28.
        public function testCreateOrder() "     { "         $db = new PDO('sqlite::memory:');"         $db->exec('CREATE TABLE `order` ( "           `orderId` INTEGER PRIMARY KEY NOT NULL, "           `productId` INTEGER NOT NULL, "           `customerId` INTEGER NOT NULL, "           `productPrice` REAL NOT NULL DEFAULT 0.0, "           `quantity` REAL NOT NULL DEFAULT 1.0);'); "         Registry::getInstance()->register('db', $db); "         $data = array ( "             'productId' => 1, "             'customerId' => 1, "             'productPrice' => 4.95, "             'quantity' => 2, "         ); "         $order = new Order(); "         $result = $order->createOrder($data); "         $this->assertGreaterThanOrEqual(1, $result); "     }
  • 30.
  • 31.
        public function testCreateOrder() "     { "         $db = $this->getMock('PDO', "             array ('exec'), array ('sqlite::memory:')); "         $db->expects($this->once()) "             ->method('exec') "             ->will($this->returnValue(2)); " !         Registry::getInstance()->register('db', $db); "         $data = array ( "             'productId' => 1, "             'customerId' => 1, "             'productPrice' => 4.95, "             'quantity' => 2, "         ); "         $order = new Order(); "         $result = $order->createOrder($data); "         $this->assertGreaterThanOrEqual(1, $result); "     }
  • 33.
  • 34.
        /** "      * @var PDO "      */"     protected $db; " !     /** "      * @return PDO "      */ "     public function getDb() "     { "         if (null === $this->db) { "             // fallback to old functions using this method "             $this->setDb(Registry::getInstance()->get('db')); "         } "         return $this->db; "     } " !     /** "      * @param PDO $db "      */ "     public function setDb($db) "     { "         $this->db = $db; "     }
  • 35.
        /** "      * Creates an order based on provided data "      *"      * @param array $data Associative array with order information "      * @return bool|int Will return the order ID if storage was successful "      * or false when storage failed "      */ "     public function createOrder($data) "     { "         $db = $this->getDb(); "         $sql = sprintf( "             'INSERT INTO `order` (`productId`, `customerId`, "             `productPrice`, `quantity`) VALUES (%d, %d, %f, %f)', "             $data['productId'], $data['customerId'], "             $data['productPrice'], $data['quantity'] "         ); "         $id = false; "         try { "             $id = $db->exec($sql); "         } catch (Exception $e) { "             Registry::get('logger')->log($e->getMessage(), CRIT); "             Registry::get('logger')->log($e->getTraceAsString(), INFO); "         } "         return $id; "     }
  • 37.
  • 38.
    Michelangelo van Dam dragonbe@gmail TDragonBe F DragonBe www.dragonbe.com Intergalactic PHP Ninja Consultant https://www.flickr.com/photos/130160246@N02/16465367556
  • 39.
    joind.in/event/view/3701 Rate my talk Ifyou liked it, thanks. If you don’t, tell me how to improve it
  • 40.