Thoughts

Confessions of a Dev late to Unit Testing

I spent years writing code but not writing unit tests. Feels like people had been doing it forever before I got into it. Now I do and so should you.

vader_testing

When I started my career many, as a new grad dev, testing primarily consisted of ensuring the code compiled. Back then the builds took all night on the fastest servers you could buy. If you broke that build you’d get a good spanking by your team.

Related image

As time went on I realized I wasn’t that fond of creating bugs. Neither was my team or management. Plus there were those testers who seemed to get pleasure out of breaking my code so I had to put a stop to that!

Related image

I learned to write better code, to write more defensively, to test my code more vigorously and even (on occasion) writing test plans so I remember how to something again in the future.

Image result for software tester

Eventually I moved to smaller companies, which meant I was closer to the end user. I could feel their pain. They made of sharing it in phone calls and emails.

Image result for angry customer

Bugs are inevitable. Especially as users find the most creative ways to break your software. The key is to resolve things quickly.

The problem was that, as the product got bigger and more complex, I realized I could easily break something I had already written. It was worse if I had written the code ages ago or someone else wrote it. Every change I made was a risk. How could I mitigate it?

Image result for 99 little bugs in the code

Wait a sec – QA will test it! Yes, they will but it’s not fair to assume it’s “their problem” or that they’ll know / catch everything or that they’ll perform full regression testing every time. Manual testing is part of a larger series of tests steps including unit tests, integration tests, performance tests, etc.

Back in 2014 I watched a video on Channel 9 about Unit Testing. I remember thinking: code that tests code? Interesting concept but I’m too busy trying to deliver code.

Image result for testing code

Clearly that wasn’t a good excuse. I made time to learn and started getting into unit testing. They key tools were:

  • a unit test framework (i.e. XUnit, NUnit, MSTest)
  • a mocking tool (i.e. moq) and
  • an tool or IDE (i.e. Visual Studio) to run the tests

I started by writing tests for new code or to ‘document’ small but important bug fixes. The latter is especially awesome. Turns out customers HATE IT when an old, nasty bug pops up again.

I’m the type of dev that likes to carefully debug code I’ve written, to ensure it’s working precisely as expected. I realized I could “document” all these tests as unit tests! Then at any point I could then hit a button and, within seconds, find out if everything was good or not. Awesomeness!

Image result for unit test all pass

But it takes time to write unit tests! Yes, they do, but I think of it as a basic investment. I already take the time to understand the requirements, the subject matter and to test the code as I write it. Why not spend a bit more time writing some unit tests? I’m sure your future self and coworkers will thank you.

futureself.png

As I worked through the hype curve I began to discover that unit tests aren’t perfect. They won’t catch everything nor should you spend huge amounts of time trying to write a perfect suite of tests.

Image result for unit test all pass

To date unit tests have caught issues before the code left my PC and I’ve been very thankful for it.

I’m far from being an expert in unit testing and, one day, I might start using TDD (test driven development).

It’s clear that, going forward, I can’t imaging writing code without writing unit tests or working on projects without them. I’m just annoyed that I had started sooner.

BTW, check out Donovan Brown’s post No more excuses.

Image result for i find your lack of tests disturbing

3 comments

    1. Good question!

      Resources:
      * That Channel 9 movie I linked to in my post. https://channel9.msdn.com/Shows/Visual-Studio-Toolbox/Getting-Started-with-Unit-Testing-Part-1
      * The Art of Unit Testing is a classic book. I found it a lot to absorb at once. If you read this, start with the first few chapters that just explain the basics – so you get the jist of it.
      * XUnit, Moq and AutoFixture cheat sheet (I currently only use the first two): http://www.jankowskimichal.pl/wp-content/uploads/downloads/2016/01/Cheatsheet_Moq_xUnit_AutoFixture.pdf
      * Checkout Pluralsight for videos. If you don’t have an account, apply for a Visual Studio Dev Essentials account which gives you 3-6 months free. This is my next video I’m watching: https://app.pluralsight.com/library/courses/csharp-unit-testing-enterprise-applications/table-of-contents. They also have videos on unit testing basics
      * I really enjoyed this recent sample (mostly because it showed how I can get Moq setup in my ASP Core project!). It demonstrates how to use XUnit and Moq together to test controllers, which were a big concern for me as that’s where a lot of important logic resided: https://github.com/aspnet/Docs/tree/master/aspnetcore/mvc/controllers/testing/sample

      Tips:
      * Learn what a mock is. This was the breakthrough moment for me. All the initial samples just have demos like “test your AddTwoNumbers(int a, int b) method”. But in reality we’re testing code that calls other code. That other code your calling – you can “mock” it. Say you want to test your CalculateInterest(int interestRate, int principle) method in your Mortgage class. Great… but it has a dependency on a complex function to get the interest rate (i.e. based on credit rating, etc, etc). You could “mock” that latter function by saying “assuming I pass X and Y, always return Z”. This is part of the “Arrange” step
      * Pick a framework. I use XUnit but NUnit is also good, as is MSTest. MSTest and NUnit are quite similar. XUnit has differently named attributes i.e. [Fact] instead of [Test]
      * I find using dependency injection (DI) helps with unit testing. DI means all your dependencies usually get given to a class via it’s constructor. If I’m testing a method in a class, I can easily pass my mocked classes
      * Naming of tests is important. I use this format, defined in this answer: http://stackoverflow.com/questions/155436/unit-test-naming-best-practices
      * Arrange, Act, Assert. These are the three basic parts of any unit test
      * Find a mocking framework that works. If your test calls a method in a class Mortgage called CalculateInterest(int interestRate, int principle) and, for hte purpose of this test, you just you need I use moq https://github.com/moq/moq
      * Start off nice and easy. As Donovan Brown wrote in his blog post, start with critical pieces of code or a test that can double-check a bug you just fixed
      * Understand the difference between a unit test and integration test

      Hope this helps.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s