Monday 2 February 2015

ApprovalTests part II (or things I didn't show at swetugg)

I gave a talk at swetugg about ApprovalTests. Swetugg is a conference arranged by Sweden .Net User Group. Thanks a lot for a great conference and all the work you put in to it!

The presentation was recorded so I'll put up the link to that video when it's available. It's in Swedish though.

Anyway, my talk and demo on ApprovalTests was merely a teaser to the tool. So I thought I was going to show some other pretty neat things you can do with it in this post. Especially how it can be used on legacy code. If you haven't seen ApprovalTests before, this post can perhaps be a little bit difficult to understand, it's mostly a follow-up on my talk. But you can watch some introduction to ApprovalTests on the site: http://approvaltests.sourceforge.net/

Nothing of what I show here is anything new, it can be seen and downloaded from other places. This is just my view on it.

Testing Console Application

There's a code kata called "Gilded Rose". The code can be downloaded here: https://github.com/NotMyself/GildedRose

But it can be any Console Application you have or any other program that might log output to some logger (most loggers support Depency Injection, and thus you can grab the output from it from your test). But let's use the Gilded Rose Program.

So, lets start by creating the gilded rose program. Copy the code from the link above in a new class, call it GildedRose.cs or something. Then also download the Program.cs from the link above.

If you run the program you'll see it will render some output to the console. But let's see what we can do instead.
Create a new test fixture class (I use xUnit, but you can use whatever you like). Add the UseReporter attribute to your test fixture (you have to grab ApprovalTests from nuget first of course). Then we can redirect the output to our own StringWriter, like this (sorry about using pictures/screen caps, but I want to show what it really looks like on my machine):

When we run the test, we will now have the output in our "received" file:

Let's approve that. This is production code so we know it works (well... it could contain bugs of course, but that's another story. We don't want to fix those bugs now anyway).

(Another pretty good thing with logging is that we can always add more. Logging doesn't (shouldn't?) break things, just bring you more information on what happens).

Great! Now we can start refactoring our code! Let's - just for fun - try and move this if-statement (we might think that's a good refactoring step?) and see if we break anything:
What happens? Let's run the test:

Nope, that broke it. I like how we easily can spot the difference using the difftool. But we really don't care what actually broke, we just care that it actually did.

Combination Tests, or "Locking code"

This is another pretty neat thing. I've stolen this directly from Llewellyn Falco (modified some, hope it's ok...) There's a video on this, but I'll show it as screen dumps here.

First, download my version of MovieNight.cs from this gist: https://gist.github.com/henebb/a4c3ac25399858234e3f

Create a new test fixture class and first write this:

If you run the test you will get an output that says: "Mr. Henrik should watch A Most Wanted Man, Sex Tape," (thus I will have time to watch "A Most Wanted Man" and "Sex Tape" during my 3.5 hour movie night).

But this doesn't really feel like we've covered much. And yes, if we start a code coverage tool (like the built in Visual Studio: Test > Analyze Code Coverage) we see that all code is not covered.

But we can modify our approval and use what is called a combination approval. It looks like this. Note how we have to change our variables to arrays (all combinations we want to try) and how we moved the function call to our CombinationApprovals:

If we run the test, we know get this output (excerpt screen dump):

The output will have 300 rows (one for each combination). And if we look at the code coverage we can now see we've covered everything. We can now approve this output and thus "lock" it. And we can refactor the code as we please.

That's two more powerful things you can use ApprovalTests for. If you download ApprovalTests you can explore some other nice reporters and approvers you can use for your specific needs.