Google Mock

12 december 2008

images4Har just fått nys om ett nytt mocking framework för C++, utvecklat av Google. Det är BSD license så det är helt öppet. Läs mer här.

Not: Mocking är att skapa ”fakeinstanser” av objekt i objektorienterade språk – det underlättar vid enhetstester där flera objekt är inblandade.  En mock påminner lite om en papegoja på så sätt att den upprepar vad du sagt till den! Du kan läsa vad jag skrivit om mocking här.

Taggar: , , , ,

Annons

Mockobjects

11 maj 2008

Har börjat läsa om Mock Objects och det som verkar kallas ”behaviour driven development”, BDD. Det verkar vara en top-down version av TDD; precis omvänt min erfarenhet av TDD hittills alltså – jag brukar alltid ha en lös idé om min ”arkitektur” i huvudet, och så TDD:ar jag fram klasserna på ”lägst nivå” först, dvs. bottom-up.

Ska pröva denna metod i kombination men NUnit’s inbyggda mock-object-funktionalitet, se om det funkar i praktiken. Om det gör det, så är det ett paradigmskifte för min syn på systemdesign. Då går nämligen hela systemet att ”odla fram” mha. TDD, inte bara enskila ”öar”!


Så här ser ett mjukvarupatent ut ..

24 februari 2010

Fick idag reda på att enhetstestverktyget TypeMock innehåller patenterad mjukvara. Jag copy-paste:ar ett par av de 59(!) ”claimsen” som finns däri:

43. A system according to claim 41 wherein said apparatus for at least partially isolating is operative to fake a failure of the second component.

44. A system according to claim 33 wherein said access controlling code is controlled by an application-specific test protocol. (länk)

Det är inte speciellt svårt att förstå att den här typen av gigantiska, superkomplicerade juridiska dokument (som kräver jurister och dessutom är väldigt luddiga/upp-till-tolkning) är alldeles utmärkta för stora företag som Microsoft och Apple att använda som bräckjärn mot små mjukvaruföretag. Varför? Jo det är *väldigt* svårt att avgöra huruvida mjukvaran det lilla företaget utvecklar bryter mot något patent eller inte.

För hur kan någon företagare veta om de bryter mot något patent? Det avgörs inte förrän efter en omständig och lång domstolsprocess – där förloraren får betala den andres rättegångskostnader! Den som har mest pengar kan köpa sig ”rätt” i domstolen. Minns Håkan Lans historia (wikipedia). En lite personligare historia om Håkan Lans.

Läs gärna diskussionen som pågått på Eli’s blogg under dagen. Har tidigare skrivit ett inlägg om det här med komplexitet och dess inverkan på marknad/aktörer i relation till aktörernas kapitalresurser.

Uppdatering: Bara för att visa att det ovanstånde problemet är på allvar, återger jag avanonymiserad kommunikation på mailinglista jag är med på. De två personerna kände inte till mitt blogginlägg:

”A”: I was curious if ”B” had anything to say about this patent: http://www.faqs.org/patents/app/20100037100 and its applicability to JMockit*.

”B”: No idea. That text is way too long and complicated for me to form any judgment. But thanks for the pointer,

* JMockit är en konkurrent till TypeMock, fast open source inte kommersiell.

Taggar: , ,


ALT.NET [GBG]-mötet måndag kväll

15 september 2009

Jag kom till Bishops Arms vid 19.20 måndag kväll. Jag tänkte jag skulle vara först, och invänta de andra. Tji fick jag! Magnus och Kristoffer hade redan anlänt. De hittade ett litet ”krypin” under trappan, som ett slags avsides rum. Perfekt för nördsnack!

Med varsin öl och mat på ingång satte vi igång och snackade .NET och branchen. Snart dök också Johan upp. Det blev en heltrevlig kväll som tog slut först efter tio.

Kristoffer hade med sig sin laptop och visade ett open-source-projekt han pysslar med — ska inte avslöja vilket då han fortfarande inte vill gå ut alltför ”officiellt” med det. Det verkade spännande och användbart – så mycket jag nu förstod av det. Det var webbrelaterat, och eftersom jag är en WinForms-kille nästan uteslutande (i alla fall i .NET-världen) hade jag lite svårt att hänga med. Och så hade jag fått i mig ett par öl vid tidpunkten 😉

Ett litet enhetstesttips gav jag, nämligen att man kan använda ordet ”Expect” istället för ”Assert.That” i sina NUnit-tester. Detta gör man genom att låta ens testklass ärva ifrån klassen ”AssertionHelper”:


public class SomeTests : AssertionHelper {

  [Test]

  public void Example1() {

    var result = new MySUT(1).Compute(2);

    Expect(result, Is.EqualTo(3));

  }

}

En lång och energisk diskussion vi tog upp var olika indelningar av automatiska tester. Jag sysslar än så länge uteslutande med mikro/fokus/enhetstester i samband med utvecklingsmetodiken TDD. Så för mig var det mäkta intressant att ta del av floran av verktyg som finns för .NET när det gäller automatiska tester.

Jag vill dela med mig av den ”tabell” vi ställde upp för att strukturera våra tankar (eller mina framförallt hehe).

Till att börja med sorterade vi alla termer för tester vi kom på i tre olika mer eller mindre väldefinierade kategorier. De tre kategorierna var (jag väljer ut en av termerna för att namnge kategorin så jag enkelt kan diskutera den nedan):

  1. Acceptanstest. Relaterade termer: Acceptanskriterier, User stories, Customer tests, GUI-tester*.
  2. End-to-end-test. Relaterade termer: GUI-tester*, integrationstest, regressionstest, systemtest, lasttest, smoketest.
  3. Enhetstest. Relaterade termer: mikrotest, fokustest.

* just GUI-tester valde vi att lägga ”mittemellan” kategori 1 och 2, då de inte riktigt kändes klockrena i någondera kategorin.

Sedan valde jag ut några olika egenskaper att beskriva de tre kategorierna utifrån. Jag går igenom egenskap för egenskap nedan.

Verktyg
På denna rad i tabellen fyllde vi i alla de verktyg vi diskuterat under kvällen.
Acceptanstest: TestComplete, StoryTeller, WebAII, Watin, FitNesse, Selenium.
End-to-end-test: NUnit, MbUnit, MSTest, xUnit.
Enhetstest: NUnit, MbUnit, xUnit, MSTest, Moq, RhinoMocks, Typemock, Pex.

Före/efter
På denna rad fyllde vi i om tester inom kategorin ifråga vanligtvis kodas före eller efter produktionskod.
Acceptanstest: Efter (dock skrivs User stories och deras acceptanskriterier före, fast dessa består inte av kod utan vardagsspråk!)
End-to-end-test: Efter (eftersom de brukar vara känsliga eftersom de är långa och nära inpå systemet).
Enhetstest: Före (såklart!)

Antal
Här gjorde vi ett slags grovuppskattning om antal tester inom varje kategori för ”ett typiskt projekt”.
Acceptanstest: 100 st
End-to-end-test: 300-400 st
Enhetstest: 2000-4000 st

% av utvecklingstiden
Här försökte vi uppskatta hur tidsfördelningen i ett typiskt projekt var, alltså utvecklingstid.
Acceptanstest: 20%
End-to-end-test: 20%
Enhetstest: 60%

Sammanfattningsvis kändes det nyttigt att få ett slags ”helhetsperspektiv” över automatiserade tester. Jag är som sagt novis på Acceptanstest/end-to-end-test, och det skulle vara kul att börja testa några av verktygen på riktigt.

Ytterligare en jämförelsediskussion jag kom på idag är ”Varför?”. Alltså något slags moralisk förklaring till vilket problem en viss kategori är till för att lösa.

Kanske något att diskutera på nästa möte..?

Innan vi skildes åt kom vi fram till att vi spikar 2:a måndagen varje månad under hösten för ALT.NET-GBG-möte. Detta eftersom det passade oss alla fyra bra tidsmässigt. Runt 18.00 den 12e oktober ska du alltså boka in om du är .NET-kodare, gillar modern programvaruutveckling och en eller annan öl!

Taggar: , , ,


Varför är testning av GUI/användarinteraktion så svårt?

18 september 2008

Jag håller på att utveckla ett kommando på jobbet. Det interagerar med användaren för att ta reda på vad det ska göra. Ungefär som en Wizard i Windows.

Jag brukar inte testa interaktion, bränd av erfarenhet från tidigare försök att testa användarinteraktion med hjälp av TDD.

Det är relativt lätt att förstå att det är svårt att testa Windows.Forms-GUIn; man måste instansiera och arbeta med Forms och Controls på ett sätt som man inte alls brukar göra. Dessutom tillkommer events-triggering som kan vara väldigt svårt att åstadkomma alls.

Men i mitt fall är det mer grundläggande: APIt jag använder är inte så komplicerat. Men det är fortfarande så j-a svårt att testa interaktion!

