it-swarm.it

Come fai a sapere cosa testare durante la scrittura di unit test?

Usando C #, ho bisogno di una classe chiamata User che abbia un nome utente, una password, un flag attivo, un nome, un cognome, un nome completo, ecc.

Dovrebbero esserci metodi per autenticare e salvare un utente. Scrivo solo un test per i metodi? E devo anche preoccuparmi di testare le proprietà in quanto sono getter e setter di .Net?

127
Mike Roosa

Molte ottime risposte a questo sono anche sulla mia domanda: " Inizio TDD - Sfide? Soluzioni? Consigli? "

Vorrei anche raccomandare di dare un'occhiata al mio post sul blog (che è stato in parte ispirato dalla mia domanda), ho avuto un buon feedback su questo. Vale a dire:

Non so da dove iniziare?

  • Ricominciare. Pensa solo a scrivere test quando scrivi un nuovo codice. Può essere una rielaborazione del vecchio codice o una funzionalità completamente nuova.
  • Inizia semplice. Non scappare e cercare di aggirare la testa in un framework di test oltre ad essere TDD-esque. Debug.Assert funziona bene. Usalo come punto di partenza. Non scherza con il tuo progetto né crea dipendenze.
  • Inizia positivo. Stai cercando di migliorare il tuo mestiere, sentirti bene. Ho visto molti sviluppatori là fuori che sono felici di ristagnare e non provare nuove cose per migliorarsi. Stai facendo la cosa giusta, ricordalo e ti aiuterà a non arrenderti.
  • Inizia pronto per una sfida. È abbastanza difficile iniziare a provare. Aspettati una sfida, ma ricorda: le sfide possono essere superate.

Prova solo ciò che ti aspetti

Ho avuto problemi reali quando ho iniziato perché ero costantemente seduto lì a cercare di capire ogni possibile problema che potesse verificarsi e quindi provare a provarlo e risolverlo. Questo è un modo rapido per avere mal di testa. I test dovrebbero essere un vero processo YAGNI. Se sai che c'è un problema, allora scrivi un test per questo. Altrimenti, non preoccuparti.

Prova solo una cosa

Ogni caso di test dovrebbe testare solo una cosa. Se ti capita mai di inserire "e" nel nome del test case, stai facendo qualcosa di sbagliato.

Spero che questo significhi che possiamo passare da "getter e setter" :)

130
Rob Cooper

Metti alla prova il tuo codice, non la lingua.

Un test unitario come:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

è utile solo se stai scrivendo un compilatore e c'è una possibilità diversa da zero che il tuo metodo instanceof non funzioni.

Non testare cose che puoi fare affidamento sulla lingua per far rispettare. Nel tuo caso, mi concentrerei sui tuoi metodi di autenticazione e di salvataggio - e scrivo test che assicurano che siano in grado di gestire i valori null in uno o tutti quei campi con grazia.

63
Tim Howland

Questo mi ha portato a test unitari e mi ha fatto molto piacere

Abbiamo appena iniziato a fare test di unità. Per molto tempo ho saputo che sarebbe stato bello iniziare a farlo, ma non avevo idea di come iniziare e, cosa più importante, cosa testare.

Quindi abbiamo dovuto riscrivere un codice importante nel nostro programma di contabilità. Questa parte è stata molto complessa in quanto ha coinvolto molti scenari diversi. La parte di cui sto parlando è un metodo per pagare le vendite e/o acquistare fatture già inserite nel sistema contabile.

Non sapevo come iniziare a codificarlo, poiché c'erano così tante diverse opzioni di pagamento. Una fattura potrebbe essere $ 100 ma il cliente ha trasferito solo $ 99. Forse hai inviato fatture di vendita a un cliente ma hai anche acquistato da quel cliente. Quindi l'hai venduto per $ 300 ma hai comprato per $ 100. Puoi aspettarti che il tuo cliente ti paghi $ 200 per saldare il saldo. E se vendessi per $ 500 ma il cliente ti pagasse solo $ 250?

