expect-run-verify… Goodbye!

February 1, 2008

Expect-run-verify is the most common pattern in mock frameworks. (update: I called it record-replay-verify before – my bad – expect-run-verify is what I really meant).

What’s wrong with it?

  1. Codebase suffers. Test methods become noisy. I have to expect/record some interactions not because I want to test them but because mocks complain if I don’t do it.
  2. Doesn’t give me a natural test-drive. I prefer when expectations become assertions and appear after execution – it’s very intuitive.
  3. Tests are fragile. Test driving new functionality that requires additional interaction often breaks all tests. Thanks to the aggressive nature of expect-run-verify.
  4. Could give better failures. When expectation becomes assertion, failure shows exact line of code. No more deciphering exception messages – just click on first element on stack trace.
  5. Could read better. Separation of stubbing and expectations reads really nicely.

Today I discovered MoQ – little mocking library for .NET. When I read how MoQ was invented I see many similarities with my own thinking process that pushed me to write Mockito.

MoQ uses C# 3.0 sugar like lambda expressions. Mockito is a java creature. Both don’t like record/playback model. Mockito goes even further and abandons expect-run-verify.

dirtyharry

Expect-run-verify…

Goodbye!

Let me enjoy most natural test-drive: as close to state based testing as possible. Expectations in Mockito are like assertions – good old friends of state based testing.

Java TDDer have several options these days:

  1. Using hand crafted stubs/mocks: too much boilerplate, too many lines of code, chaos of stubs.
  2. Using existing mock libraries: less some obscure exceptions it’s all expect-run-verify stuff.
  3. Mockito: just try it and tell me what you don’t like about it :)

I know that many test-infected java people on this planet don’t use mock frameworks. They code mocks/stubs from scratch because they find mock libraries too annoying. Mockito offers simplicity and flexibility of hand crafted mocks and yet eliminates so much boilerplate code. I encourage you to try it out.


Witamy w obrazkowie

March 9, 2007

Problem: zaciężni maruderzy tak namieszali w aplikacji (za ciężką, kontraktorską kaskę!), że nawet po miesiącu przedzierania się z maczetą przez kod, dalej czujesz się jak małe dziecko w dużym ciemnym lesie?

  • W projekcie (a był to .NET) mieliśmy do czynienia z dziesiątkami Solutions (Hej zakochani w eclipsie – solution to coś w stylu workspace) i jeszcze większą liczbą projektów. Nikt, nawet Nostradamus nie wiedział jak rozłożone są zależności między nimi. Jak trzeba było coś zakodować to średnio za trzecim razem otwierałeś w MS Dev Studio “właściwe” Solution, czyli to, które zawierało projekty, które miały kod, który Cię interesował.
  • Solutions miały paskudną właściwość dzielenia pewnych projektów między sobą. Niby niewinne, w praktyce uniemożliwia poważniejszy refaktoring: zmień cokolwiek publicznego, a sąsiednie Solution może się skompiluje. Może.
  • A teraz najlepsze: zależności między projektami były niekiedy binarne (potrzebuje DLLki), innym razem “projektowe” (potrzebuje referencji do projektu). WTF?

Ułatwmy sobie życie obrazkami! Kolega Nick, zasugerował, żeby użyć Graphviza:

1. Bardzo łatwo napisać skrypt, który zaglądnie do plików sln, przejrzy pliki proj i proszę bardzo: NHibernate od kuchni (tylko zależności projektowe):

NHibernate - zależności

2. Trochę za dużo tego, nich skrypt zajrzy tylko do wybranych projektów i niech pokaże zależności binarne:

NHibernate - podprojekty

3. A teraz fajniejsza aplikacja: CCNet. Znacznie prostsza od NHibernate, brak nadmiarowych Solutions, niewiele projektów no i przede wszystkim: Solutions NIE dzielą między sobą projektów:

CCNet - zależności

Coś w tym jest, że aplikacje dotnetowe sprzyjają nadprodukcji Solutions i Projects. Dodaj 10 programistów, 1 rok czasu i proszę bardzo przepis na chaos. Graphviz to bardzo przyjemne narządko, żeby się z tym chaosem zmierzyć (i zrefaktorować bestię).