Testování presenterů v Nette\Tester

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
radas
Člen | 221
+
0
-

Ahoj,
našel by se někdo, kdo by sem napsal pokud možno funkční kód, který by demonstroval testování presenteru pomocí nástroje Nette\Tester? Nejlépe testování

  • metody action…()
  • metody render…()
  • signálu handle…()
  • odeslaného formuláře

Rád bych pokryl aplikaci napsanou v Nette testy a rád bych využil právě Nette\Tester.

Díky moc

castamir
Člen | 629
+
0
-

Těď ti to asi moc nepomůže, ale když chvilu počkáš, tak @Hosiplan přislíbil, že udělá na poslední sobotě (tj. už za týden) přednášku právě na Nette\Tester.

radas
Člen | 221
+
0
-

To by bylo super. Bohužel se nebudu moct zúčastnit, tak doufejme, že bude videozáznam.

motorcb
Člen | 551
+
0
-

+1

David Grudl
Nette Core | 8147
+
0
-

Nejprve si vytvoř testovací bootstrap, který bude vytvářet DI kontejner.

Potom si vyrob presenter. Buď ručně vytvoříš instanci, nebo rovnou využiješ služeb PresenterFactory:

$presenterFactory = $container->getByType('Nette\Application\IPresenterFactory');
$presenter = $presenterFactory->createPresenter('Sign');

Asi bude vhodné vypnout kanonikalizaci, aby nevracel přesměrování:

$presenter->autoCanonicalize = FALSE;

a rovnou můžeme začít testovat:

// zobrazení stránky Sign:in metodou GET
$response = $presenter->run(new Request('Sign', 'GET', array('action' => 'in')));

Důležité je, že presenter počítá jen s jedním voláním run(), pro další requesty vytvoř nový presenter.

Ověříme, zda odpověď je skutečně šablona:

Assert::true( $response instanceof Nette\Application\Responses\TextResponse );
Assert::true( $response->getSource() instanceof Nette\Templating\ITemplate );

Necháme si vygenerovat výsledné HTML:

$html = (string) $response->getSource();

A třeba zkontrolujeme, zda se na stránce nacházejí formulářová políčka pro jméno a heslo:

$dom = Tester\DomQuery::fromHtml($html);

Assert::true( $dom->has('input[name="username"]') ); // zápis jako selektory v jQuery
Assert::true( $dom->has('input[name="password"]') );
radas
Člen | 221
+
0
-

Paráda, moc díky!
+1 za ten jQuery-like zápis :-)

radas
Člen | 221
+
0
-

Narazil jsem na problém s testováním presenteru, kde po odeslání formuláře a úspěšném ověření uživatele, má proběhnout přesměrování. Testuju tedy odpověď oproti Nette\Application\Responses\RedirectResponse takto:

public function testLoginFormSucceeded()
{
  $params = array(
    'action' => 'login',
    'do' => 'loginForm-submit'
  );

  $post = array(
    'e_mail' => 'somebody@domain.com',
    'password' => '***'
  );

  $request = new Request('Admin:Auth', Http\Request::POST, $params, $post);
  $response = $this->presenter->run($request);

  Assert::true($response instanceof Nette\Application\Responses\RedirectResponse);
}

Problém ale je, že do Assertu se vůbec nedojde, namísto toho v konzoli to skončí „Nette\Application\UI\InvalidLinkException: No route for Admin:Default:default()“

Přitom aplikace normálně funguje, po úspěšném přihlášení proběhne přesměrování.

Editoval radas (20. 4. 2013 21:53)

Filip Procházka
Moderator | 4668
+
0
-

Presenter při vytváření odkazu zkouší vytvořit instance cílového presenteru a volá nad ním reflexi. Musíš zajistit, aby presenter factory takový presenter mohla v pohodě vytvořit.

Také je třeba aby byl přístupný http request, který bude mít v sobě aktuální url, klidně i fake.

radas
Člen | 221
+
0
-

Díky, ale můžeš mě trošku nakopnout, jak na to?

Filip Procházka
Moderator | 4668
+
0
-
  • Mělo by stačit, aby šlo autoloadovat všechny classy presenterů a byl správně nastavený presenter factory mapping jako máš v configu
  • https://github.com/…tFactory.php
MzK
Člen | 127
+
0
-

Též mi testy vyhazovaly „Nette\Application\UI\InvalidLinkException: No route for Default:default()“, ale stačilo v setUp() nastavit $presenter->invalidLinkMode = $presenter::INVALID_LINK_SILENT;

Do _tests/bootstrap.php jsem zkoušel postupně toto:

<?php
//$container->router[] = new \Nette\Application\Routers\CliRouter('Default:default');
$container->router[] = new \Nette\Application\Routers\Route('<presenter>/<action>[/<id>].html[/p-<page>]', 'Default:default');
//$container->removeService("router");
//$container->addService("router", new Nette\Application\Routers\SimpleRouter());

if ($container->parameters['consoleMode']) {
	$container->removeService('httpRequest');
	$container->addService('httpRequest', function() {
		// Podle potreby muzeme pouzit nastaveni z configu nebo vzit z parametru prikazove radky, aj.
		$uri = new \Nette\Http\UrlScript();
		$uri->scheme = 'http';
		$uri->port = \Nette\Http\Url::$defaultPorts['http'];
		$uri->host = 'example.com';
		$uri->path = '/';
		$uri->canonicalize();
		$uri->path = \Nette\Utils\Strings::fixEncoding($uri->path);
		$uri->scriptPath = '/';
		return new \Nette\Http\Request($uri, array(), array(), array(), array(), array(), 'GET', null, null);
	});
}

//Set up router
$container->removeService("router");
$container->addService("router", new Nette\Application\Routers\SimpleRouter());
?>

ale bez výsledku, pořád jsem měl chybu „InvalidLinkException“

Edit: už to jde, chyba byla jinde. Do bootstrap stačilo přidat:

<?php
$container->router[] = new \Nette\Application\Routers\Route('<presenter>/<action>[/<id>].html[/p-<page>]', 'Default:default');
?>

Editoval MzK (25. 4. 2013 14:26)

radas
Člen | 221
+
0
-

Díky, potvrzuju, funguje. U mě stačilo do bootstrap.php (toho bootstrapu pro testy), přidat tento řádek:

$container->router[] = new Nette\Application\Routers\Route('<presenter>/<action>[/<id [0-9]+>]', 'Default:default');
sifik
Člen | 27
+
0
-

Mohl bych se zeptat, jak řešíte práva uživatelů? Tedy, zda-li má být uživatel přihlášen?

S čím souvisí – jak zacházet s redirecty?

Tedy pokud vám

$response = $presenter->run(new Request('Sign', 'GET', array('action' => 'in')));

vrátí RedirectResponse?

kedrigern
Člen | 102
+
0
-

#13 : viz https://forum.nette.org/…php-skrz-cli#… (ale mám obavu, že s aktualizací dev verze Nette se tam něco rozbilo – snad si najdu čas mrknout na to).

Honza Marek
Člen | 1664
+
0
-

Sepsal jsem svoje zkušenosti s testováním presenterů PHPUnitem.

sifik
Člen | 27
+
0
-

Shodneme se na tom, že to bude jednoduší testovat pomocí Selenia. :-)

Proto jsem vytvořil jednoduché rozšíření pro nette/tester, aby s ním bylo možné spouštet selenium testy.

  • Musel jsem udělat fork php webdriveru pro ovládání prohlížeče.