Kaip žinote, ką testuoti rašant vieneto testus?

Naudojant C #, man reikia klasės, pavadintos User , turinčio naudotojo vardą, slaptažodį, aktyvią vėliavą, vardą, pavardę, vardą ir pavardę.

Turi būti vartotojo autentifikavimo ir taupymo metodai. Ar tik rašau metodą? Ir aš net turiu nerimauti dėl testavimo savybių, nes jos yra .Net getter ir seters?

117
15 сент. nustatė Mike Roosa 2008-09-15 16:03 '08 at 4:03 pm 2008-09-15 16:03
@ 36 atsakymai
  • 1
  • 2

Daugelis nuostabių atsakymų į šį klausimą taip pat pateikiami mano klausimui: „ Pradėti TDD - problemas? Sprendimai?

Ar galiu taip pat rekomenduoti peržiūrėti dienoraščio įrašą (iš dalies tai sukėlė mano klausimas), man tai gerai. Būtent:

Aš nežinau, kur pradėti?

  • Pradėkite nuo. Tiesiog pagalvokite apie rašymo testus, kai rašote naują kodą. Tai gali būti senojo kodo apdorojimas arba visiškai nauja funkcija.
  • Pradėkite lengvai. Negalima paleisti ir pabandyti apjungti testavimo sistemą, taip pat TDD-esque. Debug.Assert puikiai veikia. Naudokite jį kaip pradinį tašką. Tai nėra jūsų projekto netvarka ar priklausomybių kūrimas.
  • Pradėkite teigiamą. Jūs bandote pagerinti savo amatus, jaustis gerai. Aš mačiau daugelį kūrėjų, kurie džiaugiasi stagnacija ir nemėgindami naujų dalykų geriau nei patys. Jūs darote teisingą dalyką, prisiminkite, ir tai padės jums neleisti jums atsisakyti.
  • Pradėkite skambinti. Sunku pradėti bandymus. Tikėtis iššūkio, tačiau atminkite - problemos gali būti įveiktos.

Tiesiog tikitės, ko tikitės.

Aš pirmą kartą pradėjau susidurti su realiomis problemomis, nes nuolat sėdėjau bandydamas išsiaiškinti visas galimas problemas, kurios gali kilti, ir tada bandau jį patikrinti ir išspręsti. Tai greitas kelias į galvos skausmą. Bandymas turi būti tikras YAGNI procesas. Jei žinote, kad yra problema, parašykite testą. Priešingu atveju nesijaudinkite.

Patikrinkite tik vieną dalyką

Kiekvienas bandymo atvejis turėtų patikrinti tik vieną dalyką. Jei kada nors atsidursite „ir“ bandymo atveju, jūs darote kažką neteisingo.

Tikiuosi, kad tai reiškia, kad mes galime pereiti nuo „getters“ ir „seters“ :)

121
15 сент. Rob Cooper atsakymas rugsėjo 15 d 2008-09-15 16:18 '08, 16:18 2008-09-15 16:18

Patikrinkite savo kodą, o ne kalbą.

Vieneto testas:

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

tik naudinga, kai rašote kompiliatorių, ir yra nulinės tikimybės, kad jūsų instanceof metodas neveikia.

Nenaudokite medžiagos, kuria galite remtis vykdymo kalba. Jūsų atveju norėčiau sutelkti dėmesį į autentifikavimo ir išsaugojimo metodus - ir norėčiau parašyti testus, kurie užtikrintų, kad jie gali apdoroti nulines vertes bet kuriame iš šių laukų.

59
15 сент. Atsakymą pateikė Tim Howland . 2008-09-15 16:09 '08 at 4:09 pm 2008-09-15 16:09

Tai privertė mane išbandyti vienetus ir mane labai laimino.

Mes ką tik pradėjome atlikti vieneto testavimą. Ilgą laiką žinojau, kad būtų malonu pradėti tai daryti, bet aš neturėjau idėjos, kaip pradėti ir dar svarbiau, ką išbandyti.

Tada teko perrašyti svarbų kodą mūsų apskaitos programoje. Ši dalis buvo labai sudėtinga, nes jame buvo daug skirtingų scenarijų. Kalbu apie tai, kaip mokėti už pardavimus ir (arba) pirkti sąskaitas faktūras, jau įrašytas į apskaitos sistemą.

Aš nežinojau, kaip pradėti ją koduoti, nes buvo tiek daug skirtingų mokėjimo galimybių. Sąskaita gali būti 100 JAV dolerių, tačiau klientas perdavė tik $ 99. Gali būti, kad pardavėjui buvo išsiųstos sąskaitos faktūros klientui, bet jūs taip pat įsigijote iš šio kliento. Taigi jūs jį pardavėte už 300 JAV dolerių, bet įsigijote 100 JAV dolerių. Galite tikėtis, kad jūsų klientas sumokės 200 JAV dolerių, kad sumokėtų likutį. O kas, jei parduodate už $ 500, bet klientas moka tik $ 250?

