Mocking External Services

Should your tests mock outside services or not? I keep seeing discussions on this topic. On the one hand, it lets your tests be in control of the testing context. Otherwise it may be very difficult to create a reliable automated test.

  • The external service might return different results at different times.
  • The external service might be slow to respond.
  • Using the external service might require running the test in a particular environment.
  • It may be impossible to generate certain error conditions with the real service.
  • There may be side-effects of using the real service.

On the other hand, our mock of the external service might differ from it in important ways.

  • Our mock service might have a slightly different interface than the real one.
  • Our mock service might accept slightly different parameters than the real one.
  • Our mock service might return slightly different results than the real one.
  • The real service might change behavior, and we won’t notice until we deploy to production.

This leaves us in a quandary. What to do? (Continued)

Another Approach to the Diamond Kata

I saw that Alistair Cockburn had written a post about Seb Rose’s post on the Diamond Kata. I only read the beginning of both of those because I recognized the problem that Seb described with the “Gorilla” approach that, upon reaching the ‘C’ case.

“The code is now screaming for us to refactor it, but to keep all the tests passing most people try to solve the entire problem at once. That’s hard, because we’ll need to cope with multiple lines, varying indentation, and repeated characters with a varying number of spaces between them.”

I’ve run into such situations before, and it’s always be a clue for me to back up and work in smaller steps. Seb describes that the ‘B’ case, “easy enough to get this to pass by hardcoding the result.” Alistair describes the strategy as “shuffle around a bit” for the ‘B’ case. I’m not sure what “shuffling around a bit” means and I don’t think it would be particularly easy to get both ‘A’ and ‘B’ cases working with constants and not heading down a silly “if (letter == 'A') … elseif (letter == 'B') …” implementation. I was curious how I would approach it, and decided to try. (Ron Jeffries also wrote a post on the topic.) I didn’t read any of these three solutions before implementing my own, just so I could see what I would do. (Continued)

The Quality Carousel

I just observed yet another conversation on twitter that started with the topic of waste in software development, brought in value as an arbiter between waste and necessity, and then quality as a modulator of value. Surely a practice that increases quality also increases value, and therefore cannot be considered waste.

These discussions seem to spin in circles. They always have, and likely always will. Why? Because they treat quality and value as attributes of what is built, rather than as relationships. I like Jerry Weinberg’s definition in Quality Software Management:Systems Thinking.

“Quality is value to some person.”

This does not bring agreement to the discussions of value and quality. It does bring a different focus to them. Who is the person that matters? I can tell you who that is. (Continued)

When Klunky Component APIs Show in the UX

At various times, the behavior of Facebook reveals to me that it’s a loosely coupled system with long latencies in synchronizing its various data stores. Just today, the iOS app asked me to confirm a friend request. When I did so, it gave me a pretty generic error—something about not being able to do this action at this time. That’s when I realized that I’d already accepted that particular friend request, days ago. That tells me that there are often inconsistencies between the database used with one interaction, and the one used with another interaction on another interface.

It also tells me that there are likely teams working on components, rather than features. If it was a feature team, the need for an error message would have driven a different underlying implementation. A feature team would want to differentiate between not being able to accomplish an action because it was already done, and because some problem was blocking it. For the former, there’s no need to show an error at all. (Continued)

Taking the Long View in Software Development

My article, Taking the Long View in Software Development, has been published on ProjectManagement.com. Free registration is required on that site.

How easy is it for your programmers to fix problems?

A programmer, writing some new code, looks into some existing code that she needs to use. Something doesn’t look quite right. In fact, there’s a bug. Whether no one’s triggered it, or they have but their complaints haven’t reached anyone who will do something about it, is hard to say. Can she fix this code now and keep working? Or does something prevent that?

In such a situation, I would prefer to write a new test illustrating the bug, fix it, and check both the test and the fix into source control. This might take five minutes or an hour. It’s a small detour, but I feel better knowing that the code is now safer for the future.

Maybe, however, there are policies, either explicit or tacit, that prevent such quick resolution. (Continued)

Build a Cache, not a Stash

There are many times where a call to get some data is time-consuming or expensive. Perhaps it makes a webservice call, or a network connection to a database, or iterates over a large collection to perform a calculation. If the values isn’t going to change rapidly, and might be needed again soon, it’s natural to want to save the value for that use. (Continued)

Technical debt comes in various varieties

Ward Cunningham originally coined the term Technical Debt and described it at OOPSLA 1992

“Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite… The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise.”

In this, Ward was not referring to poor programming practices, (Continued)

Lessons from Sailboat Racing

Recently, I was attending a sailing seminar on racing small keelboats. As the lecturer talked about the crew requirements for winning races, I noted a lot of similarities with effective software development teams. Both situations require a small group of people to work in coordinated concert to achieve a common goal. No one on the team succeeds alone–they all reach the finish line together. There is a mix of specialized skills and general work that almost anyone can do. And there is a constant need for improvement, coupled with a desire to go fast. (Continued)

I feel better, now

Oops! The whole problem started when I wanted to install a new program on the “entertainment computer” that’s connected to the TV. The existing version of Ubuntu was no longer supported, so I started what I thought would be a simple upgrade. Oops, it deleted the entire /var directory, including the contents of the second drive mounted there. That drive contained all of our photos and music. Not a problem, I thought. It’s all backed up nightly onto a USB drive. It’s just a bit of bother to copy all of that over the USB interface.

Oops! There are no photos beyond last March. I felt sick to my stomach. That’s a lot of family memories to evaporated. Whew! The program we’ve been using to download the cameras also makes a backup copy local to the machine used to download. I’ve got all the pictures back on the photo server, and now just have to sort them into directories again.

But first, I need to fix the backup script. Why didn’t it warn me when it started to fail? (Continued)