SlideShare a Scribd company logo
1 of 47
Download to read offline
Testování prakticky
@ProchazkaFilip
Co si povíme
- troška teorie
- nette/tester
- mockery/mockery
- testování proti síti
- integrační testy
- codeception/codeception
- selenium
Troška teorie
- co testovat
- že to funguje
- že to nefunguje (když nemá)
- jak testovat
- unit testy
- integrační testy
- akceptační testy
- selenium (high level akceptační testy)
- Test Driven Development (red, green, refactor)
- Behaviour Driven Development
nette/tester
tester: motivace
$obj = new Math;
$result = $obj->add(1, 2);
var_dump($result);
tester: motivace
$obj = new Math;
$result = $obj->add(1, 2);
Assert::same(3, $result);
tester: tests/bootstrap.php
require __DIR__ . '/../vendor/autoload.php';
TesterEnvironment::setup();
date_default_timezone_set('Europe/Prague');
tester: tests/math/add.phpt
require __DIR__ . '/../bootstrap.php';
$obj = new Math;
$result = $obj->add(1, 2);
Assert::same(3, $result);
tester: TesterAssert
Assert::same($expected, $actual);
Assert::equal($expected, $actual);
Assert::contains($needle, $actual);
Assert::true($value);
Assert::false($value);
Assert::type($type, $value);
// ...
tester: TesterAssert
$obj = new Math();
Assert::exception(function() use ($obj) {
$obj->divide(2, 0);
}, InvalidArgumentException::class, 'Cannot divide by zero');
tester: TestCase
class SomeTest extends TesterTestCase {
function setUp() { }
function tearDown() { }
function testOne() {
Assert::same(......);
}
}
(new SomeTest)->run();
tester: TestCase @throws
/**
* @throws InvalidArgumentException
*/
public function testOne()
{
// ...
}
tester: TestCase @dataProvider
public function dataLoop() {
return [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
}
/** @dataProvider dataLoop */
public function testLoop($a, $b, $c) {
// ...
}
tester: TestCase @dataProvider
public function dataLoop() {
yield [1, 2, 3],
yield [4, 5, 6],
yield [7, 8, 9],
}
/** @dataProvider dataLoop */
public function testLoop($a, $b, $c) {
// ...
}
tester: metadata
<?php
/**
* @testCase
*/
require __DIR__ . '/../bootstrap.php';
class SomeTest extends TesterTestCase {
_____ ___ ___ _____ ___ ___
|_ _/ __)( __/_ _/ __)| _ )
|_| ___ /___) |_| ___ |_|_ v1.6.1
PHP 7.0.0 | 'php-cgi' -n | 10 threads
........s................F.........
-- FAILED: tests/greeting.phpt
Failed: 'Hello John' should be
... 'Hi John'
in src/Framework/Assert.php(370)
in src/Framework/Assert.php(52) TesterAssert::fail()
in tests/greeting.phpt(6) TesterAssert::same()
FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)
tester: a další...
- data providery & multipliery (meta)
- skipování testů
- DomQuery na testování HTML & XML
- file mock
- zámky (aby se nemlátily paralelní testy)
- watch (automatické spouštění testů při změně kódu)
- generování code coverage
- podpora HHVM
mockery/mockery
mockery: testovaná třída
class Temperature {
function __construct(WeatherApi $weather);
function average() {
$total = 0;
for ($i = 0; $i < 3 ;$i++) {
$total += $this->weather->readTemp();
}
return $total / 3;
}
mockery: test v Testeru
class TemperatureTest extends TesterTestCase {
function testGetsAverageTemperature() {
$service = Mockery::mock(WeatherApi::class);
$service->shouldReceive('readTemp')
->times(3)->andReturn(10, 12, 14);
$temperature = new Temperature($service);
Assert::same(12, $temperature->average());
}
mockery: test v Testeru
// ...
function tearDown() {
Mockery::close();
TesterEnvironment::$checkAssertions = FALSE;
}
Testování proti síti
Testování proti síti
- je to pomalé
- síť nemusí fungovat
- formát/protocol se může změnit
- služba může mít výpadky
Testování proti síti
try {
$result = $paymentProcessor->process($order);
} catch (OrdersCardPaymentException $e) {
if (preg_match('~SoapClient.*? Connection (refused|timed out)~', $e->getMessage())) {
TesterEnvironment::skip($msg);
}
throw $e;
}
Testování proti síti
- knihovna používá psr/http-message
- výchozí je guzzle klient
- testy používají fake klienta
- api se reálně zavolá pouze poprvé
- výsledek se uloží
- další běhy načítají odpovědi z disku
- když soubor smažu, request se provede
Ukázka v testech Kdyby/CsobPaymentGateway na githubu
Testování proti síti
- můžu (alespoň částečně) vyvíjet offline
- testy náhodně nepadají
- testy jsou rychlé
Integrační testy
Integrační testy
abstract class IntegrationTestCase extends TestCase {
function getService($type);
function getContainer() {}
function createContainer() {}
abstract class DbTestCase extends IntegrationTestCase {
function createContainer() {}
function setupDatabase(Connection $db);
Integrační testy: databáze
class CartTest extends IntegrationTestCase {
function testAdd() {
$cart = $this->getService(OrderCart::class);
$cart->addItem(10); // položka s id 10
$itemsInDb = $this->getService(Connection::class)
->query("SELECT id FROM order_items WHERE order = 1");
Assert::same([10], $itemsInDb);
}
Integrační testy: presentery
abstract class PresenterTestCase extends DbTestCase {
function usePresenter($name);
function runPresenterAction($action, ...);
function makeAjax();
function fakeCsrfProtection();
function fakeRedirectFromWebpay($action, ...);
function fakeRedirectFromCsob($action, ...);
Integrační testy: presentery
class HomepagePresenterTest extends PresenterTestCase {
function setUp() {
parent::setUp();
$this->usePresenter('Front:Homepage');
}
function testRenderDefault() {
$response = $this->runPresenterAction('default');
Assert::type(TextResponse::class, $response);
}
Integrační testy: komponenty
abstract class ComponentTestCase extends DbTestCase {
function attachToPresenter($component, ...);
function loadState($params, ...);
function runSignal($signal, $params, ...);
function makeAjax();
function assertRedirect($url);
function assertSnippets($snippets);
Integrační testy: komponenty
class CartControlTest extends ComponentTestCase {
function testCopyItem() {
$basket = $this->getService(Cart::class);
$item = $basket->addItem(719693);
$control = $this->getService(ICartControlFactory::class)->create();
$this->attachToPresenter($control);
$this->runSignal('copyItem', ['item' => $item->getId()]);
// ...
Integrační testy: komponenty
// ...
Assert::same(2, $item->getCount());
$this->assertSnippets([
'snippet-user-panel',
'snippet-review',
'snippet-control-cart' => '%A%Milka Tender oříšková%A%'
]);
codeception/codeception
codeception: tests/acceptance.suite.yml
class_name: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: 'http://127.0.0.1:8000'
- HelperAcceptance
codeception: simple test
$I = new AcceptanceTester($scenario);
$I->wantTo('see note can be successfully created');
$I->testLogin();
$I->amOnPage('/notes/create');
$I->fillField('Name', 'Example note');
$I->fillField('Text', 'Lorem ipsum');
$I->selectOption('Pad', 1);
$I->click('Save');
$I->see('Example note');
selenium
codeception: tests/acceptance.suite.yml
class_name: WebGuy
modules:
enabled:
- CodeceptionModuleWebDriver
- SeleniumTestsSupportHelperNetteSetup
config:
CodeceptionModuleWebDriver:
url: 'http://www.rohlik.l/'
browser: 'firefox'
codeception: cest test
class SigninCest {
function loginWithPassword(Homepage $homepage) {
$homepage->open();
$homepage->login('filip@prochazka.su', '12345678');
$homepage->seeThatUserIsLoggedIn();
}
codeception: page object
class Homepage extends FrontBasePage {
function open() {
$I = $this->tester;
$I->amOnUrl($this->app->url(':Front:Homepage:'));
}
codeception: page object
abstract class FrontBasePage {
function __construct(WebGuy $tester, NetteApp $app);
function login($email, $password) {
$form = new LoginForm($this->tester);
$form->openLoginDialog();
$form->login($email, $password);
}
codeception: page component
class LoginForm {
function __construct(WebGuy $tester);
function login($email, $password) {
$I = $this->tester;
$I->fillField(['name' => 'email'], $email);
$I->fillField(['name' => 'password'], $password);
$I->click(['css' => '.form-login form .login-btn button[type=submit]']);
}
codeception: nette app integration
class NetteApp {
function __construct(NetteSetup $netteSetup);
function url($fqa, $args = []);
function getService($type);
function getContainer();
Díky za pozornost!
Dotazy?
@ProchazkaFilip

More Related Content

What's hot

JUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationJUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationAnton Arhipov
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Wilson Su
 
Testes unitários de JS com Jasmine e Karma
Testes unitários de JS com Jasmine e KarmaTestes unitários de JS com Jasmine e Karma
Testes unitários de JS com Jasmine e KarmaDouglas Matoso
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2André Tapia
 
Java лаб13
Java лаб13Java лаб13
Java лаб13Enkhee99
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasJavier Eguiluz
 
from new class and dependency injection to PSR-11 and Auto-wiring
from new class and dependency injection to PSR-11 and Auto-wiringfrom new class and dependency injection to PSR-11 and Auto-wiring
from new class and dependency injection to PSR-11 and Auto-wiringMilad Arabi
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorFedor Lavrentyev
 
Rambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тестыRambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тестыRAMBLER&Co
 
変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhacomakoto tsuyuki
 
EJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSEJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSDarwin Durand
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Wilson Su
 
aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.bhavesh lande
 
RxSwift 예제로 감잡기
RxSwift 예제로 감잡기RxSwift 예제로 감잡기
RxSwift 예제로 감잡기Yongha Yoo
 

What's hot (20)

JUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentationJUG.ua 20170225 - Java bytecode instrumentation
JUG.ua 20170225 - Java bytecode instrumentation
 
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 3/8
 
Testes unitários de JS com Jasmine e Karma
Testes unitários de JS com Jasmine e KarmaTestes unitários de JS com Jasmine e Karma
Testes unitários de JS com Jasmine e Karma
 
Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2Aller plus loin avec Doctrine2
Aller plus loin avec Doctrine2
 
Iteratory
IteratoryIteratory
Iteratory
 
Silex al límite
Silex al límiteSilex al límite
Silex al límite
 
Java лаб13
Java лаб13Java лаб13
Java лаб13
 
Dwr实战
Dwr实战Dwr实战
Dwr实战
 
Proxy & CGLIB
Proxy & CGLIBProxy & CGLIB
Proxy & CGLIB
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
from new class and dependency injection to PSR-11 and Auto-wiring
from new class and dependency injection to PSR-11 and Auto-wiringfrom new class and dependency injection to PSR-11 and Auto-wiring
from new class and dependency injection to PSR-11 and Auto-wiring
 
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev FedorProgramming Java - Lection 03 - Classes - Lavrentyev Fedor
Programming Java - Lection 03 - Classes - Lavrentyev Fedor
 
Rambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тестыRambler.iOS #8: Чистые unit-тесты
Rambler.iOS #8: Чистые unit-тесты
 
変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco
 
EJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOSEJEMPLOS DESARROLLADOS
EJEMPLOS DESARROLLADOS
 
Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8Practical JavaScript Programming - Session 2/8
Practical JavaScript Programming - Session 2/8
 
Index2
Index2Index2
Index2
 
aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.aggregation and indexing with suitable example using MongoDB.
aggregation and indexing with suitable example using MongoDB.
 
RxSwift 예제로 감잡기
RxSwift 예제로 감잡기RxSwift 예제로 감잡기
RxSwift 예제로 감잡기
 
Oop koncepti
Oop konceptiOop koncepti
Oop koncepti
 

Viewers also liked

Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocit
Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocitPetr Kadlec - Jak začít se Symfony a mít z toho dobrý pocit
Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocitKonference PHPlive
 
Symfony vs Nette vs Phalcon
Symfony vs Nette vs PhalconSymfony vs Nette vs Phalcon
Symfony vs Nette vs PhalconVojta Svoboda
 
Bishnu_cv_ (1).PDF
Bishnu_cv_ (1).PDFBishnu_cv_ (1).PDF
Bishnu_cv_ (1).PDFP BISHNU
 
Class 9 & 10 accounting_chapter_ten_class_ 24
Class 9 & 10 accounting_chapter_ten_class_ 24Class 9 & 10 accounting_chapter_ten_class_ 24
Class 9 & 10 accounting_chapter_ten_class_ 24Cambriannews
 
Career Builder Economic update (dec 2012)
Career Builder Economic update (dec 2012)Career Builder Economic update (dec 2012)
Career Builder Economic update (dec 2012)Jacob Rhoades
 
Sicherheit in Deutschland
Sicherheit in DeutschlandSicherheit in Deutschland
Sicherheit in DeutschlandUwe Gerstenberg
 
reference letter Laura B
reference letter Laura Breference letter Laura B
reference letter Laura BLaura Brown
 
Economic update (feb 2013)
Economic update (feb 2013)Economic update (feb 2013)
Economic update (feb 2013)Jacob Rhoades
 
Methodology scrum white board simulation
Methodology   scrum white board simulationMethodology   scrum white board simulation
Methodology scrum white board simulationJean-François Nguyen
 
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba46849a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684Tsholofelo Sello
 
Yoga tradicional
Yoga tradicionalYoga tradicional
Yoga tradicionalAruna Yoga
 
Case: apply Agile principles to front office credit analyst activity
Case: apply Agile principles to front office credit analyst activityCase: apply Agile principles to front office credit analyst activity
Case: apply Agile principles to front office credit analyst activityJean-François Nguyen
 
Climas y paisajes de la tierra(final)
Climas y paisajes de la tierra(final)Climas y paisajes de la tierra(final)
Climas y paisajes de la tierra(final)Carmen sb
 
Weather and climate
Weather and climateWeather and climate
Weather and climateCarmen sb
 
الخوف عند الاطفال
الخوف عند الاطفالالخوف عند الاطفال
الخوف عند الاطفالFaisal Aljassem
 
Pisos de vegetación en la isla de Tenerife
Pisos de vegetación en la isla de TenerifePisos de vegetación en la isla de Tenerife
Pisos de vegetación en la isla de TenerifeCarmen sb
 

Viewers also liked (20)

Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocit
Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocitPetr Kadlec - Jak začít se Symfony a mít z toho dobrý pocit
Petr Kadlec - Jak začít se Symfony a mít z toho dobrý pocit
 
Symfony vs Nette vs Phalcon
Symfony vs Nette vs PhalconSymfony vs Nette vs Phalcon
Symfony vs Nette vs Phalcon
 
Bishnu_cv_ (1).PDF
Bishnu_cv_ (1).PDFBishnu_cv_ (1).PDF
Bishnu_cv_ (1).PDF
 
Class 9 & 10 accounting_chapter_ten_class_ 24
Class 9 & 10 accounting_chapter_ten_class_ 24Class 9 & 10 accounting_chapter_ten_class_ 24
Class 9 & 10 accounting_chapter_ten_class_ 24
 
Career Builder Economic update (dec 2012)
Career Builder Economic update (dec 2012)Career Builder Economic update (dec 2012)
Career Builder Economic update (dec 2012)
 
2014-09-09 Rendering
2014-09-09 Rendering2014-09-09 Rendering
2014-09-09 Rendering
 
Sicherheit in Deutschland
Sicherheit in DeutschlandSicherheit in Deutschland
Sicherheit in Deutschland
 
reference letter Laura B
reference letter Laura Breference letter Laura B
reference letter Laura B
 
Economic update (feb 2013)
Economic update (feb 2013)Economic update (feb 2013)
Economic update (feb 2013)
 
CV-LuisIbanez
CV-LuisIbanezCV-LuisIbanez
CV-LuisIbanez
 
Methodology scrum white board simulation
Methodology   scrum white board simulationMethodology   scrum white board simulation
Methodology scrum white board simulation
 
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba46849a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684
9a0c6e_0f9ed3af9d1f4a9b8be036d3a1ba4684
 
C.V -updated
C.V -updatedC.V -updated
C.V -updated
 
Yoga tradicional
Yoga tradicionalYoga tradicional
Yoga tradicional
 
Case: apply Agile principles to front office credit analyst activity
Case: apply Agile principles to front office credit analyst activityCase: apply Agile principles to front office credit analyst activity
Case: apply Agile principles to front office credit analyst activity
 
Climas y paisajes de la tierra(final)
Climas y paisajes de la tierra(final)Climas y paisajes de la tierra(final)
Climas y paisajes de la tierra(final)
 
Weather and climate
Weather and climateWeather and climate
Weather and climate
 
الخوف عند الاطفال
الخوف عند الاطفالالخوف عند الاطفال
الخوف عند الاطفال
 
Riesgo psicisicial
Riesgo psicisicialRiesgo psicisicial
Riesgo psicisicial
 
Pisos de vegetación en la isla de Tenerife
Pisos de vegetación en la isla de TenerifePisos de vegetación en la isla de Tenerife
Pisos de vegetación en la isla de Tenerife
 

Filip Procházka - Testování prakticky

  • 2. Co si povíme - troška teorie - nette/tester - mockery/mockery - testování proti síti - integrační testy - codeception/codeception - selenium
  • 3. Troška teorie - co testovat - že to funguje - že to nefunguje (když nemá) - jak testovat - unit testy - integrační testy - akceptační testy - selenium (high level akceptační testy) - Test Driven Development (red, green, refactor) - Behaviour Driven Development
  • 4.
  • 6. tester: motivace $obj = new Math; $result = $obj->add(1, 2); var_dump($result);
  • 7. tester: motivace $obj = new Math; $result = $obj->add(1, 2); Assert::same(3, $result);
  • 8. tester: tests/bootstrap.php require __DIR__ . '/../vendor/autoload.php'; TesterEnvironment::setup(); date_default_timezone_set('Europe/Prague');
  • 9. tester: tests/math/add.phpt require __DIR__ . '/../bootstrap.php'; $obj = new Math; $result = $obj->add(1, 2); Assert::same(3, $result);
  • 10. tester: TesterAssert Assert::same($expected, $actual); Assert::equal($expected, $actual); Assert::contains($needle, $actual); Assert::true($value); Assert::false($value); Assert::type($type, $value); // ...
  • 11. tester: TesterAssert $obj = new Math(); Assert::exception(function() use ($obj) { $obj->divide(2, 0); }, InvalidArgumentException::class, 'Cannot divide by zero');
  • 12. tester: TestCase class SomeTest extends TesterTestCase { function setUp() { } function tearDown() { } function testOne() { Assert::same(......); } } (new SomeTest)->run();
  • 13. tester: TestCase @throws /** * @throws InvalidArgumentException */ public function testOne() { // ... }
  • 14. tester: TestCase @dataProvider public function dataLoop() { return [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]; } /** @dataProvider dataLoop */ public function testLoop($a, $b, $c) { // ... }
  • 15. tester: TestCase @dataProvider public function dataLoop() { yield [1, 2, 3], yield [4, 5, 6], yield [7, 8, 9], } /** @dataProvider dataLoop */ public function testLoop($a, $b, $c) { // ... }
  • 16. tester: metadata <?php /** * @testCase */ require __DIR__ . '/../bootstrap.php'; class SomeTest extends TesterTestCase {
  • 17. _____ ___ ___ _____ ___ ___ |_ _/ __)( __/_ _/ __)| _ ) |_| ___ /___) |_| ___ |_|_ v1.6.1 PHP 7.0.0 | 'php-cgi' -n | 10 threads ........s................F......... -- FAILED: tests/greeting.phpt Failed: 'Hello John' should be ... 'Hi John' in src/Framework/Assert.php(370) in src/Framework/Assert.php(52) TesterAssert::fail() in tests/greeting.phpt(6) TesterAssert::same() FAILURES! (35 tests, 1 failures, 1 skipped, 1.7 seconds)
  • 18. tester: a další... - data providery & multipliery (meta) - skipování testů - DomQuery na testování HTML & XML - file mock - zámky (aby se nemlátily paralelní testy) - watch (automatické spouštění testů při změně kódu) - generování code coverage - podpora HHVM
  • 20. mockery: testovaná třída class Temperature { function __construct(WeatherApi $weather); function average() { $total = 0; for ($i = 0; $i < 3 ;$i++) { $total += $this->weather->readTemp(); } return $total / 3; }
  • 21. mockery: test v Testeru class TemperatureTest extends TesterTestCase { function testGetsAverageTemperature() { $service = Mockery::mock(WeatherApi::class); $service->shouldReceive('readTemp') ->times(3)->andReturn(10, 12, 14); $temperature = new Temperature($service); Assert::same(12, $temperature->average()); }
  • 22. mockery: test v Testeru // ... function tearDown() { Mockery::close(); TesterEnvironment::$checkAssertions = FALSE; }
  • 24. Testování proti síti - je to pomalé - síť nemusí fungovat - formát/protocol se může změnit - služba může mít výpadky
  • 25. Testování proti síti try { $result = $paymentProcessor->process($order); } catch (OrdersCardPaymentException $e) { if (preg_match('~SoapClient.*? Connection (refused|timed out)~', $e->getMessage())) { TesterEnvironment::skip($msg); } throw $e; }
  • 26. Testování proti síti - knihovna používá psr/http-message - výchozí je guzzle klient - testy používají fake klienta - api se reálně zavolá pouze poprvé - výsledek se uloží - další běhy načítají odpovědi z disku - když soubor smažu, request se provede Ukázka v testech Kdyby/CsobPaymentGateway na githubu
  • 27. Testování proti síti - můžu (alespoň částečně) vyvíjet offline - testy náhodně nepadají - testy jsou rychlé
  • 29. Integrační testy abstract class IntegrationTestCase extends TestCase { function getService($type); function getContainer() {} function createContainer() {} abstract class DbTestCase extends IntegrationTestCase { function createContainer() {} function setupDatabase(Connection $db);
  • 30. Integrační testy: databáze class CartTest extends IntegrationTestCase { function testAdd() { $cart = $this->getService(OrderCart::class); $cart->addItem(10); // položka s id 10 $itemsInDb = $this->getService(Connection::class) ->query("SELECT id FROM order_items WHERE order = 1"); Assert::same([10], $itemsInDb); }
  • 31. Integrační testy: presentery abstract class PresenterTestCase extends DbTestCase { function usePresenter($name); function runPresenterAction($action, ...); function makeAjax(); function fakeCsrfProtection(); function fakeRedirectFromWebpay($action, ...); function fakeRedirectFromCsob($action, ...);
  • 32. Integrační testy: presentery class HomepagePresenterTest extends PresenterTestCase { function setUp() { parent::setUp(); $this->usePresenter('Front:Homepage'); } function testRenderDefault() { $response = $this->runPresenterAction('default'); Assert::type(TextResponse::class, $response); }
  • 33. Integrační testy: komponenty abstract class ComponentTestCase extends DbTestCase { function attachToPresenter($component, ...); function loadState($params, ...); function runSignal($signal, $params, ...); function makeAjax(); function assertRedirect($url); function assertSnippets($snippets);
  • 34. Integrační testy: komponenty class CartControlTest extends ComponentTestCase { function testCopyItem() { $basket = $this->getService(Cart::class); $item = $basket->addItem(719693); $control = $this->getService(ICartControlFactory::class)->create(); $this->attachToPresenter($control); $this->runSignal('copyItem', ['item' => $item->getId()]); // ...
  • 35. Integrační testy: komponenty // ... Assert::same(2, $item->getCount()); $this->assertSnippets([ 'snippet-user-panel', 'snippet-review', 'snippet-control-cart' => '%A%Milka Tender oříšková%A%' ]);
  • 37.
  • 38. codeception: tests/acceptance.suite.yml class_name: AcceptanceTester modules: enabled: - PhpBrowser: url: 'http://127.0.0.1:8000' - HelperAcceptance
  • 39. codeception: simple test $I = new AcceptanceTester($scenario); $I->wantTo('see note can be successfully created'); $I->testLogin(); $I->amOnPage('/notes/create'); $I->fillField('Name', 'Example note'); $I->fillField('Text', 'Lorem ipsum'); $I->selectOption('Pad', 1); $I->click('Save'); $I->see('Example note');
  • 41. codeception: tests/acceptance.suite.yml class_name: WebGuy modules: enabled: - CodeceptionModuleWebDriver - SeleniumTestsSupportHelperNetteSetup config: CodeceptionModuleWebDriver: url: 'http://www.rohlik.l/' browser: 'firefox'
  • 42. codeception: cest test class SigninCest { function loginWithPassword(Homepage $homepage) { $homepage->open(); $homepage->login('filip@prochazka.su', '12345678'); $homepage->seeThatUserIsLoggedIn(); }
  • 43. codeception: page object class Homepage extends FrontBasePage { function open() { $I = $this->tester; $I->amOnUrl($this->app->url(':Front:Homepage:')); }
  • 44. codeception: page object abstract class FrontBasePage { function __construct(WebGuy $tester, NetteApp $app); function login($email, $password) { $form = new LoginForm($this->tester); $form->openLoginDialog(); $form->login($email, $password); }
  • 45. codeception: page component class LoginForm { function __construct(WebGuy $tester); function login($email, $password) { $I = $this->tester; $I->fillField(['name' => 'email'], $email); $I->fillField(['name' => 'password'], $password); $I->click(['css' => '.form-login form .login-btn button[type=submit]']); }
  • 46. codeception: nette app integration class NetteApp { function __construct(NetteSetup $netteSetup); function url($fqa, $args = []); function getService($type); function getContainer();