Jag har mer och mer blivit intresserad av det här med Test Driven Development men jag har ännu inte kommit till den punkten där jag testat det. Men det känns som att det finns en del bra saker att hämta från TDD. Jag gillar konceptet med att skapa automatiserade tester och byggen. Jag fick för någon dag sedan ett mail ifrån en mailinglista där man bla sade något i stil med: "Varför ska slutanvändaren eller testaren hitta felen i det utvecklaren gjort? Utvecklaren kan hitta dessa fel i vissa fall snabbare och effektivare.". Det ligger en del i det. Nog om det... Jag antar att du menar en metod "SkapaPost". Det var ett bra konkret exempel! >En parantes bara. Är det nödvändigt att hämta upp antalet poster från databasen? Räcker det inte att >Självklart, men ett extra test gör iallafall ingen skada (dessutom kollar det att bara en rad lags till) >För om vi antar att man parallell kör testet med någon som testar i testmiljön då kan det bli fel omRiktlinjer för enhetstest av en simpel insertmetod?
Anledningen för att jag skriver detta inlägg är för att jag skulle gärna vilja få lite konkreta exempel på hur man skriver sina tester. Alla exempel jag fått på olika seminarium om TDD är hur man tex validerar en simpel multiplikationsmetod eller något liknande. Ett sådant test är inte svårt att skriva.
Det finns mängder med olika tester som jag gärna skulle vilja diskutera, just för att få fram goda riktlinjer för hur testerna bör skrivas. Men för att avgränsa diskussionen en aning så tänkte jag att vi kan börja med att diskutera hur ett bra enhetstest för en simpel insertmetod skulle kunna se ut. Jag är medveten om att hur testet ser ut skiljer sig från projekt till projekt men om man ska göra ett enhetstest på en klassisk insertmetod. Hur gör man det på ett bra sätt?Sv: Riktlinjer för enhetstest av en simpel insertmetod?
Jag brukar använda en databas med ett definierat innehåll som jag alltid återställer före testet.
I NUnit skulle mitt test se ut ungefär så här
<code>
[Test]
public void TestSkapaPost() {
int startrows = rs.NumberOfRows; // nuvarande antal rader i databasen
// kolla att posten inte finns
Assert.That(rs.LasPost(key, out value), Is.False);
// lägg till en post
Assert.That(rs.SkapaPost(key, somevalue), Is.True);
// kolla att en ny post skapats
Assert.That(rs.NumberOfRows, Is.EqualTo(startrows+1));
// Hämta posten
Assert.That(rs.LasPost(key, out value), Is.True);
Assert.That(value, Is.EqualTo(somevalue);
// kolla att posten inte går att skapa igen
Assert.That(rs.SkapaPost(key, somevalue), Is.False);
Assert.That(rs.NumbeOfRows, Is.EqualTo(startrows+1));
}
</code>
Sen brukar jag lägga till lite tester för extremvärden, t.ex. null, tom sträng, "a';x" (injection), stora tal, negativa tal.
Trots att jag anser mig vara en bra programmerare brukar c:a 10% av mina tester falera vid första försöket. Felfrekvensen har varit ganska konstant genom åren och jag hoppas det beror på att jag gör mer och mer avancerade tester :-)Sv:Riktlinjer för enhetstest av en simpel insertmetod?
En parantes bara. Är det nödvändigt att hämta upp antalet poster från databasen? Räcker det inte att bara verifiera om posten lagts till i tabellen?
När du säger att du även gör lite tester för extremvärden hur menar du då? Att testet fallerar om man tex försöker lägga in ett alltför stort tal i en int är ju inte konstigt. Men jag antar att det inte är riktigt det du menar. Förklara gärna mer :)
Generalla riktlinjer för test att skapa en post kanske skulle kunna sammanfattas enligt nedan:
- Lägg till en post.
- Checka om den specifika posten lagts till genom att hämta upp den igen.
- Verifiera att att den nya posten överstämmer med den post man tänkt sig skapa.
- Eventuellt verifiera att posten inte går att skapa igen.Sv: Riktlinjer för enhetstest av en simpel insertmetod?
>bara verifiera om posten lagts till i tabellen?
Självklart, men ett extra test gör iallafall ingen skada (dessutom kollar det att bara en rad lags till)
>När du säger att du även gör lite tester för extremvärden hur menar du då? Att testet fallerar om man
>tex försöker lägga in ett alltför stort tal i en int är ju inte konstigt. Men jag antar att det inte är riktigt det
>du menar. Förklara gärna mer :)
Inget avancerat, bara kollar att det som är förväntat händer när man stoppar in extremvärden.
Om funktionen skall ge undantag för negativa värden eller null så kollar jag att den gör det.
Det blir lite redundant eftersom jag i princip testar samma saker det som jag kollar i funktionen. Har dock hänt mer än en gång att jag råkat vända något villkor i funktionen vilket fångas av testet.Sv:Riktlinjer för enhetstest av en simpel insertmetod?
Okej, det är ett bra test men då borde testet mer kontrollera antalet förekomster av en viss identifierare än alla poster. För om vi antar att man parallell kör testet med någon som testar i testmiljön då kan det bli fel om man bara tittar på antalet poster i en tabell. Testaren kan tex lägga till en rad precis då man kör testet. Kanske inte något som sker ofta men kan nog vara bra att testet blir gjort rätt.
>Inget avancerat, bara kollar att det som är förväntat händer när man stoppar in extremvärden.
>Om funktionen skall ge undantag för negativa värden eller null så kollar jag att den gör det.
>Det blir lite redundant eftersom jag i princip testar samma saker det som jag kollar i funktionen. Har dock hänt mer än en gång att jag råkat vända något >villkor i funktionen vilket fångas av testet.
Om jag förstår dig rätt så menar du att du testar din egen felhantering. Det är en bra riktlinje för testerna!
Något annat du eller någon annan vill komplettera med?Sv: Riktlinjer för enhetstest av en simpel insertmetod?
>man bara tittar på antalet poster i en tabell.
Nu är du inne på något viktgt: multipla trådar.
Utan att ha forskat nåt i ämnet skulle jag gissa att testning av multipla trådar måste göras från ett annat perspektiv än vanlig testning. Man måste se på hur globala resurser (variabler, semaforer, databaser, nätverk, ...) används i hela programmet och inte bara i en funktion. I dagsläget handlar det nog mer om att granska kod än automatiserade tester.
Jag skulle nog inte blanda ihop de två metoderna genom att försöka testa multipla trådar i ett TDD ramverk.