Quindi ho avuto un problema molto complesso da risolvere con molte possibilità che uno scenario funzionasse perfettamente ma sarebbe sbagliato su un altro tipo di combinazione invocie/pagamento.

Qui è dove i test unitari sono venuti in soccorso.

Ho iniziato a scrivere (all'interno del codice di prova) un metodo per creare un elenco di fatture, sia per le vendite che per gli acquisti. Quindi ho scritto un secondo metodo per creare il pagamento effettivo. Normalmente un utente inserisce tali informazioni tramite un'interfaccia utente.

Quindi ho creato il primo TestMethod, testando un pagamento molto semplice di una singola fattura senza sconti di pagamento. Tutte le azioni nel sistema si verificherebbero quando un pagamento bancario viene salvato nel database. Come puoi vedere, ho creato una fattura, creato un pagamento (una transazione bancaria) e salvato la transazione su disco. Nelle mie affermazioni ho inserito quelli che dovrebbero essere i numeri corretti che finiscono nella transazione bancaria e nella fattura collegata. Controllo il numero di pagamenti, gli importi del pagamento, l'importo dello sconto e il saldo della fattura dopo la transazione.

Dopo l'esecuzione del test, andrei nel database e ricontrollerei se quello che mi aspettavo fosse lì.

Dopo Ho scritto il test, ho iniziato a scrivere il metodo di pagamento (parte della classe BankHeader). Nella codifica mi sono solo preoccupato del codice per eseguire il primo test. Non pensavo ancora agli altri scenari più complessi.

Ho eseguito il primo test, risolto un piccolo bug fino a quando il mio test sarebbe passato.

Quindi ho iniziato a scrivere il secondo test, questa volta lavorando con uno sconto sul pagamento. Dopo aver scritto il test ho modificato il metodo di pagamento per supportare gli sconti.

Durante la verifica della correttezza con uno sconto sul pagamento, ho anche testato il pagamento semplice. Entrambi i test dovrebbero passare ovviamente.

Poi mi sono avvicinato agli scenari più complessi.

1) Pensa a un nuovo scenario

2) Scrivi un test per quello scenario

3) Esegui quel singolo test per vedere se sarebbe passato

4) In caso contrario eseguirò il debug e modificherei il codice fino a quando non passerà.

5) Durante la modifica del codice ho continuato a eseguire tutti i test

È così che sono riuscito a creare il mio metodo di pagamento molto complesso. Senza test unitari non sapevo come iniziare la codifica, il problema sembrava travolgente. Con i test ho potuto iniziare con un metodo semplice ed estenderlo passo dopo passo con la certezza che gli scenari più semplici continuerebbero a funzionare.

Sono sicuro che l'uso del test unitario mi ha salvato alcuni giorni (o settimane) di codifica e garantisce più o meno la correttezza del mio metodo.

Se in seguito penso a un nuovo scenario, posso semplicemente aggiungerlo ai test per vedere se funziona o no. Altrimenti posso modificare il codice ma essere sicuro che gli altri scenari funzionino ancora correttamente. Ciò consentirà di risparmiare giorni e giorni nella fase di manutenzione e correzione degli errori.

Sì, anche il codice testato può ancora avere bug se un utente fa cose che non hai pensato o che gli ha impedito di fare

Di seguito sono riportati solo alcuni dei test che ho creato per testare il mio metodo di pagamento.

public class TestPayments
{
    InvoiceDiaryHeader invoiceHeader = null;
    InvoiceDiaryDetail invoiceDetail = null;
    BankCashDiaryHeader bankHeader = null;
    BankCashDiaryDetail bankDetail = null;



    public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
    {
        ......
        ......
    }

    public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
    {
       ......
       ......
       ......
    }


