W jednym z poprzednich wpisów przedstawiałem instrukcję instalacji PHPUnit oraz Xdebug w naszym środowisku. Dzisiaj przedstawię sposób konfiguracji Zend Framework, aby możliwe było testowanie aplikacji.

Po stworzeniu nowej aplikacji Zend Framework z wykorzystaniem Zend_Tool otrzymamy standardową strukturę poszczególnych elementów aplikacji, wśród których można między innymi znaleźć folder “tests”, który zawierał będzie elementy takie, jak na poniższym zrzucie ekranu.

Zawartość folderu tests po instalacji aplikacji ZFNiestety nie będzie to zbyt dużą pomocą przy rozpoczęciu prac związanych z testowaniem naszej aplikacji, ponieważ zarówno oba pliki bootstrap.php, jak i phpunit.xml są puste. Jak więc rozpocząć?

Pierwszym krokiem będzie stworzenie odpowiedniej zawartości pliku phpunit.xml, który zawiera wszelkie niezbędne informacje dla PHPUnit na temat naszej aplikacji. W moim przypadku wygląda on następująco:

<phpunit bootstrap="./application/bootstrap.php" colors="true">
  <testsuite name="SmartGroupTest">
    <directory>./</directory>
  </testsuite>

  <filter>
    <whitelist>
      <directory suffix=".php">../application/</directory>
      <exclude>
        <directory suffix=".phtml">../application/</directory>
        <file>../application/Bootstrap.php</file>
        <file>../application/controllers/ErrorController.php</file>
      </exclude>
    </whitelist>
  </filter>

  <logging>
    <log type="coverage-html" target="./log/report" charset="UTF-8"
       yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" />
    <log type="testdox" target="./log/testdox.html" />
  </logging>
</phpunit>

W pierwszej linii pliku definiujemy miejsce, gdzie znajduje się plik bootstrap.php naszej paczki testów dla aplikacji (domyślnie jest to ./application/bootstrap.php).

Kolejny krok to stworzenie gałęzi o nazwie “testsuite”, która jest paczką zawierającą informację o naszych testach. W podstawowej wersji, takiej jak jest przedstawiona w tym wpisie wprowadzamy informację dotyczącą nazwę paczki testów oraz zakres jej działania. W związku z tym, że chcemy testować całą aplikację wprowadzamy:

<directory>./</directory>

Kolejny krok to zdefiniowanie filtrów dla testów. W naszym przypadku wystarczające będzie zdefiniowanie sekcji whitelist, gdzie wskazujemy lokalizacje i/lub typy plików, które mają być uwzględnione przez narzędzie mierzące stopień pokrycia testami naszego kodu. Jak widać w powyższym pliku xml pod uwagę brana jest zawartość folderu application, a dokładnie pliki php (dzieje się to poprzez określenie atrybutu suffix). Jednak czy na pewno wszystko co jest plikiem php i znajduje się w /application chcemy uwzględnić. Ja zdecydowałem się wyłączyć z testów wszystkie pliki widoków (.phtml) znajdujące się w folderze /application oraz dwa pliki: Bootstrap.php oraz ErroController.php.

Gdy już mamy zdefiniowane filtry, pozostaje nam tylko ustawić odpowiednie opcje dla raportowania i logowania. Poniższym wpisem ustawiamy, że chcemy otrzymać informację o pokryciu kodu w formie plików html, wskazujemy gdzie ma zostać zapisany raport (./log/report), rodzaj kodowania, czy ma zostać wykorzystana biblioteka yui (Yahoo! User Interface Library) i czy mają zostać wyróżniane odpowiednimi stylami poszczególne elementy raportu. Ostatnie dwie wartości wskazują poziom poniżej którego pokrycie kodu testami ma być oznaczone jako niskie (mniej niż 50%), oraz wartość powyżej której będzie oznaczone jako wysokie (więcej niż 80%). Oczywiście wartość pomiędzy powyższymi zostanie oznaczona jako średnie pokrycie testami (wartość od 50% do 80%). Całość znajduje się poniżej:

<log type="coverage-html" target="./log/report" charset="UTF-8"
       yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" />

Na tym etapie możemy już dokonać wstępnego testu, czy stworzyliśmy prawidłowo plik konfiguracyjny. W tym celu w pliku “./application/bootstrap.php” w folderze tests wprowadźmy następujący kod:

<?php 
echo 'Jestem plikiem bootstrap'; 
die;

Po zapisaniu zmian przechodzimy do konsoli (Start -> Uruchom -> wpisuemy “cmd” -> Enter) i przechodzimy do folderu tests naszej aplikacji. Wprowadzamy tam polecenie:

phpunit --configuration phpunit.xml

i po naciśnięciu Enter powinien w konsoli pojawić się napis: “Jestem plikiem bootstrap”. Jeżeli tak się nie stanie – oznaczać to będzie, że został popełniony błąd w pliku phpunit.xml.

