Arrange parameters in Unittest naam

Over Unittesten valt heel wat te vertellen. Je kunt natuurlijk vanuit Test Driven Development naar unttests kijken en over red/green/refactor beginnen. Maar ik ben geen ster in TDD.

Als ik heel eerlijk ben, dan heb ik een haat/liefde verhouding met unittesten. In vind het heel lastig om in de praktijk direct met testen te beginnen. Ik moet eerst nog de werking van de code en de daarbij behorende methodes en interfaces gaan ontdekken. Ik werk dus liever vanuit de gedachte Green/Red/Refactor. Dus ik schrijf liever werkende code en daarna de unittests aansluitend op die code en refactor eventueel mijn code later.

En inderdaad, achteraf baal ik er van dat ik niet meer tests heb geschreven… Want unittests leveren zo ontzettend veel op: zeer snel de werking van je code controleren, dag in, dag uit, zelfs na vele maanden.

Niks geeft meer voldoening dan code die al maanden niet meer aangeraakt is, na het ophalen uit TFS, direct te kunnen compileren en daarna de groene unittests te zien ‘binnenstromen’.

Maar vervolgens heb ik een nieuw probleem. Naar mate er meer unittests verschijnen, moet ik ze ook uit elkaar weten te houden. Ik gebruik hierbij in eerste instantie de naamgeving: [UnitOfWork_StateUnderTest_ExpectedBehavior]. Dit is ook beschreven door Roy Osherove.

Ik combineer dit met de strategie ARRANGE, ACT, ASSERT.

Hier is een voorbeeld:

[TestMethod]
public void DoSomething_SimpleInput_Works()
{
  // Arrange

  string parameter = "Bla";
  string expected = "BlaBla";

  // Act

  string actual = SomeClass.DoSomething(parameter);

  // Assert

  Assert.AreEqual(expected, actual);
}

Maar stel dat ik meerdere unittests heb die gelijkwaardige scenario’s wil testen dan is deze naamgeving nogal eentonig… Daarom maak ik liever gebruik van een wat uitgebreidere naamgeving:

[UnitOfWork_StateUnderTest_ExpectedBehavior_Parameters].
Hieronder volgt een simpel voorbeeld hiervan:


[TestMethod]
public void DoSomething_SimpleInput_Works_Bla_BlaBla()
{
  // Arrange

  string parameter = "Bla";
  string expected = "BlaBla";

  // Act

  string actual = SomeClass.DoSomething(parameter);

  // Assert

  Assert.AreEqual(expected, actual);
}

Met dit formaat kun je verfijnder de unittesten uit elkaar houden. Kijk maar eens naar onderstaande window. Handig dus.

Maar er is wel een keerzijde. Je moet de parameters herhalen. Dezelfde waarden komen zowel in je code als in je methodenaam voor.
Dit is te ondervangen met het gebruik van de StackFrame class. Deze is eigenlijk bedoeld om runtime toegang tot je stack te hebben , maar ik kan de methodenaam nu runtime uitlezen en toepassen:


[TestMethod]
public void DoSomething_SimpleInput_Works_Bla_BlaBla()
{
  // Arrange

  StackFrame stackFrame = new StackFrame();
  string methodName = stackFrame.GetMethod().Name;

  string parameter = methodName.Split('_')[3];
  string expected = methodName.Split('_')[4];

  // Act

  string actual = SomeClass.DoSomething(parameter);

  // Assert

  Assert.AreEqual(expected, actual);
}

Als je dus het heilige vuur krijgt en snel een hele groep unittests wilt creëren dan is het heel eenvoudig geworden om de unittests te kopiëren en slecht de naam aan te passen. Deze moet uiteindelijk toch uniek en beschrijvend zijn.
Natuurlijk is dit vooral zinvol voor eenvoudige unittests met simpele types. Echt unittesten in Bulk is interessanter met de het DataSource attribuut.
Maar dit is een aardige uitbreiding van mijn unittest skills.