Tuesday, June 30, 2015

Book Review: The Art of Unit Testing with Examples in C#

I recently finished reading The Art of Unit Testing with Examples in C# by Roy Osherove (Amazon link). This is the 2nd edition that came out in 2013. I actually finished a couple weeks ago, but I've been taking time to digest the material. (I've mentioned it herehere, and here.)

The short version is that you should read this book if one of the following applies to you:
  • You want to get started with unit testing.
  • You want to improve your testing techniques.
  • You want tips for successfully incorporating unit testing in your work environment.
This is a short book (about 230 pages), and it is a fairly easy read.

Was It Useful to Me?
The easiest way to answer this question is to take a look at the bookmarks I put into the book while I was reading.

Interesting Topics Marked
It's pretty easy to see that I found lots of passages to be useful to me. I've been a believer in unit testing for a while now. And this helped validate some of the approaches that I've used and also see some shortcomings in some approaches that I've used. I can't say that I agree with everything Osherove says, but I agree with a high enough percentage of it that the differences are negligible.

There are quite a few things that stuck out for me. First is a clearly defined list of qualities that good unit tests have. And then it goes beyond that to describe the problems that keep us from having good unit tests (such as not having sufficient isolation) and looking at practical techniques for correcting those problems.

I also like that although he recommends TDD as a well-established way of building testable code, he does not proscribe it when first starting out. He says that it's more important that developers understand unit testing first. Having good unit tests is more important than a process. Once you understand the testing techniques, you can start to explore those other processes.

There is also quite a bit of time spent on isolation -- which is a huge issue when we're creating tests on discrete units of code. I appreciate that Osherove takes the time to go through the testing frameworks and isolation frameworks that he has found useful in his own work. (And this is one reason why I've looked into NUnit a bit further.)

When dealing with the various frameworks, I also appreciate that he tells how his tool set has changed since the publication of the first edition of the book and the reasons for that.

He also spends a bit of time talking about stubs and mocks and the differences between them. I will admit that I have not been very precise in my language when dealing with the fake objects that are in my tests. I am aware of this now and am working on being more accurate.

Osherove also provides some signs that you may have an over-complicated test or a test that tries to test more than one thing. For example, if you have control statements (switch, if, else) or loops (foreach, for, while), then you probably have logic that should not be in a test.

Along with this are a set of "smells" that you may have a problem with your tests. This includes things like constrained test order. If your tests have to be run in a particular order, then you have a dependency or shared state between tests that needs to be corrected.

I really appreciate a practical view of code coverage. Code coverage is not a silver bullet. Here's a quote:
"You could easily have close to 100% code coverage with bad tests that don’t mean anything. Low coverage is a bad sign; high coverage is a possible sign that things are better."
I have worked with teams that only cared about having 100% coverage (because this was something they could measure) without concern about the quality of the tests. In this situation, some developers will simply game the numbers so that they look like they have good results -- especially if the managers only care about the numbers. (And unfortunately, I saw that happen.)

An entire chapter is set aside for successfully bringing unit testing into your work environment. This is probably one of the most important sections. Finding the right champions, getting people of influence on your side, and setting realistic expectations are all key to a successful implementation.

My History With the First Edition
I'm a bit embarrassed to tell about my experience with the first edition of Osherove's book (back in 2009). I actually fought against unit testing in our environment back then. But (and this is a really big but), I wasn't fighting against unit testing itself, I was fighting against unit testing as the silver bullet that would fix a broken team. I used passages from the first edition to back up that viewpoint.

And I still believe that. Unit testing itself will not fix a broken environment. In this case, the team leaders were looking for a magic process that would idiot-proof development. What they really needed (at least in my opinion) was to invest in their developers. I am all about making developers better. Unfortunately, I saw them go through a new process every 6 months trying to fix things. It made me really sad to watch that.