    [TestMethod]
    public void TestSingleSalesPaymentNoDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 1, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSingleSalesPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 2, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    [ExpectedException(typeof(ApplicationException))]
    public void TestDuplicateInvoiceNumber()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("100", true, 2, "01-09-2008"));
        list.Add(CreateSales("200", true, 2, "01-09-2008"));

        bankHeader = CreateMultiplePayments(list, 3, 300, 0);
        bankHeader.Save();
        Assert.Fail("expected an ApplicationException");
    }

    [TestMethod]
    public void TestMultipleSalesPaymentWithPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 11, "01-09-2008"));
        list.Add(CreateSales("400", true, 12, "02-09-2008"));
        list.Add(CreateSales("600", true, 13, "03-09-2008"));
        list.Add(CreateSales("25,40", true, 14, "04-09-2008"));

        bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
        Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);

        Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);

        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSettlement()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
        list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase

        bankHeader = CreateMultiplePayments(list, 22, 200, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
    }
38
eroijen

Se sono davvero banali, non preoccuparti dei test. Ad esempio, se sono implementati in questo modo;

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Se, d'altra parte, stai facendo qualcosa di intelligente (come crittografare e decrittografare la password nel getter/setter), allora prova.

13
Steve Cooper

La regola è che devi testare ogni pezzo di logica che scrivi. Se hai implementato alcune funzionalità specifiche nei getter e nei setter penso che valga la pena testarli. Se assegnano valori solo ad alcuni campi privati, non preoccuparti.

10
Slavo

Questa domanda sembra essere una questione di dove si disegna la linea su quali metodi vengono testati e quali no.

I setter e i getter per l'assegnazione del valore sono stati creati tenendo conto della coerenza e della crescita futura, e prevedendo che un po 'di tempo lungo il setter/getter potrebbe evolversi in operazioni più complesse. Avrebbe senso mettere in atto test unitari di tali metodi, anche per motivi di coerenza e crescita futura.

L'obiettivo principale è l'affidabilità del codice, soprattutto durante le modifiche per aggiungere funzionalità aggiuntive. Non sono a conoscenza del fatto che qualcuno sia mai stato licenziato per aver incluso setter/getter nella metodologia di test, ma sono certo che esistano persone che desideravano avere metodi testati che alla fine erano a conoscenza o che potevano ricordare erano semplici set/get wrapper, ma non era vero più a lungo il caso.

Forse un altro membro del team ha ampliato i metodi set/get per includere la logica che ora ha bisogno di essere testata ma non ha quindi creato i test. Ma ora il tuo codice chiama questi metodi e non sai che sono cambiati e hanno bisogno di test approfonditi, e i test che fai in fase di sviluppo e QA non innescano il difetto, ma i dati aziendali reali il primo giorno di rilascio lo fanno innescalo.

I due compagni di squadra ora discuteranno su chi ha lasciato cadere la palla e non è riuscito a mettere i test unitari quando il set/viene trasformato per includere la logica che può fallire ma non è coperta da un test unitario. Il compagno di squadra che originariamente ha scritto il set/get sarà più facile uscire da questo clean se i test sono stati implementati dal primo giorno sul set/get semplice.

La mia opinione è che alcuni minuti di "spreco" di tempo che coprono TUTTI i metodi con test unitari, anche banali, potrebbero risparmiare giorni di mal di testa lungo la strada e perdita di denaro/reputazione dell'azienda e perdita del lavoro di qualcuno.

E il fatto che tu abbia impacchettato metodi banali con unit test potrebbe essere visto da quel compagno di squadra junior quando cambiano i metodi banali in metodi non banali e li spinge ad aggiornare il test, e ora nessuno è nei guai perché il difetto era contenuto dal raggiungere la produzione.

Il modo in cui codifichiamo e la disciplina che può essere vista dal nostro codice possono aiutare gli altri.

6
Thomas Carlisle

Un'altra risposta canonica. Questo, credo, di Ron Jeffries:

Testa solo il codice su cui vuoi lavorare.

4
user9397

Codici davvero banali come getter e setter che non hanno un comportamento aggiuntivo rispetto all'impostazione di un campo privato sono eccessivi da testare. In 3.0 C # ha anche un po 'di zucchero sintattico in cui il compilatore si occupa del campo privato, quindi non è necessario programmarlo.