Taigi, aš turėjau labai sunkią problemą, leidžiant su daugybe galimybių, kad vienas scenarijus veiktų gerai, bet būtų neteisingas kitam invocie / mokėjimų derinio tipui.

Tai buvo galimybė atlikti vieneto bandymus.

Aš pradėjau rašyti (bandymo kodo viduje) metodą, skirtą abiejų pardavimų ir pirkimų sąskaitų faktūrų sąrašui sukurti. Tada parašiau antrą būdą, kaip sukurti faktinį mokėjimą. Paprastai naudotojas įveda šią informaciją per vartotojo sąsają.

Tada aš sukūriau pirmąjį „TestMethod“, patikrindamas labai paprastą mokėjimą vienoje sąskaitoje be jokių nuolaidų. Visi sistemos veiksmai atsiranda, kai banko mokėjimas bus išsaugotas duomenų bazėje. Kaip matote, sukūriau sąskaitą faktūrą, sukūriau mokėjimą (banko operaciją) ir įrašiau sandorį į diską. Savo pareiškimuose pateikiau, kas turėtų būti teisingas skaičius, kuris baigiasi Banko operacijoje ir susietoje sąskaitoje. Po sandorio patikrinu mokėjimų skaičių, mokėjimų sumą, nuolaidos sumą ir sąskaitos faktūros likutį.

Paleidus bandymą, nuėjau į duomenų bazę ir dukart patikrinau, kas buvo tikimasi.

Kai parašiau testą, pradėjau koduoti mokėjimo būdą (BankHeader klasės dalį). Koduodamas, aš tiesiog sujaudinau kodą, kad atliktumėte pirmąjį bandomąjį leidimą. Nemaniau apie kitus, sudėtingesnius scenarijus.

Atlikau pirmąjį testą, nustatiau nedidelę klaidą, kol praėjo mano testas.

Tada aš pradėjau rašyti antrą testą, šį kartą dirbdamas su nuolaida. Po to, kai parašiau testą, pakeitiau mokėjimo būdą, kad palaikytumėte nuolaidas.

Tikrindamas teisingumą su nuolaidomis, taip pat patikrinau paprastą mokėjimą. Abu testai, žinoma, turi praeiti.

Tada persikėlėu į sudėtingesnius scenarijus.

1) Pagalvokite apie naują scenarijų.

2) Parašykite šio scenarijaus testą.

3) Vykdykite šį vieną testą, kad pamatytumėte, ar jis eina

4) Jei to nepadariau, buvau derinęs ir modifikavęs kodą, kol jis praeis.

5) Pakeitus kodą, toliau tęsiau visus testus.

Taip pavyko sukurti labai sudėtingą mokėjimo būdą. Be vieneto testavimo aš nežinojau, kaip pradėti koduoti, problema atrodė didžiulė. Bandydami, galėčiau pradėti paprastu metodu ir palaipsniui išplėsti pasitikėjimą, kad paprastesni scenarijai vis dar veiks.

Esu įsitikinęs, kad vieneto bandymų naudojimas padėjo man keletą dienų (ar savaičių) koduoti ir daugiau ar mažiau garantuoja mano metodo teisingumą.

Jei aš pagalvoju apie naują scenarijų vėliau, galiu paprasčiausiai pridėti jį prie bandymų, kad įsitikintumėte, jog tai veikia. Jei ne, galiu pakeisti kodą, bet vis tiek įsitikinkite, kad kiti scenarijai vis dar veikia tinkamai. Tai padės sutaupyti dienų ir dienų priežiūros ir klaidų taisymo fazėje.

Taip, net patvirtintas kodas vis tiek gali turėti klaidų, jei naudotojas darys tai, ką nesigalvojote arba neleido jam daryti

Žemiau pateikiami tik keletas bandymų, kuriuos sukūriau, kad galėčiau patikrinti mokėjimo metodą.

 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); } 
35
16 сент. atsakymas duotas eroijen 16 sep . 2008-09-16 06:52 '08 at 6:52 am 2008-09-16 06:52

Jei jie yra tikrai nereikšmingi, nesivarginkite su bandymais. Pavyzdžiui, jei jie įgyvendinami taip:

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

Kita vertus, jei jūs darote kažką protingo (pvz., Užšifruoti ir iššifruoti slaptažodį getter / setter), tada duokite jam testą.

12
15 сент. Atsakymas, kurį pateikė Steve Cooper, rugsėjo 15 d 2008-09-15 16:10 '08 at 4:10 pm 2008-09-15 16:10

