unit_testing.pdf

41
Unit Testing Merangkak Menuju Pengembangan Aplikasi PHP yang Berkualitas dan Tahan Banting Arthur Purnama arthur [at] purnama.de http://arthur.purnama.de 06.04.2011

Upload: yeni-setiawan

Post on 28-Aug-2014

55 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Unit_Testing.pdf

Unit Testing

Merangkak Menuju Pengembangan Aplikasi

PHP yang Berkualitas dan Tahan Banting

Arthur Purnama

arthur [at] purnama.de

http://arthur.purnama.de

06.04.2011

Page 2: Unit_Testing.pdf

Arthur Purnama

Diplom Informatiker Hochschule Fulda

Sejak 2004 bekerja sebagai PHP

Programmer

Sejak 2008 bekerja sebagai ITConsultant

divisi Portal Solutions

Saat ini tinggal di Frankfurt am Main, Jerman

Page 3: Unit_Testing.pdf

Tujuan

Memperkenalkan Unit Testing

Mendorong atau memotivasi penggunaan

Unit Testing

Memperkenalkan Unit Testing Framework

PHPUnit

Page 4: Unit_Testing.pdf

Rutinitas Test Programer PHP

Berjam-jam mencari bug

Debugger? apaan tuh?

Teman setia: echo, print_r, var_dump

Mati satu tumbuh seribu (bug baru)

Bug Lama Bersemi Kembali

Page 5: Unit_Testing.pdf

Unit Testing

In computer programming, unit testing is a

method by which individual units of source

code are tested to determine if they are fit for

use.

A unit is the smallest testable part of an

application.

In object-oriented programming a unit is

usually a method.

http://en.wikipedia.org/wiki/Unit_testing

Page 6: Unit_Testing.pdf

Unit Testing

Dalam pemrograman komputer, unit testing

merupakan suatu metode yang mana satu

unit dalam source code diuji untuk

menunjukkan bahwa code tersebut bekerja

sebagaimana mestinya.

Unit adalah bagian terkecil dari satu aplikasi

yang dapat diuji.

Dalam pemrograman berorientasi obyek, unit

biasanya adalah method.

Page 7: Unit_Testing.pdf

Contoh

function multiplicate($a, $b){

return $a*$b;

}

echo multiplicate(1, 2) === 2 ? true : false;

echo PHP_EOL;

echo multiplicate(2, 2) === 4 ? true : false;

echo PHP_EOL;

echo multiplicate(3, 2) !== 5 ? true : false;

Page 8: Unit_Testing.pdf

Kelebihan Unit Testing

Yakin setiap saat bahwa code berfungsi

sebagaimana mestinya.

Yakin setiap kali aplikasi berkembang, code

tetap berfungsi sebagaimana mestinya.

Yakin setiap kali melakukan re-design atau

refakturisasi, code tetap berfungsi

sebagaimana mestinya.

Page 9: Unit_Testing.pdf

Kelebihan Unit Testing

Menjadi bagian dari dokumentasi code

Mempermudah Integrasi antar komponen

Meningkatkan kualitas code

Page 10: Unit_Testing.pdf

Unsur Unit Testing

Harus di otomatisasi

Dapat dijalankan dengan sekali klick

Dapat dengan mudah diulang

Mudah diimplementasikan

Setelah ditulis dapat dijalankan kapan saja

Setiap orang dapat menjalankannya

Berjalan dengan cepat

Page 11: Unit_Testing.pdf

Unit Test != Integration Test

Unit Test

Tidak berinteraksi dengan basis data

Tidak berinteraksi dengan Jaringan

Tidak berinteraksi dengan File System

Tidak membutuhkan konfigurasi khusus untuk

menjalankannya

Terisolasi dari komponen atau kelas konkrit

lainnya

Page 12: Unit_Testing.pdf

Unit Testing Framework

PHPUnit

Unit Testing Framework

Ditulis oleh Sebastian Bergmann

De facto standard untuk PHP

Banyak didukung oleh Tools dan Framework lain

Page 13: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

}

?>

Page 14: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

//Nama fungsi menggunakan awalan “test“

public function testMultiplicate(){

}

}

?>

Page 15: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

//Nama fungsi menggunakan awalan “test“

public function testMultiplicate(){

$this->assertEquals(2, multiplicate(1, 2));

}

}

?>

Page 16: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

$>phpunit BelajarUnitTest MultiplikasiTest.php

PHPUnit 3.5.12 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 1 assertion)

Page 17: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

public function testMultiplicate(){

//Sangat tidak dianjurkan. Pastikan hanya selalu menguji SATU hal

$this->assertEquals(2, multiplicate(1, 2));

$this->assertEquals(5, multiplicate(3, 2));

$this->assertEquals(4, multiplicate(2, 2));

}

}

