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
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();
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);
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();