Därför frågar jag mig: vad är det som gör just interaktion så svårtestad..?

Interaktion består av ett slags dialog: fråga-svara-fråga-svara. Nästkommande fråga beror ofta på svaret som ges i föregående fråga. I mitt fall är det ”kommandot” som frågar ”användaren”, generellt är det alltså användaren som ger svaren och datorn som ställer frågorna.

Förutom att frågor kan bero på tidigare svar, kan sidoeffekter eller miljön som frågorna ställs i ändra på frågorna! T.ex. kan en fråga om ”välj skärprogram” undvikas helt om det bara finns precis ett skärprogram på ritningen. Frågan beror alltså också på miljön den ställs i, inte bara användarens svar.

Det är en massa beroenden här.

Kan det vara härifrån svårigheten kommer i interaktionstestning..? Beroendena? T.ex. beroende på filsystem eller databas vet man ju är komplicerat att testa. Beroenden rent generellt är ett bekymmer för testning. 

Och viktigare: kan vi attackera svårigheten på samma sätt som vi attackerar beroendesvårigheten när det gäller andra ”externals” (filer/db)? Dvs. dependency injection?

Jag gör ett försök:

    public interface IContext
    {
      Point2d PickZeroPoint();
      EntityCutProgram PickCutOrder();
      List<EntityCutProgram> PickECPsToAdd();
      void AddECPToCutOrder(ECP ecp, ECP cutorder);
    }

Det ger en väldigt enkel kod för själva kommandoexekveringen, [icke-komplett] exempel:

</pre>
public class MyCommand : Command {
    public void Execute(IContext context)
    {
      var cutorder = context.PickCutOrder();
      if (cutorder == null)
        context.PickZeroPoint();
      var ecps = context.PickECPsToAdd();
      if (ecps != null)
        foreach (var ecp in ecps)
          context.AddECPToCutOrder(cutorder, ecp);
    }
}

Nu kan vi bygga ett mock-object för IContext. Men innan vi gör det vill ja gå till hur man skriver ett test.

Vad är ett typiskt acceptanstest för en sådant här kommando..?

Ja det allra enklaste scenariot är att användaren startar kommandot, men ångrar sig och trycker Esc. Då ska kommandot avbrytas utan att något ändras i dess miljö.

Skriver först ned den mest naturliga översättningen av detta till kod:

</pre>
[Test]
public void Example1() {
  Given();
  User_runs_command();
  User_presses_Esc();
  Should_abort_command();
  Should_not_modify_context();
}

Hur ska vi realisera dessa metoder? Vi behöver

  • Något sätt att ”simulera” användaren
  • Något sätt att ”simulera” svar från miljön
  • Något sätt att få reda på om dialogen ”fallerar” någonstans (och var!)

Det sista är såklart viktigt för avbuggningstempot.

Infall: det känns som om jag helt enkelt vill skriva ned förväntad dialog och sedan verifiera den. Nytt försök på Exempel ett:

</pre>
[Test]
public void Dialog1() {
  Dialog_begins();
  Command_asks_PickCutOrder_Or_Create_new();
  User_presses_Esc();
  Dialog_ends();
}

Enklare, kortare, lättare att förstå(?). 

Hur realisera?

Det kan vara bra att komma ihåg läxan med att ”man behöver inte testa allt exakt”. Det kan räcka med ”grova drag” för att höja förtroendet för koden. 

Men för att kunna implementera User_presses_Esc() krävs det att jag kan ”rigga” returvärden från metoder. I detta fall räcker det med returvärde för ETT anrop.

Command_asks_PickCutOrder_Or_Create_new() kan realiseras mha anropslista.

</pre>
class ContextMock : IContext {
  List<string> expected;
  List<string> actual;

  public void Expect_PickCutOrder() { expected.Add("PickCutOrder"); }
  public ECP PickCutOrder() { callList.Add("PickCutOrder"); return new ECP(); }
  ...
  public void Verify() {
    CollectionAssert.AreEqual(expected, actual);
  }
}

To be continued…

Taggar: , ,


Ett BDD-experiment, observation ett

13 maj 2008

Jag började uppifrån-och-ned, som är tanken i BDD. Då blev jag satt i följande situation:

1. Indata till NAutoDoc är en sökväg till en mapp som ska scannas.
2. Utdata från NAutoDoc är en HTML-fil.

Försökte mig på detta i kod:

public interface IFileWriter {
  void WriteFile(string path, string content);
}

