Jag har funderat ett tag på att skriva ihop några små, informativa inlägg här - då det är ganska mycket aktivitet i det här forumet. Många är nybörjare, många arbetar dagligen med PHP - antingen för sin egen utveckling eller professionellt. Hur som helst tyckte jag att det skulle vara intressant med diskussioner kring lite mer avancerade sätt att arbeta med PHP. Jag är först ut med att föreslå användande av PHPUnit - ett bibliotek för unit-testning på PHP-kod. Den kommer ursprungligen ur JUnit (unit-testning för Java) och har motsvarigheter även i t.ex. .NET (NUnit).
PHPUnit bör användas under hela utvecklingsfasen, för att förebygga märkliga beteenden och buggar. Det är ett paket som ingår i PEAR (PHP Extension and Application Repository), så det är väldigt lätt att installera.
Vi börjar lite enkelt med en entitetsklass, som ska hålla information om en produkt: (Product.php)
<?php
class Product {
private $name;
private $price;
function __construct($productName, $productPrice) {
$this->name = $productName;
$this->price = $productPrice;
}
public function getName() { return $this->name; }
public function getPrice() { return $this->price; }
public function copy() {
$productCopy = new Product($this->name, $this->price);
return $productCopy;
}
public function increasePrice($amount) {
$this->price = $amount;
}
public function rename($name) {
$this->name = $name;
}
}
Klassen är enkelt att förstå, så nu måste vi testa den för att se att den fungerar som vi har tänkt! Då skapar vi en test-klass som ärver från PHPUnit's basklass PHPUnit_TestCase: (TestProduct.php)
<?php
require_once("Product.php");
require_once("PHPUnit.php");
class TestProduct extends PHPUnit_TestCase {
private $product;
function __construct($name) {
$this->PHPUnit_TestCase($name);
}
function setUp() {
$this->product = new Product("Produkt 1", 400);
}
function tearDown() {
unset($this->product);
}
function testCopy() {
$productCopy = $this->product->copy();
$this->assertEquals($productCopy, $this->product);
}
function testIncreasePrice() {
$initialPrice = $this->product->getPrice();
$newPrice = $initialPrice + 99;
$this->product->increasePrice(99);
$this->assertEquals($newPrice, $this->product->getPrice());
}
function testRename() {
$newName = "Produkt 1.1";
$this->product->rename($newName);
$this->assertTrue($newName == $this->product->getName());
}
}
Då var test-klassen klar, nu ska vi bara se till att köra testet också! (Test.php)
<?php
require_once("TestProduct.php");
require_once("PHPUnit.php");
$testsuite = new PHPUnit_TestSuite("TestProduct");
$result = PHPUnit::run($testsuite);
echo $result->toHTML();
Om man kör i skalläge, och inte via webbläsare, anropar man "$result->toString()" istället för "->toHTML()".
Utskriften ger:
TestCase TestProduct->testCopy() passed
TestCase TestProduct->testRename() passed
TestCase TestProduct->testIncreasePrice() failed: expected 499, actual 99 in /home/user/tester/TestProduct.php:30
Hm. Någonting är alltså fel med increasePrice()-metoden;
public function increasePrice($amount) {
$this->price = $amount;
}
Ah! I metoden ersätts priset med argumentet som skickas till metoden, den lägger inte till värdet. Metoden bör se ut så här:
public function increasePrice($amount) {
$this->price += $amount;
}
Vi kör filen Test.php igen, och bör då få utskriften:
TestCase TestProduct->testCopy() passed
TestCase TestProduct->testIncreasePrice() passed
TestCase TestProduct->testRename() passed
Jag tycker att PHPUnit är ett utmärkt verktyg för att testa sin kod, man slipper mycket manuell testning och arbetet flödar på i ett bra tempo. Hoppas att någon finner informationen intressant och att det leder till bättre programmering! Jag funderar på om jag ska skriva ihop någonting om cachning i PHP också, finns det intresse för det?
Med vänliga,