W poprzednich postach z tej serii omówiłem następujące dwa tematy:
- Pisanie testów jednostkowych za pomocą PHPUnit, część 1: Konfiguracja. Poradnik jak zacząć pisać testy PHPUnit poprzez użycie podstawowego cache i metody setUp frameworka.
- Pisanie testów jednostkowych za pomocą PHPUnit, część 2: The Tear Down. Samouczek dotyczący pisania testów jednostkowych, które prawidłowo wykorzystują metody setup i tearDown PHPUnit.
Każdy z powyższych ma na celu dostarczenie podstaw do rozpoczęcia pisania bardzo podstawowych testów jednostkowych. Sprawy mogą stać się bardziej złożone, zwłaszcza gdy aplikacja lub projekt się rozrasta (ale to zawsze prawda, prawda?).
Ale aby upewnić się, że ktoś jest na to przygotowany, jest jeden końcowy komponent do testów jednostkowych, na którym powinniśmy się skupić, a jest nim zrozumienie pliku konfiguracyjnego PHPUnit XML (który mogłeś zobaczyć w innych projektach jako phpunit.xml).
Konfiguracja PHPUnit XML
W tym poście zamierzam skonfigurować prosty projekt, który używa PHPUnit, napiszę kilka testów, takich jak te, które już widzieliśmy, i wykorzystam plik konfiguracyjny do zautomatyzowania testowania.
Co więcej, zrobię co w mojej mocy, aby jak najlepiej wyjaśnić niezbędne części pliku konfiguracyjnego, tak abyś mógł je dołączyć do swojego następnego projektu.
1 Wycinanie plików
Przed przystąpieniem do pisania testowalnego kodu ważne jest, aby znać pliki, które będą potrzebne do uruchomienia procesu.
Oto mniej więcej jak organizujemy rzeczy od samego początku projektu:
- katalog do testów,
- plik phpunit.xml _
W końcu zobaczysz także:
- pliki składające się na projekt,
- testy weryfikujące te pliki.
W tym momencie jednak przyjrzyjmy się plikowi konfiguracyjnemu XML, a następnie spróbujmy automatycznie uruchomić PHPUnit bez żadnych innych parametrów.
2 Podstawy pliku konfiguracyjnego
Najpierw spójrzmy na podstawowy plik konfiguracyjny:
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
bootstrap="./tests/bootstrap.php"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite name="AcmeTests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"></log>
</logging>
</phpunit>
Teraz zrozumiemy, na co dokładnie patrzymy (poza prostym XML).
- phpjednostka. Węzeł nadrzędny wykonuje zwykłe zadanie definiowania schematu dla pliku XML, ale jest kilka innych komponentów, którymi się zajmujemy:
- backupGlobalne. W rzeczywistości jest to związane z adnotacją, którą możemy umieścić w naszym kodzie źródłowym. Globalne to coś, czego powinniśmy unikać w programowaniu zorientowanym obiektowo, ale jeśli zdecydujesz się użyć któregoś z nich lub będziesz musiał użyć któregoś z nich, wtedy powie to PHPUnit aby obsłużył wartości które są utrzymywane przez zmienne globalne (i da ci opcję przywrócenia ich). Generalnie zostawiam to bez zmian.
- bootstrap. Jest to opcjonalne, ale jeśli zdecydujesz się dołączyć inne pliki do swoich testów (np. wprowadzenie biblioteki symulacyjnej, części WordPressa lub biblioteki innej firmy), to wystarczy, że określisz lokalizację skryptu, który musi wykonać. Wyśmiewanie i wprowadzanie WordPressa wykracza poza zakres tego postu, ale prawdopodobnie przyjrzymy się temu w przyszłości, ponieważ jest to przydatne podczas testowania wtyczek. Na razie dołączę prosty autoloader, który zasadniczo dodaje wszystkie pliki w katalogu głównym katalogu projektu. Pełne źródło zostanie udostępnione później w tym poście.
- zabarwienie. Jeśli chcesz, aby konsola drukowała raport z twoich testów i robiła to za pomocą kolorów (aby ułatwić identyfikowanie ostrzeżeń, powiadomień, błędów itd.), ustaw to na true.
- Poniżej podano wszystkie wartości logiczne. Zalecam ustawienie ich na prawdziwe w przypadku najbardziej agresywnych możliwych raportów. W ten sposób nie ujdzie ci na sucho zwykłe prześlizgiwanie się powiadomień lub ostrzeżeń, martwiąc się tylko o błędy. Jest to bardziej ćwiczenie z jakości kodu niż cokolwiek innego.
- konwertuj błędy na wyjątki
- convertNoticesToExceptions
- konwertuj ostrzeżenia na wyjątki
- pakiety testowe składają się z kolekcji testów. Ponieważ dany projekt może mieć wiele testów, ważne jest, aby każdemu pakietowi nadać unikatową nazwę i odnieść się do właściwej ścieżki do grupy testów. W naszym przykładzie będziemy mieli tylko jeden zestaw testów i znajduje się on w katalogu testów.
- rejestrowanie to funkcja, która może być tak prosta, jak drukowanie danych do konsoli lub korzystanie z biblioteki innej firmy (takiej jak Clover) do generowania raportów, które pomagają w ciągłej integracji. Ponieważ nie omówiłem jeszcze tego ostatniego w żadnym z moich poprzednich postów, będziemy trzymać się konsoli jako naszej głównej metody wyjścia. Dlatego jedynym wyjściem logowania jest php ://stdout.
Biorąc to wszystko pod uwagę, nasz plik XML zawiera wszystko, czego PHPUnit potrzebuje do działania bez żadnych innych parametrów.
Pamiętaj jednak, że zanim przejdziesz do dalszej części tego artykułu, zakładam, że globalnie zainstalowałeś PHPUnit w swoim systemie za pomocą Composera. Jeśli nie, zapoznaj się z tym artykułem, ponieważ zawiera instrukcje, jak to zrobić.
Po zakończeniu możesz sprawdzić, czy PHPUnit jest zainstalowany, wpisując w terminalu następujące polecenie:
$ which phpunit
Powinieneś zobaczyć coś takiego:
Jeśli widzisz coś takiego jak powyżej, możesz uruchomić PHPUnit w dowolnym miejscu swojego systemu.
3 Plik Bootstrapa
Zanim przejdziemy dalej, napiszmy podstawowy plik bootstrap. Nazwiemy go bootstrap.php i umieścimy w naszym katalogu testów . Obejmuje to :
<?php
// This array has a single file but could whole the contents of an entire directory.
$files = [
dirname(__DIR__).'/AcmeCache.php',
];
foreach ($files as $file) {
if (file_exists($file)) {
require_once $file;
}
}
Jest to prosty „autoloader" (który z wahaniem nazywam tak, biorąc pod uwagę, że po prostu iteruje przez pliki i wymaga ich, ale działa dla naszych celów).
W tym momencie skonfigurujmy podstawowy test.
4 Podstawowy, nieudany test
Jeśli czytasz coś o programowaniu opartym na testach, prawdopodobnie usłyszysz o cyklu czerwony-zielony-powtórz. Dużo by było na ten temat do powiedzenia i polecam poczytać o tym, ale nie o to chodzi w tym wpisie.
Zamiast tego jesteśmy bardziej skupieni na pisaniu testów, które pasują do tego, co musimy zrobić, prawda? Mając to na uwadze, wykonajmy następujące czynności:
- utwórz katalog, z którego będziesz miał kilka podstawowych plików PHP, które przetestujemy,
- w katalogu głównym, utwórz również phpunit.xml i wypełnij go kodem udostępnionym wcześniej w tym poście
- utwórz katalog testów, w którym umieścimy nasze testy.
Teraz z Terminala zmień katalog na katalog projektu (którego wprawdzie na razie brakuje), a następnie po prostu uruchom php unit:
$ phpunit
Zakładając, że wszystko jest poprawnie skonfigurowane, powinieneś zobaczyć coś takiego:
Ponieważ nie mamy kodu ani testów, naturalnie zobaczymy powyższe dane wyjściowe, prawda? Napiszmy więc pojedynczy test, który zostanie wykonany (i zakończy się niepowodzeniem), ponieważ nie ma kodu do przetestowania.
Najpierw w katalogu testów utwórz plik o nazwie AcmeCacheTest.php. I niech zrobi coś prostego, jak utworzenie instancji obiektu pamięci podręcznej, który ostatecznie utworzymy.
<?php
namespace AcmeTests;
use PHPUnitFrameworkTestCase;
use AcmeAcmeCache;
class AcmeCacheTest extends TestCase
{
private $cache;
public function setUp()
{
$this->cache = new AcmeCache();
}
public function testCacheExists()
{
$this->assertNotNull($this->cache);
}
}
Przed uruchomieniem testu zwróć uwagę, że:
- Upewnij się, że używasz PHPUnitFrameworkTestCase
- I niech nasza klasa rozszerzy TestCase
To jest część tego, co sprawia, że korzystanie z PHPUnit jest tak łatwe. Gdy to zrobisz, uruchom następujący kod z katalogu głównego projektu:
$ phpunit
Następnie powinieneś zobaczyć następujące informacje:
Zauważ, że test zakończy się niepowodzeniem i powie ci, gdzie znaleziono problem, plik i wiersz.
Aby to naprawić, musimy napisać klasę:
<?php
namespace Acme;
class AcmeCache
{
private $duration;
public function __construct()
{
$this->duration = 43200;
}
public function setDuration(int $duration)
{
$this->duration = $duration;
}
public function getDuration(): int
{
return $this->duration;
}
}
4 Kilka podstawowych, zdających testów
Podstawowy test na zaliczenie (który będzie oparty na poprzednim kodzie) będzie zawierał:
- plik z przestrzenią nazw,
- będzie reprezentować prostą pamięć podręczną,
- zostanie automatycznie załadowany przez PHPUnit przy użyciu udostępnionego powyżej pliku bootstrap.php
- i będzie miał ustawiony czas trwania w swoim konstruktorze wraz z setterem i getterem dla wartości
Najpierw sprawdźmy, czy jesteśmy w stanie skonfigurować klasę i czy nie jest ona pusta. To trochę niepotrzebne twierdzenie, ponieważ wiemy, że będziemy mieć poprawnie utworzoną klasę, ale to wprowadza nas w rowek pisania testów:
<?php
namespace AcmeTests;
use PHPUnitFrameworkTestCase;
use AcmeAcmeCache;
class AcmeCacheTest extends TestCase
{
private $cache;
public function setUp()
{
$this->cache = new AcmeCache();
}
public function testCacheExists()
{
$this->assertNotNull($this->cache);
}
}
I uruchom test:
Następnie sprawdźmy, czy ustawiona jest domyślna wartość pamięci podręcznej:
<?php
namespace AcmeTests;
use PHPUnitFrameworkTestCase;
use AcmeAcmeCache;
class AcmeCacheTest extends TestCase
{
private $cache;
public function setUp()
{
$this->cache = new AcmeCache();
}
public function testCacheExists()
{
$this->assertNotNull($this->cache);
}
public function testDefaultCacheValue()
{
$this->assertSame(43200, $this->cache->getDuration());
}
}
Podobnie jak w poprzednim kroku, uruchom testy, a teraz powinieneś zobaczyć dwa pomyślne testy:
Na koniec przetestujmy, czy jesteśmy w stanie pomyślnie zmienić wartość:
<?php
namespace AcmeTests;
use PHPUnitFrameworkTestCase;
use AcmeAcmeCache;
class AcmeCacheTest extends TestCase
{
private $cache;
public function setUp()
{
$this->cache = new AcmeCache();
}
public function testCacheExists()
{
$this->assertNotNull($this->cache);
}
public function testDefaultCacheValue()
{
$this->assertSame(43200, $this->cache->getDuration());
}
public function testSetCustomDuration()
{
$duration = 4200;
$this->cache->setDuration($duration);
$this->assertSame($duration, $this->cache->getDuration());
}
}
I ostatnie trzy zaliczone testy:
I masz to:
- plik XML PHPUnit,
- prosty bootstrap,
- pojedyncza klasa z przestrzenią nazw,
- testy jednostkowe dla każdej metody klasy
To prawda, że jest to proste, ale to kładzie fundamenty pod o wiele więcej niż to, co wiele osób już robi ze swoimi testami.
Co więcej, daje ci coś, na czym możesz się oprzeć, gdy twoje kotlety testowe stają się silniejsze.
Czy jest więcej? (Zawsze ma rację?)
Na koniec, jeśli naprawdę chcesz zagłębić się w plik konfiguracyjny, możesz przeczytać szczegółowe wyjaśnienie tego podręcznika.
Zauważ jednak, że wszystko, co zostało opisane powyżej, ma być tym, czego potrzebujesz, aby rozpocząć konfigurowanie własnego pliku konfiguracyjnego PHPUnit XML.