Pora więc na wprowadzenie właściwych informacji dla tego pliku. Nic prostszego – plik ten powinien bowiem zawierać informacje (nie wszystkie) dokładnie takie jak plik index.php aplikacji, konkretnie:

// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath( 'library'),
    get_include_path()
)));

/** Zend_Application */
require_once 'library/Zend/Application.php';

Jedyne o czym musimy pamiętać w przypadku powyższego kodu to ustawienie odpowiednich ścieżek zarówno dla folderu aplikacji (linia 3), ścieżki dla folderu bibliotek (linia 11), jak również dla includowanego pliku Application w linii 16.

Gdy wprowadzimy już te zmiany wydawać by się mogło, że możemy uruchomić testy, co powinno nam zwrócić informację, że uruchomienie testów zakończyło się pomyślnie, z czego uruchomiono 0 testów (bo przecież jeszcze nic nie napisaliśmy). Ku naszemu zaskoczeniu pojawi się jednak komunikat:

PHP Fatal error:  Uncaught exception 'PHPUnit_Framework_Exception' with message 'Neither
"SmartGroupTest.php" nor "SmartGroupTest.php" could be opened.' in 
D:\PHP\pear\PHPUnit\Util\Skeleton\Test.php:100

Skąd taki dziwny komunikat? O jaki plik SmartGroupTest.php może chodzić? Wydaje się dość dziwna powyższa wiadomość, lecz jej przyczyna jest dość prosta. Gdy nie ma żadnych testów, PHPUnit próbuje jeszcze znaleźć plik o tożsamej nazwie jak nasz testsuite. Nie przejmujemy się tym jednak i możemy kontynuować dalej konfigurację ZF dla testów.

Następnym elementem będzie stworzenie klasy, która będzie odpowiedzialna za inicjalizację całej aplikacji za każdym razem, gdy będziemy uruchamiać test. W tym celu stworzę plik SmartGroupTestCase.php w folderze /tests/application, który będzie zawierał następujący kod:

require_once '../library/Zend/Test/PHPUnit/SmartGroupTestCase.php';

class SmartGroupTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
  /** * @var Zend_Application */
  protected $application;

  public function setUp() {
    $this->bootstrap = array( $this, 'appBootstrap' );
    parent::setUp();
  }

  public function appBootstrap() {
    $this->application = new Zend_Application(APPLICATION_ENV,
                                   APPLICATION_PATH . '/configs/application.ini' );
    $this->application->bootstrap();
    }
}

Klasa ta dziedziczy po Zend_Test_PHPUnit_ControllerTestCase, więc wykorzystamy możliwość użycia metody setUp, która to jest wywoływana przed każdym testem. W klasie tej stworzymy instancję naszej aplikacji. W pierszej linii metody setUp tworzymy instancję bootstrap’a poprzez wywołanie metody appBootstrap, która tworzy obiekt Zend_Application z wczytanymi danymi z pliku konfiguracyjnego i na tej instancji wywołuję metodę bootstrap().
Nie można zapomnieć o wywołaniu “parent::setUp()”, aby na pewno zostały wywołane elementy tej metody z klasy nadrzędnej.

Modernizujemy jeszcze plik /tests/application/bootstrap.php i includujemy w nim stworzoną naszą klasę:

require_once 'SmartGroupTestCase.php';

W tym momencie możemy już przystąpić do pisania pierwszego testu. Dla potrzeb wpisu stworzyłem klasę User ze statyczną metodą “getNumberOfItems()”, która zwraca wartość liczbową. Dla tej klasy stworzyłem następujący test:

class UserTest extends SmartGroupTestCase {

  public function testCanGetNumberOfItems() {
    $numberOfItems = User::getNumberOfItems();
    $this->assertTrue( is_numeric( $numberOfItems ) );
  }
}

Jak widać klasa UserTest dziedziczy po naszej klasie SmartGroupTestCase. Zawiera ona jedną metodę testową, która sprawdza czy zwrócona wartość jest liczbą. Uruchamiamy więc test i otrzymujemy:

\htdocs\smartgroupApp\tests>phpunit --configuration phpunit.xml
PHPUnit 3.6.4 by Sebastian Bergmann.

Configuration read from \htdocs\smartgroupApp\tests\phpunit.xml

.

Time: 5 seconds, Memory: 11.25Mb

OK (1 test, 1 assertion)
Generating code coverage report, this may take a moment.

Wszystko więc działa jak należy. W kolejnym wpisie przedstawię, jak skonfigurować IDE Jetbrains PhpStorm dla potrzeb PHPUnit.

PHPUnit i Zend Framework
Tagged on:                         

Leave a Reply

Your email address will not be published. Required fields are marked *

Social Widgets powered by AB-WebLog.com.