Di solito scrivo molti test molto semplici per verificare il comportamento che mi aspetto dalle mie lezioni. Anche se è roba semplice come aggiungere due numeri. Passo molto tra la scrittura di un semplice test e la scrittura di alcune righe di codice. La ragione di ciò è che poi posso cambiare il codice senza temere di aver rotto cose a cui non pensavo.

3
Mendelt

Dovresti testare tutto. In questo momento hai getter e setter, ma un giorno potresti cambiarli un po ', magari per fare validazione o qualcos'altro. I test che scrivi oggi verranno utilizzati domani per assicurarsi che tutto continui a funzionare normalmente. Quando scrivi test, dovresti dimenticare considerazioni come "in questo momento è banale". In un contesto agile o guidato dai test, è necessario testare assumendo il refactoring futuro. Inoltre, hai provato a inserire valori davvero strani come stringhe estremamente lunghe o altri contenuti "cattivi"? Beh, non dovresti ... mai dare per scontato che il tuo codice possa essere maltrattato in futuro.

Generalmente trovo che scrivere test utente estesi sia da un lato, estenuante. D'altra parte, anche se ti dà sempre preziose informazioni su come dovrebbe funzionare la tua applicazione e ti aiuta a gettare via ipotesi facili (e false) (come: il nome utente avrà sempre una lunghezza inferiore a 1000 caratteri).

3
Sklivvz

Per moduli semplici che possono finire in un toolkit o in un tipo di progetto open source, dovresti testare il più possibile includendo banali getter e setter. La cosa che devi tenere a mente è che generare un test unitario mentre scrivi un modulo particolare è abbastanza semplice e diretto. L'aggiunta di getter e setter è un codice minimo e può essere gestita senza pensarci troppo. Tuttavia, una volta che il codice viene inserito in un sistema più grande, questo ulteriore sforzo può proteggerti dalle modifiche nel sistema sottostante, come le modifiche al tipo in una classe base. Testare tutto è il modo migliore per avere una regressione completa.

3
Dirigible

Testare il codice del boilerplate è una perdita di tempo, ma come dice Slavo, se aggiungi un effetto collaterale ai tuoi getter/setter, dovresti scrivere un test per accompagnare quella funzionalità.

