Ahoj,
nikdy jsem netestoval a tak jsem se to rozhodl změnit. Testy jsem se rozhodl psát na již rozpracované aplikaci, takže psát kód pomocí TDD se zatím nechystám, protože musím pokrýt testy kód, který teď mám.
Přečetl jsem několik článků ohledně testování a na většinu otázek jsem dostal odpověď, ale stále mi nějaké zbývají.
1. Psát vždy integrační testy?
Když už jsem hotov se všemi unit testy, měl bych se poté vrhnout na testy integrační? Tedy, místo mocků předat skutečný objekt a otestovat, jestli i tak vše funguje? Je to proces, kterým musí projít každá (nebo alespoň většina) kvalitních aplikací?
2. Test s databází je test integrační nebo jednotkový?
Je mi známo, že jedním z vlastností unit testů je izolace a rychlost, což je test s databází přesně naopak, ale jedná se v příkladu níže již o test integrační?
class Ban {
private $database;
private $email;
public function __construct(Database $database, $email) {
$this->database = $database;
$this->email = $email;
}
public function is() {
return $this->hasBan();
}
private function hasBan() {
$query = "SELECT 1 FROM banned_users
WHERE user_id = (SELECT ID FROM users WHERE email = ?)
AND to_time - NOW() > 0";
return (bool)$this->database->query($query, $this->email)->fetch();
}
}
V tomto případě potřebuji databázi, abych něco ověřil, ale přijde mi, že se i přesto jedná o test jednotkový, protože stále testuji jednotku a to i když potřebuji databázi. Platí tedy vždy, že test s databází == integrační test nebo ne?
3. Testování výsledků, který podává databáze
Mám třídy, ve kterých jsou pouze dotazy, žádné podmínky nebo cykly. Měl bych i v tomto případě pro ně psát Unit/Integrační testy, abych zjistil jestli jsem napsal dotazy správně? Testování bych prováděl v testovácí databázi s testovacími daty a úklidem. Řekl bych, že bych měl, ale nejsem si na 100% jistý.
4. Rozdělit Unit testy od Integračních testů?
Měl bych zajistit, aby Unit testy byly v jiném adresáři než jsou integrační testy? Integrační testy přece jen trvají déle, takže bude mi k něčemu, pokud se budu snažit o rozdělení? Neboli - budu někdy potřebovat mít možnost ověřit pouze integrační testy bez unit testů a naopak?
5. Jak strukturovat testy?
Měl bych v adresáři testsvytvořit pod-adresáře, dle jmenných prostorů, které mé skutečné třídy používají nebo je rozdělit dle jiného uvážení?
6. Duplicita kódu když používám mocky
V některých případech testuji třídy, které potřebují stejné rozhraní. Tento opakující se mock se mi nechce stále dokola vytvářet, tak jsem si na něj vytvořil samotnou třídu, která vrací namockovaný objekt. Tuto třídu spokojeně používám na několika místech. Měl bych něco takového dělat nebo tam ty duplicity nechat a nestarat se o ně? Nicméně existují ještě další takové mocky(které mají stejné rohraní), které vyhazují výjimku nebo nesmí být nikdy zavolány, ale na ty již žádnou třídu nemám a také se mi párkrát opakují. Nelíbí se mi to, jak z toho ven?
7. Prověření všech případů
<?php
class InactiveState implements State {
private $user;
private $offlineState;
public function __construct(OfflineState $offlineState, User $user) {
$this->offlineState = $offlineState;
$this->user = $user;
}
public function is() {
if($this->offlineState->is())
return $this->isInactive();
return false;
}
private function isInactive() {
return $this->user->getLogoutReason() === IUserStorage::INACTIVITY;
}
}
Kód využívá třídu User, která je z Nette, OfflineState má rozhraní State a jedinou metodu is. Měl bych v tomto případě projít tímto procesem: Namockovat nejdřívě OfflineState tak, aby napřed vracel false a otestovat InactiveState jestli vrací false, dále třídu User a metodu getLogoutReason namockovat tak, aby vracela něco jiného než IUserStorage::INACTIVITY a OfflineState s metodou is nastavit na true a ověřit, jestli je výsledek také false? A projít takto všechny kombinace, které mohou nastat? Zdá se mi to složitý, ale nevím, zda je to potřeba nebo ne.
Omlouvám se za delší text, ale jsem v tomto začátečník a vše bych si rád ujasnil. Děkuji za jakékoliv vaše názory a odpovědi.