Devo testare la classe consumatrice o la classe che esegue la logica?

2

Ho uno scenario simile a questo:

public class VatCalculator
{
    public decimal GetValueWithVat(decimal value, decimal? vatRatePercentage)
    {
        if(vatRate == null)
        {
            return value;
        }

        return value * (1 + (vatRate / 100));
    }
}


public ReceiptGenerator
{
    private readonly VatCalculator _vatCalculator;

    public ReceiptGenerator(VatCalculator vatCalculator)
    {
        _vatCalculator = vatCalculator;
    }

    public Receipt GenerateReceipt(Item purchasedItem, decimal? vatRate)
    {
        var receipt = new Receipt();

        receipt.PriceBeforeVat = purchasedItem.Price
        receipt.PriceAfterVat = _vatCalculator.GetValueWithVat(purchasedItem.Price, vatRate)
    }
}

In questo caso, ho alcuni test di unità che vorrei scrivere, ad es.

  • Se non viene fornita alcuna aliquota IVA, il valore "Prezzo dopo IVA" deve essere uguale al prezzo dell'articolo acquistato.
  • Se viene fornita un'aliquota IVA, il valore "Prezzo Dopo IVA" deve essere regolato di conseguenza

La mia domanda è se dovrei scrivere questi test unitari a livello della classe ReceiptGenerator o della classe VatCalculator .

Se provo al livello di classe ReceiptGenerator ciò significa che ho test più duraturi; Il codice di GenerateReceipt può essere refactored, ad es. utilizzare un metodo privato o un'API e i test dovrebbero ancora passare senza modifiche. Ma questo mi sembra uno spazio troppo grande per un test unitario, la mia comprensione è che dovrebbe essere un test focalizzato molto granulare

Se eseguo il test al livello VatCalculator , posso utilizzare quella classe in altri utenti (ad esempio, se trasferisco la mia attività online, posso utilizzarla per fornire prezzi on-the-go per i clienti che navigano su un prodotto) senza dover testare i consumatori stessi.

    
posta FLSH 20.09.2016 - 12:10
fonte

4 risposte

3

Dovresti testare sia a VatCalculator sia a ReceiptGenerator level.

Nei test unitari per la classe VatCalculator , verifichi che l'aggiustamento corretto al prezzo specificato sia effettuato in base alla tariffa IVA specificata.

Nei test unitari per ReceiptGenerator , verifichi che lo scontrino mostri gli importi giusti, non importa quanto sciocco sia il risultato dato dalla tua classe di calcolo IVA. Se il calcolatore IVA che utilizzi nel test dice che il prezzo diventa negativo dopo aver aggiunto l'IVA, allora lo scontrino mostrerà meglio questo. Ciò dimostra che ReceiptGenerator utilizza effettivamente il calcolatore dell'IVA fornito e non tenta di eseguire il proprio calcolo.
Questi test dovrebbero non utilizzare la classe VatCalculator , ma piuttosto una versione di prova di quella classe in cui è possibile restituire risultati sciocchi e risultati plausibili.

Infine, avresti un test di integrazione (o anche di livello superiore) per dimostrare che le classi ReportGenerator e VatCalculator funzionano correttamente insieme.

    
risposta data 20.09.2016 - 12:38
fonte
0

C'è molta confusione intorno ai "test unitari". Il modo più semplice per pensarli è un'unità di lavoro, cioè un lavoro autonomo. Per "autocontenuto", voglio dire che i test unitari dovrebbero essere in grado di funzionare in parallelo, senza effetti collaterali, e quindi non si influenzano a vicenda.

Nel tuo caso, VatCalculator.GetValueWithVat è una funzione pura, quindi non c'è alcun vantaggio nel prenderlo in giro o testarlo da solo. Può essere testato in sicurezza come parte di altri test di unità. Essendo una pura funzione in una classe che non implementa un'interfaccia, potresti renderla static e potresti migliorare ReceiptGenerator iniettandola direttamente tramite Func<decimal, decimal?, decimal> nel costruttore di ReceiptGenerator .

Quindi prova sia GetValueWithVat che ReceiptGenerator nei tuoi test unitari.

L'unico altro punto da notare sul tuo codice è var receipt = new Receipt(); . Questo è un punto debole di accoppiamento stretto nel codice che potrebbe causare problemi in futuro. Faresti meglio a iniettare un'istanza di IReceiptFactory in ReceiptGenerator e creare istanze di Receipt tramite tale factory.

    
risposta data 20.09.2016 - 14:02
fonte
0

Il punto di un test unitario è verificare che ogni unità interessata funzioni in base al suo design (e implicitamente quindi alle sue specifiche).

Pertanto, sono necessari casi di test appropriati per ciascuno di:

  • VatCalculator::GetValueWithVat()
  • ReceiptGenerator::ReceiptGenerator()
  • ReceiptGenerator::GenerateReceipt()

Se non provi VatCalculator::GetValueWithVat() stand-alone, non puoi supporre che sia corretto quando lo si utilizza come parte del test di ReceiptGenerator::GenerateReceipt()

È accettato che alcuni di questi casi di test siano banali, ma anche test banali possono fallire!

    
risposta data 20.09.2016 - 16:31
fonte
-1

Entrambi.

Assicurati di testare ogni parte singolarmente; sono test unit , dopotutto. Questo ti permetterà di controllare che la logica su ogni parte sia corretta. Ti permetterà anche di scambiare le implementazioni e assicurarti che ogni parte funzioni ancora come previsto.

Avendo il ReceiptGenerator controlla se VatCalculator fa i suoi lavori non è richiesto, poiché hai testato il VatCalculator da solo. Ma vuoi assicurarti che ReceiptGenerator aggiunga e rimuova correttamente i prodotti dalla ricevuta, calcoli la modifica corretta, ecc.

    
risposta data 20.09.2016 - 12:40
fonte

Leggi altre domande sui tag