Se si sta eseguendo uno sviluppo basato su test, è necessario scrivere prima il contratto (ad es. L'interfaccia), quindi scrivere i test per esercitare quell'interfaccia che documenta i risultati/comportamento previsti. Quindi scrivi i tuoi metodi da soli, senza toccare il codice nei test unitari. Infine, prendi uno strumento di copertura del codice e assicurati che i tuoi test esercitino tutti i percorsi logici nel tuo codice.

3
warren_s

in generale, quando un metodo è definito solo per determinati valori, prova i valori su e oltre il bordo di ciò che è accettabile. In altre parole, assicurati che il tuo metodo faccia quello che dovrebbe fare, ma niente di più . Questo è importante, perché quando fallirai, vorrai fallire presto.

Nelle gerarchie ereditarie, assicurati di verificare la conformità LSP .

Testare getter e setter predefiniti non mi sembra molto utile, a meno che tu non abbia intenzione di fare qualche validazione in seguito.

2
Rik

bene se pensi che possa rompersi, scrivi un test per questo. Di solito non testare setter/getter, ma lasciami dire che ne fai uno per User.Name, che concatena nome e cognome, scrivo un test quindi se qualcuno cambia l'ordine per cognome e nome, almeno lo saprebbe ha cambiato qualcosa che è stato testato.

2
pmlarocque

La risposta canonica è "prova tutto ciò che può rompersi". Se sei sicuro che le proprietà non si romperanno, non testarle.

E una volta trovato qualcosa che si è rotto (trovi un bug), ovviamente significa che devi testarlo. Scrivi un test per riprodurre il bug, guardalo fallire, quindi correggi il bug, quindi guarda il test.

2
Eric Normand

Non fa male scrivere test unitari per i tuoi getter e setter. In questo momento, potrebbero semplicemente fare field get/sets sotto il cofano, ma in futuro potresti avere una logica di validazione o dipendenze tra proprietà che devono essere testate. È più facile scriverlo ora mentre ci stai pensando, poi ricordarti di modificarlo se mai fosse il momento.

2
Bob King

Idealmente, avresti fatto i test unitari mentre stavi scrivendo la lezione. Ecco come intendi farlo quando usi Test Driven Development. Aggiungete i test mentre implementate ciascun punto funzione, assicurandovi di coprire anche i casi Edge con test.

Scrivere i test in seguito è molto più doloroso, ma fattibile.

Ecco cosa farei nella tua posizione:

  1. Scrivi una serie base di test che testano la funzione principale.
  2. Ottieni NCover ed eseguilo sui tuoi test. La copertura del test sarà probabilmente intorno al 50% a questo punto.
  3. Continua ad aggiungere test che coprono le custodie Edge fino a ottenere una copertura di circa l'80% -90%

Questo dovrebbe darti una serie funzionante di unit test che fungeranno da buon buffer contro le regressioni.

L'unico problema con questo approccio è che il codice deve essere progettato per essere testabile in questo modo. Se hai commesso errori di accoppiamento all'inizio, non sarai in grado di ottenere una copertura elevata molto facilmente.

Questo è il motivo per cui è davvero importante scrivere i test prima di scrivere il codice. Ti costringe a scrivere codice che è liberamente accoppiato.

1
Simon Johnson

Rende il nostro codice migliore ... periodo!

Una cosa che noi sviluppatori di software dimentichiamo quando facciamo lo sviluppo guidato dai test è lo scopo dietro le nostre azioni. Se un test unitario viene scritto dopo che il codice di produzione è già in atto, il valore del test diminuisce (ma non viene completamente perso).

Nel vero spirito del unit testing, questi test non sono non principalmente lì per "testare" più del nostro codice; o per ottenere una copertura del codice migliore del 90% -100%. Questi sono tutti vantaggi collaterali della prima scrittura dei test. Il grande vantaggio è che il nostro codice di produzione finisce per essere scritto molto meglio a causa del processo naturale di TDD.

Per aiutare a comunicare meglio questa idea, potrebbe essere utile leggere quanto segue:

Teoria imperfetta dei test unitari
Sviluppo software mirato

Se riteniamo che l'atto di scrivere più unit test sia ciò che ci aiuta a ottenere un prodotto di qualità superiore, allora potremmo soffrire di un Cargo Cult di Test Driven Development.

1
Scott Saad

Non testare ovviamente il codice di lavoro (boilerplate). Quindi, se setter e getter sono solo "propertyvalue = value" e "return propertyvalue" non ha senso testarlo.

1
erlando

Anche get/set può avere conseguenze strane, a seconda di come sono state implementate, quindi dovrebbero essere trattati come metodi.

Ogni test di questi dovrà specificare una serie di parametri per le proprietà, definendo le proprietà accettabili e inaccettabili per garantire che le chiamate ritornino/falliscano nel modo previsto.

È inoltre necessario essere consapevoli dei gotcha di sicurezza, ad esempio un esempio di iniezione SQL, e testarli.

Quindi sì, devi preoccuparti di testare le proprietà.

1
CestLaGalere

Credo che sia sciocco testare getter e setter quando eseguono una semplice operazione. Personalmente non scrivo test unitari complessi per coprire qualsiasi modello di utilizzo. Provo a scrivere abbastanza test per assicurarmi di aver gestito il normale comportamento di esecuzione e quanti casi di errore riesco a pensare. Scriverò più unit test come risposta alle segnalazioni di bug. Uso il test unitario per garantire che il codice soddisfi i requisiti e per facilitare le modifiche future. Mi sento molto più disposto a cambiare codice quando so che se rompo qualcosa un test fallirà.

1
Andrei Savu

Mentre è possibile indovinare correttamente dove il codice deve essere testato, in genere penso che siano necessarie metriche per eseguire il backup di questa ipotesi. I test unitari a mio avviso vanno di pari passo con le metriche di copertura del codice.

Codice con molti test ma una piccola copertura non è stata ben testata. Detto questo, il codice con una copertura del 100% ma non testando i casi vari ed errori non è eccezionale.

Volete un equilibrio tra elevata copertura (minimo 90%) e dati di input variabili.

Ricordati di provare "immondizia"!

Inoltre, un test unitario non è un test unitario a meno che non verifichi un errore. I test unitari che non hanno asserzioni o sono contrassegnati con eccezioni note testeranno semplicemente che il codice non muore durante l'esecuzione!

È necessario progettare i test in modo che segnalino sempre guasti o dati imprevisti/indesiderati!

1
Ray Hayes

Scriverei un test per tutto ciò per cui stai scrivendo codice che è testabile al di fuori dell'interfaccia della GUI.

In genere, qualsiasi logica che scrivo che abbia una logica aziendale che inserisco in un altro livello o livello di logica aziendale.

Quindi scrivere test per tutto ciò che fa qualcosa è facile da fare.

Primo passaggio, scrivi un test unitario per ciascun metodo pubblico nel tuo "Livello di logica aziendale".

Se avessi una lezione come questa:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

La prima cosa che farei prima di scrivere qualsiasi codice sapendo che dovevo compiere queste azioni sarebbe iniziare a scrivere unit test.

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

Scrivi i tuoi test per convalidare il codice che hai scritto per fare qualcosa. Se stai iterando su una raccolta di cose e cambiando qualcosa su ognuna di esse, scrivi un test che fa la stessa cosa e asserisci che è realmente accaduto.

Ci sono molti altri approcci che puoi adottare, vale a dire Behavoir Driven Development (BDD), che è più coinvolto e non è un ottimo punto di partenza con le tue capacità di test delle unità.

Quindi, la morale della storia è, testare tutto ciò che fa qualcosa di cui potresti essere preoccupato, tenere i test unitari test di cose specifiche di piccole dimensioni, molti test sono buoni.

Mantieni la tua logica di business al di fuori del livello dell'interfaccia utente in modo da poter scrivere facilmente i test per loro e sarai bravo.

Consiglio TestDriven.Net o ReSharper poiché entrambi si integrano facilmente in Visual Studio.

1
Dean Poulin

Quando capisco i test unitari nel contesto dello sviluppo agile, Mike, sì, devi testare i getter e i setter (supponendo che siano pubblicamente visibili). L'intero concetto di unit test è testare l'unità software, che in questo caso è una classe, come scatola nera . Poiché i getter e i setter sono visibili esternamente, è necessario testarli insieme a Authenticate and Save.

1
Onorio Catenacci

Se i metodi Authenticate and Save utilizzano le proprietà, i test toccheranno indirettamente le proprietà. Finché le proprietà stanno solo fornendo accesso ai dati, non dovrebbero essere necessari test espliciti (a meno che non si stia andando per una copertura del 100%).

1
Tom Walker

Metterei alla prova i tuoi getter e setter. A seconda di chi sta scrivendo il codice, alcune persone cambiano il significato dei metodi getter/setter. Ho visto l'inizializzazione delle variabili e altre convalide come parte dei metodi getter. Per testare questo genere di cose, vorresti test unitari che coprono esplicitamente quel codice.

1
Peter Bernier

Personalmente "testerei tutto ciò che può rompersi" e il semplice getter (o anche le migliori proprietà automatiche) non si romperà. Non ho mai avuto una semplice dichiarazione di reso fallita e quindi non ho mai testato per loro. Se i getter hanno un calcolo al loro interno o qualche altra forma di affermazioni, aggiungerei sicuramente dei test per loro.

Personalmente uso Moq come un framework di oggetti finto e quindi verifico che il mio oggetto chiama gli oggetti circostanti come dovrebbe.

1
tronda

Devi coprire l'esecuzione di ogni metodo della classe con UT e controllare il valore di ritorno del metodo. Ciò include getter e setter, specialmente nel caso in cui i membri (proprietà) siano classi complesse, che richiede grande allocazione di memoria durante la loro inizializzazione. Chiama il setter con una stringa molto grande per esempio (o qualcosa con simboli greci) e controlla che il risultato sia corretto (non troncato, la codifica è buona ecc.)

Nel caso di numeri interi semplici che si applicano anche: cosa succede se si passa lungo anziché intero? Questo è il motivo per cui scrivi UT per :)

1
m_pGladiator

Il test di una classe dovrebbe verificare che:

  1. i metodi e le proprietà restituiscono i valori previsti
  2. Le eccezioni appropriate vengono generate quando viene fornito un argomento non valido
  3. Le interazioni tra la classe e altri oggetti si verificano come previsto quando viene chiamato un determinato metodo

Naturalmente se i getter e i setter non hanno una logica speciale, allora i test dei metodi Authenticate e Save dovrebbero coprirli, ma altrimenti dovrebbe essere scritto un test esplicativo

1
Crippledsmurf

Consiglierei di scrivere più test per i tuoi metodi Authenticate and Save. Oltre al caso di successo (in cui vengono forniti tutti i parametri, tutto è scritto correttamente, ecc.), È bene avere test per vari casi di errore (parametri errati o mancanti, connessioni al database non disponibili se applicabile, ecc.). Raccomando Pragmatic Unit Testing in C # with NUnit come riferimento.

Come altri hanno già affermato, i test unitari per getter e setter sono eccessivi, a meno che non vi sia una logica condizionale nei getter e nei setter.

1
Scott Lawrence

Non testerei l'effettiva impostazione delle proprietà. Sarei più preoccupato di come queste proprietà vengono popolate dal consumatore e di cosa le popolano. Con qualsiasi test, è necessario soppesare i rischi con i tempi/i costi dei test.