[Test]
public void NoInputFilesDoesNotProduceAnOutputFile()
{
  // Dependency
  DynamicMock fileWriter = new DynamicMock(typeof(IFileWriter));
  fileWriter.ExpectNoCall("WriteFile");

  // SUT (subject under test)
  TestDocGenerator gen = new TestDockGenerator(
    (IFileWriter)fileWriter.MockInstance,
    "somepath");
  gen.GenerateReport("report.html");

  fileWriter.Verify();
}

Men här låser det sig i min hjärna: hur specificerar jag att ”somepath” inte innehåller några filer? Jag tänkte mig att TestDocGenerator skulle instansiera någon ”filescanner”-klass mha. ”somepath” internt, och använda denna för att rekursivt söka igenom en sökväg.

Satt fast med denna problematik nästan en hel dag innan jag kom på mitt tankefel: ”somepath” är ett beroende! Det borde alltså mockas, inte instansieras internt i TestDocGenerator!

Försök två blir alltså:


public interface IFileList {
 List<string> GetFiles();
 }
 public interface IFileWriter {
 void WriteFile(string path, string content);
 }

[Test]
 public void NoInputFilesDoesNotProduceAnOutputFile()
 {
 // Dependency
 DynamicMock fileList = new DynamicMock(typeof(IFileList));
 fileList.ExpectAndReturn("WriteFile", new List<string>());
 DynamicMock fileWriter = new DynamicMock(typeof(IFileWriter));
 fileWriter.ExpectNoCall("WriteFile");

// SUT (subject under test)
 TestDocGenerator gen = new TestDockGenerator(
 (IFileList)fileList.MockInstance,
 (IFileWriter)fileWriter.MockInstance);
 gen.GenerateReport("report.html");

fileList.Verify();
 fileWriter.Verify();
 }
 

Slutsats: att instansiera grejer i konstruktor eller annanstans verkar inte vara BDD-vänligt! Det är detta Michael Feathers kallar ett ”internt beroende” i sin bibel ”Working Efficiently With Legacy Code” om jag minns rätt. Det är ett hälsotecken; BDD tvingar fram renare kod.

Läs även andra bloggares åsikter om , , ,


Ett BDD-experiment: NAutoDoc

12 maj 2008

Har läst om Behaviour Driven Development, artikeln ”Mocks Aren’t Stubs” av Martin Fowler först, som gjorde skillnad på begreppen Dummy, Fake, Stub och Mock. Det var den artikeln som fick upp mitt intresse för BDD. Surfade runt ett tag och fastnade för artikeln ”A new look at test-driven development” av Dave Astels, en artikeln som verkar ligga på framkanten av BDD. Bland annat så diskuteras ramverket rSpec (Ruby Specification) som låg i sin linda när artikeln skrevs, och bygger på artikelns nya kontext-inriktade synsätt.

I alla fall så håller jag nu på att testa (no pun intended!) detta nya angreppssätt att utveckla programvara. Det lilla experimentet blir en enkel implementation av TestDoc-idéen, dvs. att testkod ofta är bra dokumentation av klasser. Det funkar så här. Säg att vi utvecklar en medelvärdes-klass. Vi bygger ett test som kontrollerar att medelvärdet av ”inga tal” inte går att beräkna, och ska ge ett Exception. Så här ser det ut med NUnit:

[TestFixture]
public class MeanComputerFixture {
  [Test, ExpectedException]
  public void CallingComputeWithNoAddsIsAnError() {
    MeanComputer cpu = new MeanComputer();
    double mean = cpu.Compute();
  }
  [Test]
  public void TheMeanOfASingleValueIsTheValueItself() {
    MeanComputer cpu = new MeanComputer();
    cpu.Add(5);
    Assert.AreEqual(5, cpu.Compute());
  }
}

Detta lilla test skulle producera följande ”dokumentation” av MeanComputer-klassen:

MeanComputer:
– calling compute with no adds is an error
– the mean of a single value is the value itself

Lite nice, och förhoppningsvis något som är användbart också i praktiken. Planerar köra det på både mitt spelprojekt (Dogfight2008) och på jobbprojektet. (nackdelen som jag ser det är de obekvämt långa metodnamnen…)

Detta känns som ett lagom stort projekt att ta sig an BDD med. Kommer att parsa .cs-filer direkt, och generera en HTML-fil som resultat. Eller varför inte en .rtf-fil..? Har varit sugen på att lära mig .rtf-filformatet då det innehåller page-breaks till skillnad från HTML, något som kan vara riktigt användbart.

Läs även andra bloggares åsikter om , , ,


%d bloggare gillar detta: