2024-05-16 22:54:30
  • Hello!
  • Whats ya doin?
  • ByeBye

[&]

18.224.70.238

Narzędzie PHPUnit

workshop: #25-phpunit-intro.html

Narzędzia do przeprowadzania Unit testów

PHPUnit - uruchamianie

Przygotowanie

  1. Dla narzędzia PHPUnit wymagany jest interpreter PHP (pobierz archiwum ZIP, wypakuj narzędzie *.phar oraz nadaj uprawnienia wykonywalne)

  2. Utwórz katalog do pracy, np. 25-phpunit oraz umieść tam pobierane narzędzia oraz wyniki pracy

  3. Zapoznaj się z listą dostępnych asercji oraz Skryptami do przetestowania

1 Zadania do wykonania testów

Zapoznaj się z zadaniami, następnie zaimplementuj Unit testy.

  1. mechanizm ładowania arkusza CSS oraz biblioteki JS przez metodę loadLib() - napisz i przetestuj (CaT, code & test)

  2. weryfikacja poprawnego generowania formularzy przez klasę FormBuilder - przetestuj i popraw (TaP, test & patch)

  3. moduł pobierania istniejącej strony HTML z Internetu uGet - napisz, przetestuj i popraw (CTF, code-test-fix)

  4. moduł przesyłania plików z zadaniami na Hosting uSend - napisz, przetestuj i popraw (CTF, code-test-fix)

  5. testy do własnej aplikacji - skonsultuj się z prowadzącym

2 Przygotowanie środowiska testowego

Poniższa struktura jest przykładowa - jeżeli czcisz nieporządek i rozgardiasz - możesz wrzucić wszystkie pliki do jednego katalogu.

/PHPUnit
  +--app	(pliki z kodem aplikacji)
  |    |--MojaApka.php
  |    \--Pakiet.php
  +--res	(katalog wyników testów)
  |    |--result-1.html
  |    \--result-1.xml
  +--tests	(katalog z testami i asercjami)
  |    |--MojaApkaTest.php
  |    \--PakietTest.php
  +--tools
  |    \-- phpunit.phar (uruchamiane narzędzie)
  phpunit.xml	(opcjonalny plik z ustawieniami narzędzia)
3 Uruchamianie testów

Wywołanie testów możliwe jest dla tego narzędzia na kilka sposobów:

  • Proste wywołanie pojedynczego testu; wyniki do terminala

    ./tools/phpunit.phar tests/MojaApkaTest.php
  • Wywołanie wszystkich testów z katalogu tests z przełącznikiem --colors kolorowania wyników w terminalu

    ./tools/phpunit.phar --colors tests
  • Wywołanie wszystkich testów z przełącznikiem --testdox generujacym wyniki do pliku XML

    ./tools/phpunit.phar --colors tests --testdox
  • Wywołanie pojedynczego testu z przełącznikiem --testdox-html generujacym wyniki do pliku HTML

    ./tools/phpunit.phar --colors tests/MojaApkaTest.php --testdox-html
  • Wywołanie testów z przełącznikiem --testdox-html res/wyniki.html generujacym wyniki do pliku w katalogu res/wyniki.html

    ./tools/phpunit.phar --colors tests --testdox-html res/wyniki.html
  • Wywołanie testów skonfigurowanych w pliku phpunit.xml*

    ./tools/phpunit.phar

* plik musi istnieć w katalogu głównym projektu, skąd wywołuje się narzędzie oraz posiadać następującą strukturę:

<?xml version="1.0" encoding="UTF-8" ?>
<phpunit colors="true"
	 stopOnFailure="false">
  <testsuites>
    <testsuite name="Nazwa-Testu">
      <directory>tests</directory>
      <file></file>
    </testsuite>
  </testsuites>
</phpunit>
4 Implementacja asercji

Przykładowa asercja:

<?php // Kod testów jednostkowych
use PHPUnit\Framework\TestCase;	// użyj biblioteki PHPUnit w tym skrypcie
require('app/lib-1.php');	// załącz plik z kodem do przetestowania
// 	klasa testująca Klasę powinna kończyć się słowem `Test`
class FormTest extends TestCase
{	// klasa musi dziedziczyć metody z klasy TestCase
  public function testDisplayEmptyForm()
  {	// pojedyncze testy zaczynają się słowem `test` po którym następuje nazwa testu
    $f = new Form("Testowy formularz");
    $form = $f->display();
    $formToCompare = "<form><h2>Testowy formularz</h2></form>";
    $this->assertEquals( $formToCompare, $form );
  }
  public function testDisplayFormAndControls()
  {
    $f = new Form("Testowy formularz");
    $label = '<label>Etykieta</label>';
    $input = '<input type="text" name="entry" />';
    $f->pack($label,$input);
    $form = $f->display();
    $formToCompare = "<form><h2>Testowy formularz</h2><label>Etykieta</label><input type="text" name="entry" /></form>";
    $this->assertEquals( $formToCompare, $form );
  }
}

Zaimplementuj oraz wykonaj testy i asercje dla pozostałych klas. Jeżeli trzeba - popraw powyższy kod.

Testy wymagają stworzenia nowych instancji oraz ich skasowania po teście*

Instancjonowanie klasy na rządanie testów

public function setUp() : void {
	$this->instance = new KlasaWymaganaDoTestow();
}

Destrukcja klasy

public function tearDown() : void {
	unset($this->instance);
}

*!!!UWAGA!!! Zapis metod Instancji i Destrukcji klasy musi być dokładnie taki, jak przedstawiono na w/w listingach.

5 Testowanie metod prywatnych

Testowanie prywatnych metod* wymaga użycia tzw. mechanizmu Refleksji (Reflection) dostępnego w wielu obiektowych językach programowania.

public function invokeMethod(&$object, $methodName, array $parameters = array())
{
	$reflection = new \ReflectionClass(get_class($object));
	$method = $reflection->getMethod($methodName);
	$method->setAccessible(true);

	return $method->invokeArgs($object, $parameters);
}

*!!!UWAGA!!! Zapis tzw. Refleksji dostępu do prywatnej metody musi być dokładnie taki, jak przedstawiono na w/w listingu.

Użycie Reflekcji

// testowanie publicznych metod
public function testMojaMetodaPubliczna(){
	$this->assertEquals( $wzorzec, $this->mojaMetodaPubliczna('parametr') );
}
// testowanie prywatnych metod z użyciem tzw. Refleksji
public function testMojaMetodaPrywatna(){
	$this->assertEquals( $wzorzec, $this->invokeMethod(
			$this->instance,
			'mojaMetodaPrywatna',
			['parametr']
		)
	);
6 Zadanie warsztatowe

Zadanie 1a

mechanizm ładowania arkusza CSS oraz biblioteki JS przez metodę loadLib() - napisz i przetestuj (CaT, code & test)

Zaimplementuj metodę loadLib(), której zadaniem jest renderowanie znaczników LINK oraz SCRIPT dla przykładowych kombinacji przedstawionych poniżej:

// przykładowe wyniki metody `loadLib()`
<link rel="stylesheet" href="ui/katalog/plik.css" />
<link rel="stylesheet" href="ui/katalog/plik.css?v=123" />
<script src="ui/katalog/plik.js" /></script>
<script src="ui/katalog/plik.js?v=123" /></script>

Deklaracja metody oraz jej wywołanie:

public function loadLib( $type, $filePath, $version=null ){}
...
loadLib('css','katalog/arkusz');
loadLib('js','katalog/biblioteka',['ver'=>123]);

Zadanie 1b

Rozszerz implementację metody oraz testów o obsługę:

// A/ test i metoda generująca dodatkowo atrybut media="print"
loadLib('css-prn','katalog/plik',['ver'=>123]);
// B/ test sprawdzający brak pliku - w tym przypadku test ma przejść pozytywnie

Podsumowanie

  1. Powinieneś umieć używać narzędzia dla PHP do Unit testów oraz jego asercji na przyszłotygodniowym sprawdzianie (na kartce).