1
Bloodhound

Dovresti testare "ogni blocco di codice non banale" usando i test unitari per quanto possibile.

Se le tue proprietà sono banali ed è improbabile che qualcuno introduca un bug, allora dovrebbe essere sicuro non testarle.

I tuoi metodi Authenticate () e Save () sembrano buoni candidati per i test.

1
user7015

Scrivere codice che non ha valore è sempre una cattiva idea. Poiché il test proposto non aggiunge alcun valore al tuo progetto (o molto vicino ad esso). Quindi stai perdendo tempo prezioso che potresti dedicare alla scrittura di codice che in realtà porta valore.

0
pjesi

In secondo luogo testare qualsiasi cosa possa eventualmente rompersi e non scrivere test sciocchi. Ma il principio più importante è prova tutto ciò che trovi è rotto: se qualche metodo si comporta in modo strano scrivi un test per delineare il set di dati che lo fa fallire, quindi correggi il bug e osserva la barra diventare verde. Verifica anche i valori dei dati "limite" (null, 0, MAX_INT, elenchi vuoti, qualunque cosa).

0
Manrico Corazzi

Quando si scrivono test unitari o qualsiasi test, si determina cosa testare osservando le condizioni al contorno di ciò che si sta testando. Ad esempio, hai una funzione chiamata is_prime. Fortunatamente, fa quello che suggerisce il nome e ti dice se l'oggetto intero è primo o no. Per questo suppongo che tu stia usando oggetti. Ora, dovremmo verificare che si siano verificati risultati validi per un intervallo noto di oggetti primi e non primi. Questo è il tuo punto di partenza.

Fondamentalmente, guarda cosa dovrebbe accadere con una funzione, un metodo, un programma o uno script, e poi cosa dovrebbe assolutamente non accadere con lo stesso codice. Questa è la base per il tuo test. Preparati a modificare i test man mano che diventi più informato su ciò che dovrebbe accadere con il tuo codice.

0
Dan

La migliore regola empirica che ho visto è testare tutto ciò che non puoi dire a colpo d'occhio, per certo, funzionerà correttamente. Qualcos'altro e finisci per testare la lingua/l'ambiente.

0
user74754