Test unitari e pacchetti di terze parti. Mi burlo o no?

4

Mi sto solo abituando ai test unitari e sul mio nuovo progetto ho deciso di adottare un approccio TDD.

Il mio codice qui sotto è quello di testare la classe UserServices che è responsabile della creazione di un utente, eliminando un utente, controllando se un utente esiste ecc.

Sono sulla buona linea? Chiedo perché ovunque guardi discute di derisione e non posso fare a meno di pensare che dovrei prendere in giro predis (un pacchetto usato per interagire con Redis in PHP). Ma deriderlo sarebbe difficile dato che la mia classe si aspetta un'istanza di Predis.

Nel setup creo un utente fittizio su cui eseguire le azioni. Potrei aver bisogno di crearne più di uno, ma a questo punto uso solo quello. Sebbene ci siano metodi come createUser che avrebbero bisogno di creare un utente completamente nuovo.

<?php

namespace VoteMySnap\Tests;

class UserServicesTest extends \PHPUnit_Framework_TestCase
{
    const HOST = '127.0.0.1';
    const PORT = 6379
    const AUTH = NULL;

    public $predis;

    public function setUp()
    {
        $this->predis = new \PredisClient([
            'host' => HOST,
            'port' => PORT
        ]);

        /*
         * Create a dummy user
         */
        $dummyUser = [
            'user:1' => [
                'snapchat_username' => 'james16',
                'password' => 'somesecret',
                'email' => '[email protected]'
            ]
        ];

       /*
        * Insert user into Redis
        */ 
        $this->predis->hmSet(key($dummyUser), $dummyUser[key($dummyUser)]);
    }

    public function tearDown()
    {
        /*
         * Remove the dummy user
         */
        $this->predis->delete(key($dummyUser));
    }  
}

Sono sulla buona strada qui?

    
posta BugHunterUK 04.02.2016 - 15:02
fonte

3 risposte

2

Ho sempre seguito la massima che un test unitario mette alla prova una cosa e una sola cosa. Programmare in modo tale che ogni metodo faccia una cosa e una sola cosa, dovrebbe significare che puoi scrivere un test unitario per quel metodo abbastanza facilmente.

Se il tuo metodo richiama qualsiasi altro servizio o classe, allora dovresti prendere in giro quelli per cui il loro comportamento durante il test è completamente noto. PHPUnit consente di simulare classi comprese quelle nei pacchetti che si stanno utilizzando, ad es. PredisClient. Vorresti anche prendere in giro il metodo hmSet. Consiglierei di leggere quanto segue per ottenere una migliore comprensione di come PHPUnit fa questo.

link

Potresti anche voler rifattorizzare il tuo codice per istanziare PredisClient al di fuori della classe che stai testando (se non lo hai già fatto) e poi iniettarlo tramite il parametro costruttore in quanto ciò consente alla tua versione beffeggiata di essere facilmente iniettata. Cerca Iniezione di dipendenza per vedere come questo può aiutare!

    
risposta data 04.02.2016 - 17:14
fonte
0

In tutti i casi di Test unitario, devi definire cos'è un'unità. È poco pratico renderlo troppo piccolo e inutile renderlo troppo grande.

Martin Fowler dice di renderlo un corso, a volte (importante):

"I often take a bunch of closely related classes and treat them as a single unit"

Suppongo che intenda che un'unità per lui è una classe, ma a volte, se contiene dipendenze strettamente accoppiate, le considererà come parte dell'unità.

Puoi rendere i test delle unità difficili per te stesso, oppure puoi essere pragmatico e mantenere la vita facile. L'intero punto di test unitario è controllare se il tuo codice funziona. Quindi, se puoi includere questa dipendenza difficile da rimuovere nei tuoi test, puoi capire se alcuni errori sono dovuti all'oggetto dipendente o al tuo codice, e le esecuzioni di test sono molto veloci e non richiedono un'impostazione estesa ... quindi tieni in.

Se alcune di queste condizioni non sono vere, allora dovrai capire come deriderlo o ignorare i test unitari e mettere il broncio su tutti i tuoi sforzi nei test di integrazione (che devi comunque fare, i test unitari vanno solo un modo breve per creare un sistema corretto)

    
risposta data 04.02.2016 - 15:24
fonte
0

Uno dei principi su cui cerco di attenermi quando il test è Don 'Mock What You Do Own Own .

Quando utilizzi una libreria di terze parti, è probabile che non ti serva tutto questo, solo un piccolo sottoinsieme. Inoltre, potresti non volere che la semantica di quella libreria pervada la tua applicazione, poiché ciò che fa potrebbe essere espresso in termini leggermente diversi dalla tua parte.

Pertanto, avvolgere il componente esterno all'interno di una classe di adattatori. Esporre solo le funzionalità di cui si conosce la necessità dell'applicazione e fornire loro nomi coerenti con il resto dell'applicazione. Metti un'astrazione su quel wrapper in modo che possa essere facilmente sostituita con altre implementazioni nei test o altrove.

Test unitario le tue classi che consumano queste funzioni con lo stub del wrapper, ma test di integrazione se possibile il wrapper stesso rispetto al modulo reale di terze parti.

    
risposta data 10.02.2016 - 14:02
fonte

Leggi altre domande sui tag