?>

Page 18: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

$>phpunit BelajarUnitTest MultiplikasiTest.php

PHPUnit 3.5.12 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 3.00Mb

There was 1 failure:

1) BelajarUnitTest::testMultiplicate

Failed asserting that <integer:6> matches expected <integer:5>.

$\MultiplikasiTest.php:10

FAILURES!

Tests: 1, Assertions: 2, Failures: 1.

Page 19: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

public function testMultiplicate1And2(){

$this->assertEquals(2, multiplicate(1, 2));

}

public function testMultiplicate3And2(){

$this->assertEquals(5, multiplicate(3, 2));

}

public function testMultiplicate2And2(){

$this->assertEquals(4, multiplicate(2, 2));

}

}

?>

Page 20: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

$>phpunit MultiplikasiTest.php

PHPUnit 3.5.12 by Sebastian Bergmann.

.F.

Time: 0 seconds, Memory: 3.00Mb

There was 1 failure:

1) BelajarUnitTest::testMultiplicate3And2

Failed asserting that <integer:6> matches expected <integer:5>.

$\MultiplikasiTest.php:12

FAILURES!

Tests: 3, Assertions: 3, Failures: 1.

Page 21: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

<?php

//MultiplikasiTest.php

require_once 'multiplikasi.php';

class BelajarUnitTest extends PHPUnit_Framework_TestCase{

public function testMultiplicate1And2(){

$this->assertEquals(2, multiplicate(1, 2));

}

public function testMultiplicate3And2(){

$this->assertNotEquals(5, multiplicate(3, 2));

}

public function testMultiplicate2And2(){

$this->assertEquals(4, multiplicate(2, 2));

}

}

?>

Page 22: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

$>phpunit BelajarUnitTest MultiplikasiTest.php

PHPUnit 3.5.12 by Sebastian Bergmann.

...

Time: 0 seconds, Memory: 3.00Mb

OK (3 tests, 3 assertions)

Page 23: Unit_Testing.pdf

Contoh Unit Testing Multiplikasi

$>phpunit --testdox BelajarUnitTest MultiplikasiTest.php

PHPUnit 3.5.12 by Sebastian Bergmann.

BelajarUnitTest

[x] Multiplicate 1 and 2

[x] Multiplicate 3 and 2

[x] Multiplicate 2 and 2

Page 24: Unit_Testing.pdf

Tapi.. Code saya seperti ini..

<?php

// Connects to your Database

mysql_connect ( "your.hostaddress.com", "username", "password" ) or die ( mysql_error () );

mysql_select_db ( "Database_Name" ) or die ( mysql_error () );

//checks cookies to make sure they are logged in

if (isset ( $_SESSION ['ID_my_site'] )) {

$username = $_ SESSION ['ID_my_site'];

$pass = $_ SESSION ['Key_my_site'];

$check = mysql_query ( "SELECT * FROM users WHERE username = '$username'" ) or die ( mysql_error () );

$result = mysql_fetch_array ( $check );

foreach ( $result as $info ) {

//if the cookie has the wrong password, they are taken to the login page

if ($pass != $info ['password']) {

header ( "Location: login.php" );

} else { //otherwise they are shown the admin area

echo "<p>Admin Area</p>";

echo "<p>Your Content<p>";

echo "<a href=logout.php>Logout</a>";

}

}

} else {

//if the cookie does not exist, they are taken to the login screen

header ( "Location: login.php" );

}

?>

Page 25: Unit_Testing.pdf

Core techniques

Refactoring

Separation of Concern

Inversion of Control (Dependency Injection)

Design by Contract

Design Patterns

Page 26: Unit_Testing.pdf

Contoh Refactoring

<?php

namespace myapp\security;

use myapp\daos\interfaces\User;

use myapp\util\interfaces\Session;

class Authorize implements interfaces\Authorize{

private $userDAO;

private $session;

public function __construct(User $userDAO, Session $session) {

$this->userDAO = $userDAO;

$this->session = $session;

}

public function isAuthorize(){

if($this->session->isAuthenticate()){

$user = $this->userDAO->getByUsername($this->session->getUsername());

return $this->session->getPassword() === $user->getPassword();

}else{

return false;

}

}

}

?>

Page 27: Unit_Testing.pdf

Mocks & Stubs

<?php

namespace myapp\mocks;

use myapp\daos\interfaces\User;

class UserPalsu implements User{

public function getById($id){

return null;

}

public function getByUsername($username){

return null;

}

public function getAll(){

return null;

}

}

?>

<?php

namespace myapp\mocks;

use myapp\util\interfaces\Session;

class SessionPalsu implements Session{

public function getUsername(){

return null;

}

public function getPassword(){

return null;

}

public function isAuthenticate(){

return false;

}

}

?>

Page 28: Unit_Testing.pdf

Unit Test Authorize

<?php

use myapp\security\Authorize;

use myapp\mocks\SessionPalsu;

use myapp\mocks\UserPalsu;

class AuthorizeTest extends PHPUnit_Framework_TestCase {

public function testIsAuthorizeSessionNotAuthenticate(){

$userDAO = new UserPalsu();

$session = new SessionPalsu();

$authorize = new Authorize($userDAO, $session);

$this->assertFalse($authorize->isAuthorize());

}

}

?>

Page 29: Unit_Testing.pdf

Mocks & Stubs

<?php

namespace myapp\mocks;

use myapp\models;

use myapp\daos\interfaces\User;

class UserPalsu implements User{

private $user;

public function getById($id){

return null;

}

public function getByUsername($username){

return $this->user;

}

public function getAll(){

return null;

}

public function

setUser(models\interfaces\User $user){

$this->user = $user;

}

}

?>

<?php

namespace myapp\mocks;

use myapp\util\interfaces\Session;

class SessionPalsu implements Session{

private $username;

private $password;

private $authenticate;

public function getUsername() {

return $this->username;

}

public function setUsername($username) {

$this->username = $username;

}

public function getPassword() {

return $this->password;

}

public function setPassword($password) {

$this->password = $password;

}

public function isAuthenticate(){

return $this->authenticate;

}

public function setAuthenticate($authenticate){

$this->authenticate = $authenticate;

}

}

?>

Page 30: Unit_Testing.pdf

Unit Test Authorize

<?php

use myapp\models\User;

use myapp\security\Authorize;

use myapp\mocks\SessionPalsu;

use myapp\mocks\UserPalsu;

class AuthorizeTest extends PHPUnit_Framework_TestCase {

//public function testIsAuthorizeSessionNotAuthenticate(){...

public function testIsAuthorizeSessionAuthenticateButWrongPassword(){

$userDAO = new UserPalsu();

$user = new User("username", "password");

$userDAO->setUser($user);

$session = new SessionPalsu();

$session->setPassword("wrongpassword");

$authorize = new Authorize($userDAO, $session);

$this->assertFalse($authorize->isAuthorize());

}

public function testIsAuthorizeSessionAuthenticateCorrectPassword(){

$userDAO = new UserPalsu();

$user = new User("username", "password");

$userDAO->setUser($user);

$session = new SessionPalsu();

$session->setPassword("password");

$authorize = new Authorize($userDAO, $session);

$this->assertTrue($authorize->isAuthorize());

}

}

?>

Page 31: Unit_Testing.pdf

Mengorganisir Unit Test

Fixture

Bootstrap

Stubs & Mocks Tools

Test Suite

Code Coverage

Page 32: Unit_Testing.pdf

Fixtures

<?php

use myapp\models\User;

use myapp\security\Authorize;

use myapp\mocks\SessionPalsu;

use myapp\mocks\UserPalsu;

class AuthorizeTest extends PHPUnit_Framework_TestCase {

private $userDAO;

private $session;

public function setUp(){

$this->userDAO = new UserPalsu();

$user = new User("username", "password");

$this->userDAO->setUser($user);

$this->session = new SessionPalsu();

$this->session->setAuthenticate(true);

}

public function tearDown(){

$this->userDAO = null;

$this->session = null;

}

//public function testIsAuthorizeSessionNotAuthenticate(){..

public function testIsAuthorizeSessionAuthenticateButWrongPassword(){

$this->session->setPassword("wrongpassword");

$authorize = new Authorize($this->userDAO, $this->session);

$this->assertFalse($authorize->isAuthorize());

}

public function testIsAuthorizeSessionAuthenticateCorrectPassword(){

$this->session->setPassword("password");

$authorize = new Authorize($this->userDAO, $this->session);

$this->assertTrue($authorize->isAuthorize());

}

}?>

Page 33: Unit_Testing.pdf

Bootstrap

<phpunit bootstrap="/path/to/bootstrap.php"

colors="false"

convertErrorsToExceptions="true"

convertNoticesToExceptions="true"

convertWarningsToExceptions="true"

stopOnFailure="true">

<!-- ... -->

</phpunit>

Page 34: Unit_Testing.pdf

Stubs and Mocks Tools

<?php

use myapp\security\Authorize;

class AuthorizeTest extends PHPUnit_Framework_TestCase {

private $userDAO;

private $session;

public function setUp() {

$this->userDAO = $this->getMock ( '\myapp\daos\User' );

$user = $this->getMock ( 'myapp\models\User', array(), array(), '', false, false, false );

$user->expects ( $this->any () )->method ( 'getUsername' )->will ( $this->returnValue ( 'username' ) );

$user->expects ( $this->any () )->method ( 'getPassword' )->will ( $this->returnValue ( 'password' ) );

$this->userDAO->expects ( $this->any () )->method ( 'getByUsername' )->will ( $this->returnValue ( $user ) );

$this->session = $this->getMock ( '\myapp\util\Session', array(), array(), '', false, false, false );

$this->session->expects ( $this->any () )->method ( 'isAuthenticate' )->will ( $this->returnValue ( true ) );

}

public function tearDown() {

$this->userDAO = null;

$this->session = null;

}

//public function testIsAuthorizeSessionNotAuthenticate(){...

public function testIsAuthorizeSessionAuthenticateButWrongPassword() {

$this->session->expects ( $this->any () )->method ( 'getPassword' )->will ( $this->returnValue ( 'wrongpassword' ) );

$authorize = new Authorize ( $this->userDAO, $this->session );

$this->assertFalse ( $authorize->isAuthorize () );

}

public function testIsAuthorizeSessionAuthenticateCorrectPassword() {

$this->session->expects ( $this->any () )->method ( 'getPassword' )->will ( $this->returnValue ( 'password' ) );

$authorize = new Authorize ( $this->userDAO, $this->session );

$this->assertTrue ( $authorize->isAuthorize () );

}

}

?>

Page 35: Unit_Testing.pdf

Test Suite File SystemObject Tests

|-- Freezer |-- Freezer

| |-- HashGenerator | |-- HashGenerator

| | `-- NonRecursiveSHA1.php | | `-- NonRecursiveSHA1Test.php

| |-- HashGenerator.php | |

| |-- IdGenerator | |-- IdGenerator

| | `-- UUID.php | | `-- UUIDTest.php

| |-- IdGenerator.php | |

| |-- LazyProxy.php | |

| |-- Storage | |-- Storage

| | `-- CouchDB.php | | `-- CouchDB

| | | | |-- WithLazyLoadTest.php

| | | | `-- WithoutLazyLoadTest.php

| |-- Storage.php | |-- StorageTest.php

| `-- Util.php | `-- UtilTest.php

`-- Freezer.php `-- FreezerTest.php

$>phpunit Tests

PHPUnit 3.5.13 by Sebastian Bergmann.

............................................................ 60 / 75

...............

Time: 0 seconds

OK (75 tests, 164 assertions)

Page 36: Unit_Testing.pdf

Test Suite XML

<phpunit>

<testsuites>

<testsuite name="Object_Freezer">

<file>Tests/Freezer/HashGenerator/NonRecursiveSHA1Test.php</file>

<file>Tests/Freezer/IdGenerator/UUIDTest.php</file>

<file>Tests/Freezer/UtilTest.php</file>

<file>Tests/FreezerTest.php</file>

<file>Tests/Freezer/StorageTest.php</file>

<file>Tests/Freezer/Storage/CouchDB/WithLazyLoadTest.php</file>

<file>Tests/Freezer/Storage/CouchDB/WithoutLazyLoadTest.php</file>

</testsuite>

</testsuites>

</phpunit>

Page 37: Unit_Testing.pdf

Code Coverage

Page 38: Unit_Testing.pdf

Memulai Unit Testing

Yakinkan diri sendiri

Kumpulkan Case Study atau Success Story http://biblio.gdinwiddie.com/biblio/StudiesOfTestDrivenDevelopment

Cari Pendukung / Panggil Konsultan

Tentukan Tujuan

Catat Perkembangan

Bersiap menghadapi rintangan

Page 39: Unit_Testing.pdf

Kemana Setelah Ini

Metodologi

Test Driven Development

Behaviour Driven Development

Tools Pendukung

IDE (Zend Studio, PHPStorm, PDT, NetBeans)

Build Automation (Ant, Maven, Phing)

Continuous Integration

Test Lain menggunakan PHPUnit

Database Testing

UI Testing (Selenium)

Diskusi terbuka di Milist / Groups

Page 40: Unit_Testing.pdf

Referensi

Wikipedia http://en.wikipedia.org/wiki/Unit_testing

„PHPUnit Manual“ – Sebastian Bergmann http://www.phpunit.de/manual/current/en/

„Getting Started With PHPUnit “ – Sebastian Bergmann http://www.slideshare.net/sebastian_bergmann/getting-started-with-phpunit

„The Art of Unit Testing“ - Roy Osherove

„Unit Testing Fundamentals“ – Richard Paul http://www.slideshare.net/rapaul/unit-testing-fundamentals

„Embrace Unit Testing“ – Alessio Pace http://www.slideshare.net/alessiopace/embrace-unit-testing