April 28, 2020

Effective Test Writing

A framework for writing effective tests

This is an article that came out of a workshop I had with my super talented team at PaloIT as we start a greenfield Java project for the Government.

A quote from a very smart friend of mine, Jayesh Salgaonkar, struck me the other day as we were talking about Test Driven Development. He posited that:

“There is a massive difference between the minds of a developer, and a tester. The Developer creates, and the Tester inquires”

This struck me as a realization that we as developers, learned to focus on creating and problem solving but weren’t taught how to ask questions.

Through the years, I value inquiry more and more. To the point where it’s sometimes annoying (Thanks socrates). I’ve also embraced the fact that there is value in questioning, and value in knowing what you do not know.

As I started a new project that will improve the lives of many, I wanted to start and understand if I can improve the lives of the people I work with first.

I reached out to a very skilled and experienced leader, Kean Lin, to get us into a virtual room with the objective to learn the concepts of Test Driven development together.

Out of that workshop, the team learned about the history and the RED-GREEN-REFACTOR cycle that is the gist of Test Driven Development. But I took away something much bigger out of that short time.

We had a fun exercise of doing a hot-potato test writing around the game TicTacToe. The requirements were:

  • A game is over when all fields are taken
  • A game is over when all fields in a column are taken by a player
  • A game is over when all fields in a row are taken by a player
  • A game is over when all fields in a diagonal are taken by a player
  • A player can take a field if not already taken
  • Players take turns taking fields until the game is over

What I saw was a struggle of each individual in starting to write and think about what to test.

So the following week, I came to the team again with a different objective: to give a framework on how to start looking at requirements and start an inquiry to determine what to start with.

The Framework

  1. Start with an end in mind. Design an ideal end state or outcome based on the objective or vision of your task. It could be in your head or in a piece of paper.
  2. Figure out your inputs and outputs. Starting with your inputs and your outputs will help you have an idea what kind of approaches you can take in your implementation.
  3. Determine the dependencies you might be using, and how would that affect your test. (IoC, mocking, stubs, spies)
  4. Recognize what we can, and can’t test. Prioritize what’s important and focus on that.
  5. Embrace mistakes. You don’t have to get things right the first time.
  6. Be open to change. Be open to refactoring. Dont get attached to your code. Refactor as often as the RED-GREEN-REFACTOR cycle allows. Remember you started with an end in mind, that end can change.
  7. Be wary of premature refactoring. This is not necessarily bad, but be aware that you are skipping ahead if you do. Experienced developers do this because they already think in a way that follows the framework. For those starting out, force yourself to start small. Focus on those small iterations. Practice keeping it simple.

The writing framework above is agnostic to whatever test you are doing. Unit, Behaviour, Integration, or End to End. It does not need any tools but it does require you to change how you think.

Now, how do I improve my writing process now? How do I apply this?

Let’s look at one your tasks right now:

  • What is the end state of this task? What should it look like once you’re finished?
  • How many ways can I get to this end state? 2, 3, 7 ways?
  • What is the smallest part I can start with? Is it this input box? or is it the validation of the input box? or is it just the validation function?
  • Should I even test the input box? Is it a priority? maybe the priority is this password box, let’s check with the team, or the PO.

Asking the questions above would already vastly improve the type of tests you write. You just have to take time to do it.

The framework above gives you ways of starting how to write effective tests, but how do you measure effectiveness? There is no one way to measure an effective test as codebases evolve over time and organizations have different definitions of quality. What you could look at are the following:

  • Your Organization’s/Team’s Definition of Done
  • Your Team’s working agreement
  • Your Project’s guidelines
  • Code Quality Tools
  • Code Coverage

It would be ideal for you to determine the measurement at the start of the project, or keep it as mantra. My personal one is “test only what’s important, focus on value”.

Writing tests on their own is valuable and it should be for all developers and organizations. However, cultivating a culture of testing and inquiry should be explored more in conjunction as it will improve the quality of the work made.

Stay safe and stay indoors everyone.

This article was originally published in April 28, 2020, here.