Tworząc różnego rodzaju komponenty, najczęściej w formie klas dążymy do tego, aby implementowane rozwiązania zachowywały się poprawnie w każdej, możliwej do zaistnienia sytuacji. Doskonałym narzędziem na drodze ku stworzeniu bardziej niezawodnego kodu, są testy jednostkowe (unit tests).

testy jednostkowe

Unit tests umożliwiają przeprowadzenie weryfikacji poprawnego funkcjonowania konkretnych klas, ich metod lub funkcji – zatem przynależą do grupy testów białej skrzynki (white box). W metodyce programowania zwinnego (agile software development) są one doskonałą metodą dokumentacji poszczególnych modułów aplikacji.
Programiści piszą testy jednostkowe równolegle z komponentem dla którego są przeznaczone. Choć takie podejście wydłuża czas pracy, to w ostatecznym rozrachunku przynosi sporo korzyści. Moduły są bowiem mniej błędogenne, a ich działanie cechuje się większą niezawodnością. Poprzez wprowadzoną automatyzację oszczędzamy godziny, które poświęcilibyśmy na przeprowadzanie testów ręcznie i nanoszenie ewentualnych poprawek.

narzędzia do testów

Dla programistów PHP istnieją na rynku gotowe rozwiązania. Wśród nich pozwolę sobie wymienić PHPUnit oraz SimpleTest. Oczywiście nic nie stoi na przeszkodzie, by samemu spróbować stworzyć własny komponent do przeprowadzania testów. Potrzebna jest tylko odrobina czasu i chęci, oraz zaznajomienie się z pojęciem asercji, o której miałem już okazję napisać parę słów TUTAJ. Omawiane przeze mnie zagadnienie postaram się wyjaśnić z wykorzystaniem biblioteki SimpleTest.

simpletest

Klasa testowa – Maths będzie bardzo prosta. Jej jedyna metoda, zwróci TRUE, jeżeli iloraz dwóch liczb jest większy od zera. W przeciwnym wypadku – FALSE. Spójrzmy więc na jej deklarację.

class Maths {

	public function IsPositive ($first,$second) {

		if (($first/$second)>0)
			return true;

	}

}

Jako, że test piszemy równocześnie, zatem zobaczmy jak może wyglądać:

// klasa testujaca dziedziczy po UnitTestCase
class TestMaths extends UnitTestCase {

	// wolana przed wykonaniem testow
	public function setUp() {

		$this->maths = new Maths();

	}

	// wolana po zakonczeniu wszytskich testow
	public function tearDown () {

		unset($this->maths);

	}

	// metoda testowa, gdyz zawiera prefiks test
	public function testIsPositive () {

		for ($i=0;$i<100;$i++)
			// sprawdzamy czy metoda klasy Maths
			// zwraca zawsze jakas wartosc
			$this->assertnotNull(
				$this->maths->IsPositive(rand(-10,10),rand(-10,10))
			);

	}

}

Powyższa klasa musi dziedziczyć po UnitTestCase. Metoda setUp() jest wywoływana przed wykonaniem jakichkolwiek testów (czyli wszystkich metod które zaczynają się przedrostkiem test), a tearDown() po ich zakończeniu. Brakuje nam uruchomienia przedstawionego kodu.

require_once(dirname(__FILE__) . '/simpletest/autorun.php');

require_once 'Maths.php';
require_once 'TestMaths.php';
// tworzymy nowa grupe testow
$test = new GroupTest('Moje testy');
// dodajemy testowanie naszej klasy
$test->addTestCase(new TestMaths());
// uruchamiamy test
$test->run(new HtmlReporter());

Na wyjściu otrzymujemy:

error

Zapomnieliśmy o fakcie, iż nie wolno dzielić przez zero, oraz o zwracaniu wartości FALSE jeśli iloraz jest mniejszy lub równy zero. Wprowadzamy więc poprawki.

class Maths {

	public function IsPositive ($first,$second) {

		if ($second===0)
			return 0;
		if (($first/$second)>0)
			return true;
		else
			return false;

	}

}

Ponowne uruchomienie testu daje wyczekiwany rezultat. Wszystko funkcjonuje poprawnie.

error

Na koniec prezentuję opis najważniejszych metod klasy UnitTestCase, bez znajomości których ciężko wyobrazić sobie efektywne pisanie unit tests:

  • assertTrue($a)$a musi być prawdą (np. 1,true,12,’a')
  • assertFalse($a)$a musi być fałszem (np. 0,false,”)
  • assertNull($a)$a musi być NULL’em
  • assertNotNull($a)$a nie może być NULL’em
  • assertEqual($a,$b)$a i $b muszą być sobie równe, lecz nie koniecznie tego samego typu

To tylko krótki wstęp możliwości oferowanych przez SimpleTest. Zainteresowanych odsyłam do dokumentacji, którą znajdziecie TUTAJ.

Pozostaw Odpowiedź