Två programmeringsböcker beställda

05 december 2008

Beställde två böcker om programmering igår:

1. Kent Becks moderna klassiker ”Test Driven Development: By example”

2. Mike Cohns ”User stories applied”

9780321146533

Becks bok är något varje TDD-nörd (som jag är!) bör ha i sin hylla har jag förstått på mailinglistor jag är med på. Jag anser mig redan kunna en hel del om TDD (hållit på med det i snart två år) men det finns alltid mer att lära och Beck är en av förgrundsgestalterna ”i branschen”. TDD handlar om kvalité och mjukvarudesign hand i hand – något jag brinner för.

9780321205681User Stories Applied är lite mer av en joker jag hört gott om när det handlar mer om metodik/specifikation/kommunikation. Det är lite mer nära BDD – Behaviour Driven Development – en modernare variant av TDD som hittills gäckat min förståelse. Hoppas bygga upp mer fingertoppskänsla för BDD med hjälp av denna bok.

Trevlig julläsning förväntas i alla fall!

Taggar: , ,

Annons

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: