Sto discutendo un po 'di un argomento filosofico con uno dei miei colleghi riguardo al modo "giusto" di fare test unitari (in questo caso con PHPUnit). Sono dell'opinione che dovresti scrivere un metodo di prova nel test unitario per test che vuoi eseguire.
// Obviously a very contrived example!
class AdderTest extends TestCase
{
private $object = NULL;
protected function setup ()
{
$this -> object = new Adder ();
}
/**
* Test that 2 + 2 = 4
*/
public function testAddTwoTwoFour ()
{
$this -> assertEquals ($this -> object -> add (2, 2), 4);
}
/**
* Test that 2 + 3 = 5
*/
public function testAddTwoThreeFive ()
{
$this -> assertEquals ($this -> object -> add (2, 3), 5);
}
// and a bunch of other test cases
}
Il mio collega, tuttavia, pensa che sia meglio usare i fornitori di dati.
class AdderTest extends TestCase
{
private $object = NULL;
protected function setup ()
{
$this -> object = new Adder ();
}
/**
* Test add method
*
* @dataProvider addTestDataSource
*/
public function testAdd ($expected, $a, $b)
{
$this -> assertEquals ($this -> object -> add ($a, $b), $expected);
}
private function addTestDataSource ()
{
return [
[4, 2, 2], // Equivalent to testAddTwoTwoFour
[5, 2, 3], // Equivalent to testAddTwoThreeFive
];
}
}
La mia opinione personale è che il primo è migliore perché:
- Un metodo di test = 1 test, e ogni test unitario dovrebbe verificare uno e un solo fatto sull'unità in prova è corretto.
- I fallimenti sono facili da individuare perché il nome del metodo di prova fallito viene visualizzato
- Sono dell'opinione che i test unitari non debbano in nessun caso tentare di essere affatto "intelligenti" sulla base del fatto che un errore di test significa che il codice sotto test è sbagliato o il test stesso è sbagliato *, e più intelligente è il test, più è difficile escludere il test come fonte di errore. Dovresti eseguire il debug del codice, non i suoi test unitari.
- Nel caso di PHPUnit si basa su "magic" per funzionare (vale a dire PHPUnit che decodifica il tag @dataProvider)
- Se vuoi fare diversi tipi di asserzioni devi comunque scrivere altri metodi di test.
Il mio collega preferisce il suo metodo perché:
- Un test di unità per caso viola Non ripeti te stesso
- Un test di unità per caso incoraggia la copia e incolla, che è normalmente considerata una cattiva pratica
- Se l'interfaccia dell'unità in prova cambia, devi cambiare molti metodi di test (che possono essere soggetti a errori) mentre devi solo cambiare un metodo di test e un metodo di fornitura dati nel caso del provider di dati
- Il test unitario è molto più conciso e quindi più facile da capire.
Mentre io (naturalmente) penso di essere corretto, il mio collega solleva alcuni punti validi. Pensi che il mio approccio sia migliore o preferiresti il suo? Qual è il tuo ragionamento per la tua scelta, soprattutto se tale ragionamento non è negli elenchi che ho fornito sopra?
* presumendo che non ci siano bug nel framework dei test unitari, naturalmente!