Jag satt och funderade på hur jag skulle testa en liten algoritm. Algoritmen skulle skapa en objektinstans utifrån givna indata, dvs. en funktion, säg från A till B. Kalla algoritmen ForReal.
Som exempelproblem, kan man tänka på att detektera kollisioner mellan en lista med fyllda rektanglar.
Det var lite halvbökigt att sätta ihop förväntat resultat, expB, för att jämföra med vad algoritmen kom fram till, och då kom jag på följande:
Om jag känner till en enkel, korrekt algoritm för att beräkna A->B, kan det vara lättare att använda den som ”bollplank” vid testning, istället för att konstruera förväntat resultat. Kalla denna algoritm Naive.
Då kan man direkt i testfixturen lägga in Naive, och bara hitta på några An att genomföra punkttestning mot.
I exempelproblemet med kolliderande rektanglar, skulle Naive helt enkelt testa kollision mellan alla rektanglar i en dubbelloop, medan ForReal skulle hitta på någon avancerad sortering eller datastruktur för att göra det bättre än O(n^2).
Vilka kriterier ska vara uppfyllda för att denna teknik ska funka bra?
- Man har något sätt att jämföra Bn (värdelikhet)
- Man känner till en enkel implementation, Naive
- Det är lätt att skapa An
- ForReal behöver vara extremt snabb (annars kunde man använda Naive!)
När funkar detta mindre bra?
- Om man inte har kod för att jämföra olika Bn, hjälper inte Naive
- Om man vill testa rejäla An, eller att Bn blir såpass stora/tunga att beräkna att Naive är opraktisk, blir testerna slöa och så vill man inte ha dem
Läs även andra bloggares åsikter om algoritm, algoritmer, optimering, prestanda, programmering, tdd, tdd-teknik
Som en kommentar till min egen post kan man konstatera att själva grundproblemet här, är att Bn inte är lätta att konstruera. Detta är en ”bad code smell” (kod med dålig andedräkt?) och tecken på att B behöver faktoriseras om!