webForumDet fria alternativet

Att testa sin kod (PHP)

Webbutvecklingur Webbrelaterade artiklar

4 svar · 4 387 visningar · startad av SPiN

SPiNMedlem sedan mars 20007 896 inlägg
#1

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,

jmeMedlem sedan maj 20012 237 inlägg
#2

Tummen upp. Bra initiativ. Har nu ett tag använt PHPUnit. Tidigare har jag kört med JUnit på jobbet.

Det kan till en början vara lite svårt att verkligen fatta, hur mycket unit tester kan bidra med. Har själv säkert inte uppfattat allt ännu.

Det kan kännas trögt att skriva tester till varje funktion men det belönas verkligen då en unit test rapporterar om ett fel i en funktion som nyligen ändrats och som innan dess legat orört i 3 år.

Sedan skall man ju skriva testerna INNAN man skriver innehållet i den funktion man vill testa. ;) Vem orkar skriva unit tester till en klass som gjort 5 år sedan och som kanske innehåller femtioelva funktioner.

Avancerade inlägg, språk som språk, är alltid välkomna! Orkar du skriva om caching med PHP så kommer iaf jag att läsa den med stort intresse.

SPiNMedlem sedan mars 20007 896 inlägg
#3

Tack. :)

Sedan skall man ju skriva testerna INNAN man skriver innehållet i den funktion man vill testa.

Inte nödvändigtvis, det du menar nu är TDD - Test-Driven Development. Att man skriver tester utifrån vad klassen och dess metoder ska åstadkomma - så skriver man metoderna utefter det. PHPUnit är ett bra verktyg för både och, dock. :)

Avancerade inlägg, språk som språk, är alltid välkomna! Orkar du skriva om caching med PHP så kommer iaf jag att läsa den med stort intresse.

Då kommer jag antagligen att skriva det. Men det blir senare till kvällen i så fall. :)

jmeMedlem sedan maj 20012 237 inlägg
#4

Återigen, ett utmärkt förslag av SPiN. Vad vore riktigt roligt, är om flera wf-medlemmar skulle våga skriva egna artiklar/inlägg angånde valfritt ämne om den kan tänkas ge nåt till såväl nybörjare som mer erfarna. Extra roligt vore ju givetvis om alla kunde bidra med sådant, som artikelfattaren kanske glömde att nämna. Sedan kan väl alla hålla med om att en passande ton bör hållas så att ingen i onödan håller sig för att skriva.

Jag kan tänka mig att försöka skriva nåt lämpligt, just inom PHP. Vågar dock ännu inte lova. ;)

EDIT: Jag skulle kunna tänka mig skriva lite om hur man kommer igång med Zend Framework ifall det finns intresse för det.

SPiNMedlem sedan mars 20007 896 inlägg
#5

Zend Framework är ett utmärkt ramverk, och roligt att arbeta med - jag skulle gärna läsa om din syn på det och hur du använder det! :)

(För tydlighetens skull tycker jag att vi håller det i olika trådar - mitt cachnings-inlägg placerar jag i en ny tråd.)

127 ms totalt · 3 externa anrop · v20260731065814-full.29ac60f6
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
125 ms — hämta tråd, inlägg och bilagor (db)