Taisyklė yra ta, kad jums reikia išbandyti kiekvieną jūsų parašytą logiką. Jei naudojote tam tikrą funkcionalumą „getters“ ir „seters“, manau, kad jie nusipelno būti išbandyti. Jei jie priskiria vertes tik tam tikriems privatiems laukams, nesijaudinkite.

9
15 сент. atsakymas pateikiamas Slavo 15 sep. 2008-09-15 16:07 '08 at 4:07 pm 2008-09-15 16:07

Kitas kanoninis atsakymas. Tai, manau, iš Ron Jeffreys:

Patikrinkite tik kodą, kurį norite naudoti.

4
15 сент. atsakymą pateikė vartotojo 9397 15 sep . 2008-09-15 22:04 '08 10:04 val. 2008-09-15 22:04

Atrodo, kad šis klausimas yra klausimas, kur galima daryti išvadą, kokie metodai yra išbandomi ir kurie ne.

Vertybių priskyrimo įrenginiai ir įgulos kūrėjai buvo sukurti nuosekliai ir ateityje augant ir numatant, kad tam tikras laikas kelyje, setter / Getter gali virsti sudėtingesnėmis operacijomis. Būtų patartina atlikti atskirus šių metodų bandymus, taip pat užtikrinti nuoseklumą ir augimą ateityje.

Pagrindinis tikslas yra kodų patikimumas, ypač atliekant pakeitimus, kad būtų pridedamos papildomos funkcijos. Aš nežinau, kas niekam nebesudarytų, kad į testavimo metodiką įtrauktų kūrėjus ir (arba) getters, bet aš tikiu, kad yra žmonių, kurie nori, kad jiems būtų įrodyta metodai, kuriuos jie žinojo arba galėjo prisiminti paskutinį kartą buvo paprasti įrenginiai / gauti vyniojimą, bet tai nebuvo ilgesnė.

Galbūt kitas komandos narys išplėtė nustatytus / gaunančius metodus, kad įgalintų logiką, kuri dabar turi būti išbandyta, bet tada nesukūrė bandymų. Bet dabar jūsų kodas skambina šiais būdais, ir jūs nežinote, kad jie pakeitė ir reikalauja išsamių bandymų, o testavimas, kurį atliekate kūrimo ir kokybės užtikrinimo metu, nesukelia defekto, bet realūs verslo duomenys pirmą kartą išleidimo dieną sukels jį.

Du komandos nariai aptars, kas nukrito kamuolį ir nepavyko atlikti vieneto testų, kai nustatė / gauna morphed, kad logika, kuri gali būti nesėkminga, bet neapima vieneto testo. Komandinis draugas, kuris iš pradžių parašė rinkinį / bus gautas, bus lengviau išeiti iš šio tinklo, jei bandymai bus atlikti nuo pirmos dienos paprasta rinkinio / gavimo metu.

Mano nuomone, kelios minutės „švaistomos“ laiko, apimančios VISUS metodus, naudojant vienintelius testus, net ir nereikšmingus, gali sutaupyti galvos skausmo dienų kelyje ir prarasti pinigus / verslo reputaciją ir prarasti kažkieno darbą.

Ir tai, kad jūs taikėte trivialius metodus su vieneto testais, šis jaunesnysis komandos draugas gali matyti, kai jie pakeičia trivialius metodus į ne trivialus ir siūlo juos atnaujinti testą, ir dabar niekas nepatiria problemų, nes trūkumas susijęs su gamybos pasiekimu .

Tai, kaip mes koduojame, ir disciplina, kurią galima matyti iš mūsų kodo, gali padėti kitiems.

4
21 марта '15 в 15:55 2015-03-21 15:55 atsakymą pateikė Thomas Carlisle kovo 21 d. 15:55 2015-03-21 15:55

Modelio kodo testavimas yra laiko švaistymas, tačiau, kaip sako Slavo, jei pridėsite šalutinį efektą prie savo getter / seterio, tuomet turite parašyti bandymą, kuris pridedamas prie šios funkcijos.

Jei atliekate testo kūrimą, pirmiausia turite parašyti sutartį (pvz., Sąsają) ir tada parašyti testą, kad būtų įgyvendinta ši sąsaja, kurioje dokumentuojami numatomi rezultatai / elgesys. Tada parašykite savo metodus nepaliesdami kodo testų. Galiausiai paimkite kodo aprėpties įrankį ir įsitikinkite, kad jūsų bandymai atlieka visus jūsų kodo loginius kelius.

3
15 сент. atsakymas pateikiamas Warren_s 15 sep . 2008-09-15 16:12 '08 at 4:12 pm 2008-09-15 16:12

Tikrai trivialus kodas, pvz., Getters ir seters, kurie neturi papildomo elgesio, nei nustatyti privatų lauką, yra per daug patikrinti. 3.0 C # yra net sintaksinis cukrus, kur kompiliatorius rūpinasi privačiu lauku, taigi jums nereikia programuoti.

