Robusní testovaní řadiču v nette

Ondris
Člen | 37
+
0
-

Ahoj,

začínám psát testy na jednu větší aplikaci v nette. Nechci spát jednotlivý testy jednotek, ale celkový testy řadičů. To znamená, že test by měl odeslat celý formulář a pak zkontrolovat, jestli se provedli všechny navazující úkony. Tuhle kontrolu bych rád prováděl v databázi. Slyšel jsem o http://docs.mockery.io/…example.html , ale radši bych se mu vyhnul, protože chci mít testy co „nejblíž reálnému použití“. Mám s tím, ale dva problémy:

<?php

declare(strict_types=1);

namespace App\Tests;

use Nette;
use Tester;
use Tester\Assert;

$container = require __DIR__ . '/../../../../../app/bootstrap.php';

/** @testCase */
class IssueWorkflowPresenterTest extends Tester\TestCase
{
    /** @var \Nette\Database\Context */
    private $database;

    private $presenterFactory;

    public function __construct(Nette\DI\Container $container)
    {
        $this->database = $container->getByType('\Nette\Database\Context');
        $this->presenterFactory = $container->getByType('Nette\Application\IPresenterFactory');
    }

    public function setUp() {
        $this->database->beginTransaction();
    }

    public function testSomething() {
        Assert::true(true);
    }

    public function tearDown() {
        $this->database->rollBack();

        parent::tearDown();
    }

}

$test = new IssueWorkflowPresenterTest($container);
$test->run();

Tento kód mi vyhodí chybu:
Nette\Database\ConnectionException
could not find driver

2. Zajímalo by mě, pokud při testování pracujete s databází, jak to řešíte? Zatím mám představu, že udělám bootstrap pro testy, v něm nastavím jiný config a tam bude jiná databáze. V ní bude připojená jiná databáze. Problémy ale jsou, že budu muset migrace spouštět na 2 databázemi. Pak ještě se bude muset vytvořit nějaká výchozí sada dat. Teď když to píšu, tak to nezní jak tolik práce, ale přece jen by mě zajímali vaše zkušenosti.

chemix
Moderator | 1310
+
0
-

Na tohle ma David Matejka nekolik povidani. V mangowebu udelali mangotester ktery prave ulehcuje tyto integracni testu a resi si databazi (chces ji mit pro kazdy test “cistou”)

Co pouzivas za db driver? Orm?
Jakou databazi pouzivas?

h4kuna
Člen | 741
+
+3
-

Během následujícího týdne vývojáři z čsfd vydají balíček/nástroj na tento případ testování.

Editoval h4kuna (11. 5. 2019 18:13)

Petr Parolek
Člen | 458
+
-1
-

používám velmi dlouho https://github.com/…ik/testbench a naprostá spokojenost

Ondris
Člen | 37
+
0
-

Používáme databází mysql + doctrinu, občas když je někde problém s výkonností, tak použijeme nette database.

Jinak díky v pondělí vyzkouším tyto dva balíčky:
https://github.com/…ik/testbench
https://github.com/…mango-tester

@h4kuna Pokud jsem po vydání toho balíčku hodíš odkaz, tak budu rád.

Ondris
Člen | 37
+
0
-

Pořád i s těmi knihovnami mi to skončí na chybě:

Nette\Database\ConnectionException
could not find driver

Přitom stránky jako takový normálně fungují. config zatím používám stejný pro web i testy. Nevíte někdo v čem může být chyba?

h4kuna
Člen | 741
+
0
-

@Ondris Tak je to venku DatabaseReplicator

Cílem tohoto nástroje je připravit kopii databáze pro test. Není potřeba používat zámky a transakce. Opravdu ta kopie je jen pro jeden test. Použití v testech je je jednoduché a vyžaduje dvě volání. Na začátku testu nebo v metodě setUp() je potřeba zavolat $database->create() co ti vrátí instanci tvého connection ukazující na novou databázi a na konci testu $database->drop(). Více v readme. Nástroj je rok v interním provozu.

Vnitřní fungování je následující, vytvoří se zdrojová databáze ze souboru/ů na disku, nadále je jen pro čtení. Ze souboru/ů se dělá md5 hash a tím se poznává zda je zdrojová databáze aktuální. A při každém požádání se z ní udělá kopie.

Bacha zajímavost v čsfd během testů se vyrobí cca 250 databází. Postgres to umí kopírovat během mžiku.

Rozšíření pro nette je tady

Celkově to má pár ale:

  • není implementovaná žádná veřejná databázová vrstva, protože v čsfd je unikátní, klidně pošli PR, v readme je postup jak toho docílit, bude to vyžadovat vlastní tvorbu
  • v praxi není otestovaná podpora pro mysql, protože v čsfd je postgres
  • testnul jsem to pro nette 3, nicméně zatím primární podpora je pro nette 2.4

Jak to nainstalovat, předpokládám že budeš chtít nette rozšířenímysql

composer require --dev pmgdev/database-replicator-nette

Pro mysql je větev, kde testy prochází nicméně to opravdu není otestovaný v provozu.
V composer.json pod řádek "pmgdev/database-replicator-nette": "^0.1.0" přidej "pmgdev/database-replicator": "dev-mysql as 0.1.x-dev" a spusť composer update pmgdev/database-replicator

V neonu bude potřeba ještě podstrčit službě databaseReplicator.command třídu PmgDev\DatabaseReplicator\Database\Mysql\Command

services:
	- PmgDev\DatabaseReplicator\Database\Mysql\CommandFactory
	databaseReplicator.command:
		create: @PmgDev\DatabaseReplicator\Database\Mysql\CommandFactory::create(@databaseReplicator.admin)

Bude ti hlásit, aby jsi doplnil cestu na svůj sql soubor, kde je zapsaný schéma databáze.

Otestovat si to můžeš vytažením přes container

$database = $container->getService('databaseReplicator.test_db.database'); // test_db v názvu je vzato z readme rozšíření
$database->create();

Snad jsem na nic nezapomněl.

Editoval h4kuna (20. 5. 2019 10:05)

Mysteria
Člen | 797
+
0
-

Osobně používám taky přístup pro každý test vlastní databáze. Nepoužívám tedy žádné rozšíření, protože si myslím, že na těch asi 25 řádků to opravdu není potřeba, ale v setUp metodě vygeneruju náhodný název databáze, z SQL skriptu ji vytvořím a vložím testovací data a EntityManageru přes ReflectionObject změním název databáze. V tearDown pak jenom databázi smažu. Výhodou je, že díky tomu mohou testy běžet paralerně, takže není problém s rychlostí.