A Sad Tale of Woe Again
So your husband or wife is a software engineer, and you’re not. You like the idea of software, you even use software, but you are as interested in what goes into creating software as you are in soap manufacturing. He (or she, but programming is still a stupidly male-dominated field, so we’ll stick with the percentages) comes home, blathering on about his day. The conversation goes something like this:
Him: “They handed me a legacy codebase today. It’s ancient .Net 2 stuff. I’m supposed to refactor the existing code and, in parallel, rewrite it to .Net 4.5.”
You: (silent, but thinking, “I wonder if crocodiles attack alligators. Or can they mate with them? You only hear about crocodiles or alligators, not crocodiles and alligators. Is a ‘crocogator’ a thing?”)
Him: “I spent about five hours just looking at the stack. What a mess! I mean, it’s not bad, really, but before I make any changes I need a way to unit test, and it’s not architected for that. I don’t want to go down the rabbit hole since I’m rewriting the whole thing using SOLID DDD principles, but I’ve got to get some DI going, and I’m going to have to figure out how to mock some of the internals.”
You: (nodding, and thinking, “If I pull weeds today, then I can mow tomorrow and feel virtuous two days in a row, and treat myself to wine at lunch on Saturday.”)
Him: “Can I brainstorm the unit testing with you? Just, you know, talk it out? That would really help.”
You: (nodding slowly, thinking, “O! M! G! Just cut off my head and pour cabbage into it! Still, he’s a good man. All I have to do is listen.”
Him: “Stop me any time if I can explain how something works.”
You: “OK, honey.” (but thinking, “The weeds. I was going to pull the weeds.”)
Unbaffling Language to the Rescue!
The only thing worse than listening to a software developer talk about code is asking a sailor about an upcoming voyage. Here are some actual nautical terms and phrases: cumshaw, geedunk, abeam, baggywrinkle, beat to quarters, by and large, coxswain. The definition of “death roll”?: “In a keel boat, a death roll is the act of broaching to windward, putting the spinnaker pole into the water and causing a crash-gybe of the boom and mainsail, which sweep across the deck and plunge down into the water.” [Wikipedia]
Water. I drink water. I understand water.
Programmers don’t need to live lives of unending, habitual obfuscation. We can explain, if we but remember the lessons of literature.
The Totally Contrived, Ridiculous Metaphor
Imagine you’re a high school teacher. Now, imagine that you have a four-inch wood splinter going through your left eyelid. Which is easier on your mental state? If you say “splinter,” you must be a teacher.
Now, imagine a magical school where you don’t have to grade your own papers. You finish your eight-hour work day, go home, take an hour planning the next day’s lessons, have dinner, and study an hour or two for your required continuing education course, but you don’t have to grade at least twenty-five of the 120 five-page essays from mid-term exams.
Instead, you get to hand the exams to your Grading And Reports Department. It works like this:
- Give Mr Michael Murphy your stack of 120 essays.
- A few days later, pick up the graded essays and a formatted report of the students’ grades, broken down by class period, by student, and summarized with comparative aggregates. It’s a great report.
Recently, you were tasked with testing the GARD system. You’re a great choice, because you helped create the department. Here’s what you know:
- Mr Murphy takes the papers and gives them to Dr Marcia Malone. Dr Malone grades every paper. She gives the results back to Mr Murphy.
- Mr Murphy aggregates the grades and creates the formatted report.
- You helped train Dr Malone, who is brilliant. She can grade anything. But teachers have no control over how she grades.
- The grading scale Dr Malone uses could change at any time. Today, 90-100% could be an “A.” Tomorrow, 93-100% could be an “A.” (Remember, this is a contrived example.)
Here’s a lousy illustration.
You give the papers to Mr Murphy
Mr Murphy gives the papers to Dr Malone, who does mysterious, magical mischief.
Mr Murphy gives you back the papers.
You have only been asked to test the report formatting. This is critical! You are not verifying the grades are correct. You only care about the report. You devise this test
Given a stack of 120 papers, if the grades are abc, then report should look like xyz.
So here’s your challenge. You are going to give Mr Murphy 120 papers. He’s going to create the report. You’re going to compare what he gives you with how you know the report should look, right down to the numbers and letter grades on it. If they match, the test passes. If not, the test fails.
“Crap!” you think, “I can’t depend on Dr Malone to always give Mr Murphy the same grades! Besides, it takes her three days on average to grade that many papers, and I want my tests to be done in a day. It only takes Mr Murphy a few hours to prepare a report.”
You develop a plan. You are a genius.
- You build an automaton that looks like Dr Malone. But, it doesn’t actually grade anything. It just gives back a consistent set of scores that you tell it.
- When you give Mr Murphy the papers, you’ll also give him the automaton.
- Instead of Mr Murphy handing the papers to Dr Malone, he’ll hand them to the automaton and immediately get back your scores from it.
- Mr Murphy formats the report and gives it to you.
More laughable illustrations, but let’s include the programming terms.
We have a dependency on our grader, Dr Malone. We’ll change the GARD room so that we can give it a real or fake grader. This is called Dependency Injection.
Mr Murphy doesn’t care which grader he gets answers from. For our test, he uses the fake one. That is, he uses a Mock (also called a fake, or stub, or substitute).
We get back the report made from data we injected. We just want to compare the reports, the work Mr Murphy does.
If they match, the test passes. If not, fail!
How a programmer sees this
A programmer sees it the same way. Except it’s all words that look like English, but are alien-ese.
The Production Code
Using the Production Code
The Test Code
Dependency Injection and Mocking solve two problems that affect how well software can be tested.
- Dependency Injection lets us control what external dependencies, like a grading engine, a method uses. If we couldn’t do this, we’d have to always use production data, when that’s not what we’re always testing.
- Once we can inject a dependency, we can Mock its behavior. That is, we can make it do whatever we want, giving the method under test consistent results. Again, we’re not testing the dependent service. We’re testing the method that is using it.
It takes some work, but once you get your head wrapped around these concepts and their implementation, their importance becomes clear.