So, I really enjoyed reading the second edition of the book because I'm now coming at it from a more productive direction. I have been extremely successful with unit testing, and I agree that it's one of the marks of a true professional -- someone who cares about the quality of the product that they deliver. (But that's another story.)

Wrap Up
So the short version is that The Art of Unit Testing is filled with great guidance and advice. As mentioned, where Osherove describes a technique that is different that what I have been doing, I explore it further.

For example, I've been swayed over to the side of not using Setup methods in test suites. Historically, I've used Setup methods, but after looking at things a bit more, I have changed my mind. I now agree with Osherove that we can enhance readability and maintainability by switching from Setup methods to factory methods that are called directly in the tests.

To make things more interesting, I had a recent conversation with Barry Stahl (my buddy that makes me think), and he described a technique that takes the concept of the factory method one step further. I'll definitely be exploring this a bit more.

Any book that encourages me to rethink the way that I've been doing things is a good book. We should be constantly re-evaluating our processes to make sure that we don't stagnate and are always headed in a productive direction.

Happy Coding!

Git Miscellany: Stuff I Didn't Know But I Do Now

You don't need to be an expert in order to show someone else how to do something. There is a lot we can learn from experts, but there's also a lot we can learn from someone who is 2 steps ahead of us, like "Watch out for that step!"

As we found out yesterday in You Aren't Instantly Awesome, and That's Okay, I'm not afraid to share what I do know even when there's much, much more that I don't know.

Last week, I did an introduction to Git presentation for a user group in Las Vegas. I am by no means an expert, but I can share my experiences in getting started with the tool and what helped me get comfortable with it. And that's what I did: Getting Started with Git.

Of course some questions came up that I did not have the answer to. Well, now I do. That's what's really great about continuous learning. So let's take a look at those questions.

Commit GUIDs
In distributed and disconnected systems (especially), we end up using GUIDs (globally unique identifiers) to mark our items. This ensures that 2 people don't use the same identifier that then causes problems when we try to bring the records together.

Git has identifiers that look like GUIDs to mark the commits:

So the question came up: How are these identifiers generated?

After a little bit of searching, I found the answer: These aren't GUIDs; they are SHA-1 hashes of the commits.

The hash is used for data integrity of the Git repository. So the idea is that when we create a commit, that changeset is used to generate a hash value. This value can be checked to make sure that the repository has not been tampered with.

Since Git is distributed, that means that I have all the files for the repository on my machine. It's possible for me to go in and monkey with a changeset in the Git repository on the file system. But if I tried to push that or otherwise try to use that particular commit, I would end up getting an error instead. If you modify the files, then the hash of the modified files will no longer match the has that was generated with the original commit.

For a little more information, you can check out this article on Wikipedia: SHA-1 / Data Integrity.

The "-u" Parameter
When doing an initial push or pull with a remote repository, the sample commands show using the "-u" switch. Here's the instructions from GitHub for pushing a local repository to a newly-created GitHub repository:

The "push" command will push to "origin" (the name we gave to our remote repository location) from the "master" branch (our main branch on our local repository).

But what does the "-u" parameter do?

I found the answer to this in the Code School - Try Git tutorial that I mentioned in my first Git article. Specifically on Step 11: https://try.github.io/levels/1/challenges/11

This tell us that "-u" sets up a default for the push command. So the next time we need to push to the remote repository, we can just use "git push", and it will use "origin" and "master" automatically as the parameters.

The same is true when we use "git pull" and the "-u" parameter.

I highly recommend the Code School tutorial. When you go through it, be sure to check the "Advice" box next to the file system display. This has a lot of helpful hints.

These aren't necessary to completing the tutorials, but they are extremely helpful as we start to go a bit deeper. I actually missed these my first time through, and I found lots of good stuff when I went back to look.

Remote Repository Options
The last question is a bit more complex. I won't give a specific answer, but I'll show you where to find what you need.

How do I set up a remote repository on our company network?

There are a myriad of options for remote repositories. Two easy off-site hosts are GitHub and Visual Studio Online. But what if we want to set up our own remote repository on our server?

It turns out there are a lot of options for this. What you choose will depend your specific needs. And this is all spelled out in the Git "Book", specifically Chapter 4. Start by looking at Git on the Server - The Protocols.

What I like about this (even though I haven't had to do this myself) is that it gives Pros and Cons to using a particular protocol. Here's a snippet:

Then from there, the rest of Chapter 4 is all about the setup process. The complexity of the process depends on your needs -- from just having a network file share all the way up to a full-blown Git server.

Keep Learning; Don't Be Afraid to Share
There are certain topics that I am very comfortable with and have a lot of experience in. It's easy for me to share what I know with others because I've probably had the same questions that they do.

There are also topics that I'm still new to. It's a bit harder to share because I know that questions will come up that I can't answer, and I know that there will probably be someone in the room with much more experience than I do. (In fact, one of the attendees at the user group meeting had been using Git as their source control system at their company; he was nice enough to help out with some of the questions.)

But I'm not afraid to say "I don't know." And it usually turns into a blog article. Just like this one.

Even if you don't know everything, it's helpful when you say "Watch out for that step!" to the people behind you.

Happy Coding!

Monday, June 29, 2015

You Aren't Instantly Awesome, and That's Okay

Learning is a process. When we're new at something, we have a tendency to be embarrassed about our lack of skill. But we shouldn't be. We should be proud to show that we're learning and progressing.

For those of you who missed the news, I got a banjo back in January:

Five months later, I've found that this is something I enjoy. And I've been taking it to developer events as an object lesson.
We aren't instantly awesome at new things.

It takes time to get proficient.

When we're learning, we need to expect this.
And just to show how much I believe this, I will play my banjo badly in public. It's not to show off my musical skills but to show that I'm not embarrassed to show people that I'm still in the learning process.

I ended up with an audio recording of that at the So Cal Code Camp this past weekend. Here's a chance for you to enjoy that:

Keep learning, keep exploring, and don't be afraid to suck when you pick up something new.

[Update 10/15/2015: I have been getting better. Check out You Aren't Instantly Awesome, But You Can Get Better with Practice to hear the latest.]

Happy Coding!

Friday, June 12, 2015

Property Injection: Simple vs. Safe

Property injection is a pattern, and just like any pattern, there are many ways to implement it. Today we'll take a look at a simple implementation that will work in some places. Then we'll take a look at a safer implementation (that is a little more code) that will work in other places. This will help us pick the right implementation for our needs.

I recently finished reading The Art of Unit Testing, 2nd Edition by Roy Osherove (Amazon). I read the first edition many years ago when I was at a different point in my career (and for interesting reasons that I won't go into here). While going through the book this time, I was comparing Osherove's techniques to the techniques that I've been using. Some of them are the same, and some of them differ a bit. Where things differ, I'm re-evaluating my processes to determine if a different approach may work better for me (and this is one reason I've been exploring NUnit further).

One difference I came across was in the implementation of Property Injection.

Simple Property Injection
The idea behind property injection is that we have a property that will have the production behavior by default. Then for testing, we can swap this out with a fake object by using the property setter.

Osherove shows a simple implementation of this pattern that uses the default getter and setter (like we get when we use the "propfull" code snippet). Then the default value for the property is set in the constructor.

Here's some code that shows this:

This is code that's been modified a bit from my HouseControl application (available on GitHub) to show Osherove's technique.

The object we want to swap out is the "ICommander" property. This is the object responsible for interacting with the hardware in this system.

And what we have is pretty simple:
  • A property with a backing field
  • Getters and setters that have no logic other than to get or set the value of the backing field
  • A constructor where we set the property to our production object (the "SerialCommander")
This means that if we do nothing, we use the production "SerialCommander" object. But we also have the chance to swap this object out for testing.

Swapping in a Fake
When we're testing this object, we can put in a fake "ICommander" by simply setting the property before interacting with the object.

Now any calls to the "Commander" property will be through our fake. And this is a pretty simple class in this case:

This just outputs a message to the console if we're in debug mode. Otherwise it does nothing.

Restrictions on Simple Property Injection
This code actually causes a problem in this application (which I'll explain in a bit). But before I get to that, I want to point out that Osherove mentions the restriction that we've run into:
"When you should use property injection
Use this technique when you want to signify that a dependency of the class under test is optional or if the dependency has a default instance created that doesn't create any problems during the test." [emphasis mine]
The Art of Unit Testing, p. 63
In our case, we do meet the criteria of having a dependency where we want a default instance (we want to use the "SerialCommander" when we run the application). But notice the last part: "that doesn't create any problems during the test." This is where our particular application falls down.

Hardware Interaction
The whole reason that I need to use property injection is because I wanted to option to test run the application even when I don't have the hardware available (see Rewriting a Legacy App Part 4: Completing the MVP with Scheduling).

Here's the constructor for our "SerialCommander" class:

This tries to initialize a serial port on COM3. The problem is that if we don't have our hardware plugged in to this machine, COM3 doesn't exist, so this code throws an exception.

Here's what happens when we run our test code:
  1. The "HouseController" constructor creates an instance of the "SerialController".
  2. The "SerialController" constructor throws an exception since the hardware is not present.
  3. We never get the chance to set the "Commander" property to our fake object since an exception is thrown.
So we fail the condition of Osherove's statement. This *does* create problems during the test.

Safer Property Injection
But all is not lost. We just need to come up with a different way to implement property injection. For this, we change the getter of our property:

Rather than creating the "SerialCommander" in the constructor, we create it in the getter of the property. But we only create it if the backing field is null.

Let's see why this is safer.

Production Run (with Default Object)
When our application runs in production, we want to use the "SerialCommander" object. Here's the process:
  1. When we create the class, the "commander" backing field is null.
  2. The first time we try to use the "Commander" property, the backing field is null, so a new "SerialCommander" is created.
  3. All subsequent calls to the "Commander" property will use the already-instantiated object in the backing field.
So this accomplishes our goal of using "SerialCommander" if we do nothing.

Test Run (with Fake Object)
For our test run, we'll use the same code that we saw above:

Here's how that process goes:
  1. When we create the class, the "commander" backing field is null.
  2. Before making any calls on the class, we set the "Commander" property to our fake object ("FakeCommander").
  3. The first time we use the "Commander" property, the backing field is *not* null, so it uses the fake object that has been assigned.
  4. Any subsequent calls to the "Commander" property will use the fake object in the backing field.
One thing to notice in this process is that the "SerialCommander" object is never created during the test run. This means that we safely get around the problem we ran into with the simple property injection.

Options Are Good
It's always good to have options. Then we can weigh the pros and cons and pick the right implementation for our application.

In this case, the simple property injection has the advantage of being very easy to implement (we could even use an automatic property if we wanted), but we may run into problems if the default implementation has some requirements we can't meet.

The safer property injection has more complex code, but we can use it in more situations. This safer implementation is how I was introduced to property injection, so this is what I've been using in my code. This has been necessary because I use this to create fake services in my tests. The simple implementation would not work for these scenarios.

For more information on how I've implemented property injection, refer to "Dependency Injection: The Property Injection Pattern" and "Property Injection - Additional Unit Tests".

Wrap Up
So this is one case where I've found my testing techniques to be a little different from Osherove's. I kind of wish that he had shown the more complex implementation as an option, but I'm really glad that he gives the restrictions when he talks about where to use the simple implementation.

Looking at other developers' techniques lets us think about situations a bit differently. Sometimes we see better ways of doing things. Sometimes we see that we're right in line with someone else. And sometimes we find that our current way of doing things has fewer limitations.

By sharing we all get better.

Happy Coding!

Monday, June 8, 2015

Unit Testing: Setup Methods or Not?

Developer events are a great place to talk to other developers about technologies and techniques that are on your mind. This past week at Denver Dev Day was no different. In particular, I had a chat with David Batten (Pluralsight & Twitter) and Brian Lagunas (Blog & Twitter) about unit testing.

This was especially timely for me because I've been reading the 2nd edition of Roy Osherove's book The Art of Unit Testing (Amazon). This is an excellent read, and I'll post a review in the next few days. There were a couple of topics that came up while reading, and I've been thinking about them a bit more. One of them has to do with Setup methods in unit tests.

We were talking about various unit testing frameworks (NUnit vs xUnit.NET) and different techniques. David mentioned that he moved away from using Setup methods in unit tests because there were other ways of doing that work that keeps the code more apparent. This is exactly what Osherove also says in The Art of Unit Testing. The idea is that we use factory methods instead of creating objects in the Setup for the tests.

I've found myself using both over the years. I've been thinking about this a bit more due to the book, so let's take a look at why we may want to use factory methods instead of setup methods.

A Look at a Setup Method
We'll start by taking a look at a set of unit tests that uses a Setup method. This is taken from my presentation "DI Why: Getting a Grip on Dependency Injection". I won't explain all of the code (you can check out the PDF Walkthrough in the session materials for that).

In this code, we have unit tests for a view model in our application. The class is called "MainWindowViewModel", so I have a test class called "MainWindowViewModelTest" (a bit of a mouthful).

These tests have a Setup method:

The primary purpose of this is to initialize a stub object that we can use in our tests. This stub represents the repository that we need. Rather than using the real object, we use Moq to create an in-memory object that behaves the way we want for testing. In this case, if someone calls the "GetPeople" method, it will return the hard-coded "people" collection that we have here. (And yes, using "DateTime.Parse" with a string like we have here is not good because it depends on the current culture having "MM/dd/yyyy" as the date format. I'm re-doing this demo code (which will fix this), but it's not posted on my site yet.)

Notice the class-level field "IPersonRepository _repository". This holds our stub object that we use later in the tests.

We're using MSTest in this example. When we mark the method with the [TestInitialize] attribute, this method is run before every test.

Here's what one of our tests looks like:

This test uses the "_repository" field as a parameter for our MainWindowViewModel constructor (an example of constructor injection). Since "_repository" is initialized in the Setup method, we have a valid value that we can use for this test.

The rest of the test makes sure that our "RefreshPeopleCommand" behaves as expected. In this case, it should populate the "People" property with our fake data.

Here's another test for the ClearPeopleCommand:

This is similar to the previous test. Again, feel free to check out the session materials for more details.

What's So Bad About This?
The problem with this code is that we need to go somewhere else to get more information about this test.

We are using the "_repository" field, but just by looking at the test, it's hard to tell exactly what that variable is (what type is it?) or how it's initialized.

This actually isn't quite as bad as the problem described by Osherove (and we'll look at that in just a bit). To see how things can be more readable, let's change our Setup method to a factory that's responsible for creating our stub.

A Look at a Factory Method
Instead of using a Setup method and a class-level field, we'll use a factory method that returns the type that we're looking for.

When we look at this method, it looks almost exactly like the "Setup" method from above. The difference is that instead of setting a class-level field, we return the "IPersonRepository" stub.

Notice that this method does not have the [TestInitialize] attribute. This means that it is *not* run automatically, so we need to call it in our tests.

Here's a refactored test:

We have a new line of code in this test. The first line of code calls the "GetRepositoryStub" method that we just created and assigns it to a local variable that is then used in our test.

The other test will have a similar change:

What's So Good About This?
The advantage of using the factory method is that all of the code is directly run in the test methods. There is now no question as to what "repository" is. We can easily see that it is an "IPersonRepository" without having to scroll to the top of the class. In addition, we can see that we are initializing it with the "GetRepositoryStub" method. This gives us a clue that we're creating a stub object that we can use in our tests.

Note: I'm currently examining how I name the variables used in my unit tests based on Osherove's book and my experiences. I'll have to get back around to this in a future article.

Readability of unit tests is extremely important. We need to think about how these tests are used. They aren't just used when we're writing the code, they are also used as we continue to develop the code. And they are also used when we go back to fix bugs or add features.

When a test fails, we want to make things as easy as possible for the developer to figure out what's going on. The first step is to make sure we have good names on our tests. If we have good names for our tests (that describe what the test is doing and what is expected), then we often don't have a need to look at the test code itself.

But when we do look at the test code, we want things to be as obvious as possible. The developer trying to debug the code may not be the same developer who wrote the test. So we want to make things as direct and non-tricky as possible.

Writing New Tests
When we're adding new features, we want to create new tests for those features. That means we'll often look at the tests that are already there so that we can (hopefully) create tests in the same style. If the tests are direct and obvious, it will be much easier for us to write new tests without having to go look for any "magic" that is going on in the Setup method.

Setup & Teardown Still Have Uses
As mentioned in a previous article (Beware of "Never" & "Always"), I examine advice from other developers to see if it fits my particular scenario. In this case, I ended up looking at how I've used Setup and Teardown methods (Teardown methods run automatically *after* each test has run). In doing so, I've found that there are a few scenarios where I would still use a Setup or Teardown method.

In a previous article (Mocking Current Time with a Simple Time Provider), I had a static property that needed to be reset before each test would run. I accomplished this with a Setup method:

This sets the static "TimeProvider" property to a valid default value. The reason we need to do this is because static objects are shared across tests, so if a test overrides this value, then it may cause another test to fail if it is not reset.

After thinking about this a bit more, I figured out that it would actually be more appropriate to do this in a Teardown method that runs *after* each test has completed:

This has the effect of resetting the static "TimeProvider" property. Since we've set the property to automatically create the correct default time provider if it is "null", this code works just fine. (In fact, I think it works a little better because now we leave it up to the production code to figure out what the correct default value is).

I still haven't updated this code in the project, but it's been on my mind for a few days. But the main point is that Setup and Teardown methods do still have their uses. In this case, it's a true "reset to default", and it makes sure that we don't have unexpected interactions between our tests.

Err on the Side of Readability
The biggest reason that I've been thinking about this is that I've seen small variations in the examples that Osherove shows in his book and how I've been writing my tests. I had to do a bit of thinking on this because in some of his examples, he shows how things can be a lot worse.

Here's a test based on a worse-case scenario described by Osherove:

Don't Do This!

For this test, I moved *all* initialization up to the Setup method. Notice that the entire "Arrange" section is gone; we are simply using the "vm" object (which is now a class-level field). This makes this test extremely hard to follow, and this is the type of thing that Osherove is trying to avoid (and for good reason).

Why would someone do this? In order to consolidate similar code (i.e. following the DRY principle). All shared code is in the Setup method, but at the cost of readability. By using factory methods, we can still follow DRY while keeping our test code readable and maintainable.

Let's take a look at our test using the factory method one more time:

This code is much easier to follow. We can see that "vm" is a MainWindowViewModel. And we can see that "repository" is a stub object based on the IPersonRepository interface. If we really care about how the stub is created, we can click into that method. But there's no need to look for a Setup method to see if something else is going on.

As another option, we could create a factory method for the view model object. And I've done this in my own projects. This made sense to me if I was initializing objects in a few different ways (in order to test different scenarios); then I could have multiple factories that gave me just the initial state I needed for a particular test. And the factories were shared across tests so I didn't have to keep writing the same initialization code over and over.

Wrap Up
It's great to talk to other developers about their experiences. Most of us have found better ways of doing things as we try different techniques. It's also reassuring to find out that you've been thinking about things in the same way as someone else.

It's really easy to feel alone in the development world. "Am I doing this right?" And we have this problem because "right" varies depending on the situation. I really like it when I talk to other developers who are doing things the same way that I'm doing something. It lets me move forward more confidently.

I also like to hear from developers who are doing things differently from me. This makes me take a look at my techniques and process to see if I can improve them.

In this particular case, I've found that I'm generally on the same path as David, Brian, and Roy Osherove. But I've seen where I vary things a bit as well. This gives me the opportunity to re-evaluate things to see where I can improve my processes.

I'm always looking for better ways of doing things. I'll be experimenting some more to determine which parts of my testing process work well for me and which parts I can tweak to make a bit better. Lots to think about -- all spurred by a small conversation at a developer event.

Happy Coding!