Data dreven unittest

by Jesper august 12, 2009 08:06

Man kan vel sagtens argumenterer for at, en test man har behov for at køre gentagende gange, ikke er en god test. Men der er bare situationer, hvor det giver god mening, uanset om det så er ‘korrekt’ eller ej. Test af et kompliceret regulært udtryk for eksempel. Det er nok også derfor at NUnit i de senere versioner, har fået en RowTest attribut, der gør det muligt at markerer en test metode som en: RowTest, og efterfølgende tilføje så mange Row-attributter som man lyster:

[RowTest]
[Row(7.95, 8)]
[Row(5.126, 5.25)]
[Row(10.37, 10.5)]
public void TestAfrunding(double price, string expected)
{
    var sut = new Money(price);
    Assert.AreEqual(expected, sut.Rounded);
}

Den feature i mbUnit, har jeg i øvrigt hørt flere udviklere fremføre, som argument for at skifte MStest ud. Det holder jo selvfølgelig ikke, men hvad gør man så egentlig, når man arbejder med MStest, og har behov for at gennemfører loopede tests?

Ja for det første, så er data dreven unittest ikke særligt godt dokumenteret på MSDN, og man har stort set kun et eksempel, men roder man lidt med Reflector, finder man hurtigt frem til det centrale. Vi har en attribut der hedder: DataSource, som vi kan dekorere vores testmetoder med. Infrastrukturen i MStest, hooker automatisk op på den datakilde, og udfører testen for hver datarow der måtte være i datakilden.

Man kan bruge alle datakilder: Sql, OleDb osv., og browser man lidt rundt i MStests private assemblies, finder man en XML datakilde, og så er der jo basis for et dejligt setup.

Jeg starter med at skrive min test:

private void TestAfrunding(decimal expected, decimal input)
{
    var sut = new Money(input);

    Assert.AreEqual(expected, sut.Rounded);
}

Læg mærke til at jeg ikke har dekoreret den med TestMethod-atributten. Jeg isolerer nemlig min test i denne metode, for at fjerne grim konverteringskode.

Så laver jeg en Xmlfil der indeholder den data jeg vil teste med. Her har man frie hænder, men mit eks. ser således ud:

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <row>
    <price>7,95</price>
    <output>8</output>
  </row>
  <row>
    <price>7,75</price>
    <output>7,75</output>
  </row>
  <row>
    <price>7,22</price>
    <output>7,25</output>
  </row>
  <row>
    <price>7,12</price>
    <output>7,00</output>
  </row>
  <row>
    <price>7,13</price>
    <output>7,25</output>
  </row>
  <row>
    <price>7,125</price>
    <output>7,25</output>
  </row>
</data>

Selve testmetoden kommer til at se således ud:

[TestMethod,
DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
           "TestData.xml",
           "Row",
            DataAccessMethod.Sequential)]
public void RowTest()
{
    // Xmldata konverteres
    decimal expected = Convert.ToDecimal(TestContext.DataRow["output"]);
    decimal input = Convert.ToDecimal(TestContext.DataRow["price"]);
    
    // Her kaldes den egentlige test
    TestAfrunding(expected, input);
}

Det fine ved dette framework, er at man i modsætning til mbUnit, kan rette i sine testdata, og køre testene, uden at skulle rekompilerer. Desuden har man separeret kode fra data, og det er jo altid godt.

Frameworket kører alle test selvom der er nogen der skulle fejle. Ser man efterfølgende på detaljerne i testresultatet, kan man direkte se hvilken datarow der fik testen til at fejle – nice;-)

Udklip110809

Måske er denne metode lidt mere indviklet end i mbUnit, men når først man har prøvet at have hul igennem, virker det enormt intuitivt, og kan virkelig øge kvaliteten i de tests man laver.

Code on…

Tags:

Unittest | VS.NET | MS test

Kommentarerne er lukkede

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen | Modified by Mooglegiant

About

Mit navn er Jesper Jensen, og jeg arbejder til dagligt som web-udvikler hos DGI, hvor mit speciale er klientside applikationer. Før det var jeg nogle år i robotbranchen, hvor jeg arbejdede med 3D simulering og system koordinering. Jeg elsker webudvikling, og specielt JavaScript har min interesse. Jeg har blogget om mine oplevelser med udvikling siden 2004

Calendar

<<  september 2010  >>
mationtofr
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

RecentComments

Comment RSS