Testowanie
==========

> Note|Uwaga: Wparcie dla testowania opisane w tym rozdziale wymaga Yii w wersji 1.1 lub wyższej.
Nie oznacza to jednak, że nie możesz testować aplikacji utworzonej za pomocą Yii 1.0.x.  
Istnieje wiele świetnych frameworków testujących, które mogą posłużyć Ci w tym celu, takich
jak [PHPUnit](http://www.phpunit.de/), [SimpleTest](http://www.simpletest.org/).

Testowanie jest nieodzownym procesem podczas tworzenia oprogramowania.  

Bez względu na to, czy zdajemy sobie z tego sprawę, czy też nie, przeprowadzamy
testy cały czas w procesie tworzenia aplikacji internetowej. Na przykład, 
podczas pisania klasy w PHP, możemy używać instrukcji `echo` lub `die` 
w celu pokazania, że zaimplementowaliśmy metodę poprawnie. Podczas tworzenia 
strony zawierającej złożone formularze HTML, możemy spróbować wprowadzić trochę danych 
testowych aby upewnić się, że interakcja pomiędzy stroną a nami jest taka jakiej oczekujemy.
Bardziej zaawansowani programiści napiszą kod aby zautomatyzować wspomniany proces testowania,
w taki sposób, aby za każdym razem gdy występuje potrzeba przetestowania czegoś,
wywołać napisany kod i pozwolić komputerowi wykonać testy za nas. Takie postępowanie 
nazywamy *testami automatycznymi* i są one głównym tematem niniejszego rozdziału.

Wsparcie testów oferowane przez Yii to wsparcie dla *testów jednostkowych* oraz *testów funkcjonalnych*. 

Test jednostkowy weryfikuje czy pojedyncza jednostka kodu działa w oczekiwany sposób.
W obiektowo zorientowanym programowaniu, najbardziej podstawową jednostką kodu jest klasa. 
Tak więc test jednostkowy weryfikuje głównie to czy metody interfejsu klasy działają prawidłowo.
Oznacza to, że biorąc różne parametry wejściowe, test weryfikuje czy metoda zwraca oczekiwany rezultat.
Testy jednostkowe zazwyczaj są pisane przez ludzi, którzy tworzą klasę, która ma być testoswana.

Test funkcjonalny weryfikuje czy funkcjonalność (np. zarządzanie postami w systemie blogowym) 
działa jak należy. W porównaniu do testu jednostkowego, test funkcjonalny znajduje się na 
wyższym poziomie, ponieważ testowana funkcjonalność wykorzystuje wiele klas. 
Testy funkcjonalne pisane są zazwyczaj przez ludzi, którzy bardzo dobrze znają  
wymagania stawiane systemowi (mogą być to zarówno programiści jak i inżynierowie jakości).


Programowanie sterowanie testami (ang. TDD, Test-Driven Development)
--------------------------------------------------------------------

Poniżej przedstawimy cykle programowania w tak zwanym [programowaniu sterowanym testami (TDD)](http://en.wikipedia.org/wiki/Test-driven_development):

 1. Utwórz nowy test, który pokrywa zaimplementowaną funkcjonalność. Oczekuje się, 
 że test nie powiedzie się podczas pierwszego wywołania, ponieważ funkcjonalność ta dopiero zostanie zaimplementowana.
 2. Uruchom wszystkie testy i upewnij się, że nowy test nie powiódł się. 
 3. Napisz kod, tak aby nowy test powiódł się.
 4. Wywołaj wszystkie testy i upewnij się, że wszystkie powiodły się.
 5. Po poprawieniu kodu, który został nowo napisany i upewnij się, że wszystkie testy wciąż kończą się sukcesem.  

Powtarzaj kroki od 1 do 5 w celu kontynuowania implementacji funcjonalności. 

Konfiguracja środowiska testowego
---------------------------------

Wsparcie dla testów oferowane przez Yii wymaga [PHPUnit](http://www.phpunit.de/) 3.5+ 
oraz [Selenium Remote Control](http://seleniumhq.org/projects/remote-control/) 1.0+. 
Aby dowiedzieć się jak zainstalować PHPUnit oraz Slenium Remote Control, zajrzyj do ich dokumentacji.

Jeśli używasz komend konsoli `yiic webapp` w celu utworzenia nowej aplikacji Yii, 
wygeneruje ona nastepujące pliki i katalogi za nas do pisania i wykonywania nowych testów:

~~~
testdrive/
   protected/                zawiera chronione pliki aplikacji
      tests/                 zawiera testy dla aplikacji
         fixtures/           zawiera odprzęt testowania bazy danych
         functional/         zawiera testy funcjonalne
         unit/               zawiera testy jednostkowe
         report/             zawiera containing raporty pokrycia (ang. coverage reports)
         bootstrap.php       skrypt wykonywany na samym początku
         phpunit.xml         plik konfiguracyjny PHPUnit
         WebTestCase.php     klasa bazowa dla internetowych testów funkjonalnych 
~~~

Jak widać powyżej, nasz kod testujący będzie się znajdował głównie w trzech katalogach:
`fixtures`, `functional` oraz `unit`, a katalog `report` będzie używany do przechowywania 
wygenerowanych rapotów pokrycia.

Aby wywołać testy (zarówno testy jednostkowe jak i funkcjonalne), możemy wykonać następujące
instrukcje w oknie konsoli:

~~~
% cd testdrive/protected/tests
% phpunit functional/PostTest.php    // wykonuje pojedynczy test
% phpunit --verbose functional       // wykonuje wszystkie testy w katalogu 'functional'
% phpunit --coverage-html ./report unit
~~~

W powyższych przykładzie ostatnia komenda wykona wszystkie testy w katalogu `unit` 
i wygeneruje raport pokrycia kodu w katalogu `report`. Zauważ, że 
[rozszerzenie xdebug ](http://www.xdebug.org/) musi być zainstalowane i aktywowane 
w celu wygenerowania raportów pokrycia kodu.

Skrypt startowy testu
---------------------

Zobaczmy co można znaleźć w pliku `bootstrap.php`. Plik ten jest szególny ze względu
na to, że przypomina [skrypt wejściowy](/doc/guide/basics.entry) i jest on punktem startowym 
podczas wykonywania zestawu testów.

~~~
[php]
$yiit='path/to/yii/framework/yiit.php';
$config=dirname(__FILE__).'/../config/test.php';
require_once($yiit);
require_once(dirname(__FILE__).'/WebTestCase.php');
Yii::createWebApplication($config);
~~~

W powyższym kodzie, najpierw załączamy plik `yiit.php` z frameworku Yii, który inicjalizuje 
pewne zmienne globalne i dołącza wymagane klasy podstawowe klasy testów. Następnie 
tworzymy instancję aplikacji sieciowej używając pliku konfiguracyjnego `test.php`. 
Jeśli sprawdzimy `test.php`, powinniśmy zauważyć, że dziedziczy on z pliku konfiguracyjnego `main.php` 
i dodaje komponent aplikacji `fixture`, którego klasą jest [CDbFixtureManager]. 
Stałe składniki (ang. fixtures) opiszemy szczzegółowo w następnym rozdziale. 

~~~
[php]
return CMap::mergeArray(
	require(dirname(__FILE__).'/main.php'),
	array(
		'components'=>array(
			'fixture'=>array(
				'class'=>'system.test.CDbFixtureManager',
			),
			/* uncomment the following to provide test database connection
			'db'=>array(
				'connectionString'=>'DSN for test database',
			),
			*/
		),
	)
);
~~~

Jeśli wywołujemy testy, które używają bazy danych, powinniśmy dostarczyć testową 
bazę danych, tak aby wywołanie testu nie kolidowało z czynnościami wykonywanymi 
na produkcji czy też w środowisku deweloperskim. Aby tak się stało, musimy tylko 
odkomentować konfigurację `db` w powyższym kodzie i wypełnić właściwość `connectionString` 
wartością DSN (nazwa źródła danych) wskazującą na bazę testową.

Przy pomocy takiego skryptu startowego, podczas uruchamiania testów jednostkowych,
otrzymamy instancję aplikacji, która jest niemal identyczna z tą dostarczaną dla 
żądań sieciowych. Główna różnica polega na tym, że posiada ona menedżer zarządzania stałymi  
składnikami (ang. fixture manager) oraz używa bazę testową.

<div class="revision">$Id: test.overview.txt 2997 2011-02-23 13:51:40Z alexander.makarow $</div>