Paprastai rašau labai paprastus testus, kurie išbando elgesį, kurį tikiuosi iš savo klasių. Net jei tai yra paprasti dalykai, pvz., Du numeriai. Aš labai persijungiu tarp paprasto testo rašymo ir kai kurių kodo eilučių rašymo. Taip yra todėl, kad galiu pakeisti kodą, nebijodamas, kad aš sulaužiau tai, ką aš nemanau.

3
15 сент. Atsakymą pateikė Mendelt, rugsėjo 15 d. 2008-09-15 16:14 '08 at 4:14 pm 2008-09-15 16:14

Jūs turite patikrinti viską. Dabar jūs turite getters ir steigėjų, bet vieną dieną galite juos šiek tiek pakeisti, galbūt atlikti patvirtinimą ar kažką kitą. Testai, kuriuos šiandien rašote, bus naudojami rytoj, kad įsitikintumėte, jog viskas veikia kaip įprasta. Rašydami testą, turėtumėte pamiršti apie tokius svarstymus, kaip „tai yra trivialus“. Lankstus arba testavimo kontekste turėtumėte išbandyti prielaidą dėl būsimo refaktoravimo. Be to, ar bandėte įterpti tikrai keistąsias vertybes, pvz., Labai ilgas eilutes ar kitą „blogą“ turinį? Na, jūs turėtumėte ... niekada nepriimti, kaip blogai jūsų kodas ateityje gali būti piktnaudžiaujama.

Apskritai manau, kad plataus vartotojo testų rašymas vienoje pusėje yra išsekęs. Kita vertus, nors jis visada suteikia jums neįkainojamą idėją, kaip jūsų paraiška turėtų veikti, ir padės jums atsikratyti paprastų (ir klaidingų) prielaidų (pavyzdžiui, naudotojo vardas visada bus mažesnis nei 1000 simbolių).

3
15 сент. atsakymas pateikiamas Sklivvz 15 sep . 2008-09-15 17:01 '08 at 5:01 pm 2008-09-15 17:01

Paprastiems moduliams, kurie gali būti įrankių rinkinyje arba atviro kodo tipo projekte, turėtumėte pasitikrinti, kiek įmanoma, įskaitant trivialus „getters“ ir „seters“. Tai, ką norite nepamiršti, yra tai, kad vieneto testas generuojant tam tikrą modulį yra gana paprastas. Įrašų ir nustatymų pridėjimas yra minimalus kodas, ir jį galima apdoroti be daug mąstymo. Tačiau, kai tik jūsų kodas bus patalpintas didesnėje sistemoje, ši papildoma pastanga gali apsaugoti jus nuo bazinės sistemos pakeitimų, pvz., Tipo pakeitimų bazinėje klasėje. Bandymas evertuoti yra geriausias būdas užbaigti regresiją.

3
15 сент. Atsakymas pateikiamas Dirigible 15 Sep. 2008-09-15 17:10 '08, 5:10 val. 2008-09-15 17:10

Apskritai, kai metodas apibrėžiamas tik tam tikroms reikšmėms, patikrinkite ribas ir virš leistiną ribą Kitaip tariant, įsitikinkite, kad jūsų metodas daro tai, ką turėtų daryti, bet ne daugiau. Tai svarbu, nes, kai jums nepavyksta, norėsite nesėkmės anksčiau.

Paveldėjimo hierarchijose būtinai patikrinkite, ar laikomasi LSP .

Jei nenorite atlikti kai kurių patikrinimų, man nėra naudinga išbandyti numatytuosius „getters“ ir „seters“.

2
15 сент. atsakymas duotas Rik 15 rugsėjo. 2008-09-15 16:14 '08 at 4:14 pm 2008-09-15 16:14

Tai nėra skausminga rašyti vieneto testus savo getters ir steigėjų. Šiuo metu jie gali tiesiog užpildyti lauką po gaubtu, tačiau ateityje jums gali būti patvirtinimo logika arba tarpusavyje susijusios priklausomybės, kurias reikia išbandyti. Tai lengviau rašyti dabar, kai galvojate apie tai ir tada pagalvokite apie jo modernizavimą, jei jis kada nors ateis.

2
15 сент. Atsakymą pateikė Bob King rugsėjo 15 d 2008-09-15 16:08 '08 at 4:08 pm 2008-09-15 16:08

Jūs turite padengti kiekvieno klasės metodo vykdymą su UT ir patikrinti metodo grąžinimo vertę. Tai apima „getters“ ir „seters“, ypač jei nariai (savybės) yra sudėtingos klasės, kurioms reikia inicijuoti didelį atminties paskirstymą. Skambinkite setteriui su labai didele eilute, pvz., (Arba kažkuo su graikų rašmenimis) ir patikrinkite, ar rezultatas yra teisingas (nėra sutrumpintas, kodavimas yra geras ir tt)