This content is part of the Essential Guide: How to improve code quality, from teamwork to AI features

How a tester can contribute to the code review process

Can a software tester really play a meaningful role during code review? Expert Matthew Heusser explains the step-by-step process to make yourself useful during code review.

If the typical tester doesn't write code, but can read it, how can they contribute to the code review process? Learn how to answer that question in this article. Starting with how distance from code can be a benefit, we'll add just enough guidelines and suggestions to see what the programmer sitting next to you might not.

The benefits of distance and confusion

When writers review their own material, they talk of "distance." Put the manuscript down and do something else, ideally for two or three days. Work completed on Friday will be best reviewed on Monday. The author will look at the piece with fresh eyes and be able to see the problems.

Sometimes the best distance is another person in another role. During the code review process, the author will be forced to explain what they were thinking to everyone reviewing. When the author gets confused, and can't explain something, and realizes the code will not do what is expected, the tester can just smile and say, "You're welcome."

Another advantage is when the reviewer, the less technical tester, is confused by a bit of code. In the worst case, the code is fine, and the reviewer learns a new technical trick. More commonly, a confused reader means confusing code. This might not be a bug, but it is a hint that the code is overly complex.

Here's a collection of hints and some fixes:

Guidelines for clean code

The complexity of code is a function of the number of branches it has, along with the length of each piece of code and its function or method. It is possible to transform the code into a graph and calculate the complexity, but for now, consider that the longer the code is, with more loops, if/else blocks and indentured blocks, the worse the code is.

The human mind can only track a few variables at a time. A function that has a lot of variables and is pages long is going to be more than a person can keep track of at one time -- so changes could have unintended side effects. The typical fix for this is to extract, or pull out, some piece of the function into a smaller, clearer function. Improving the design without changing the behavior is called refactoring.

Code review can even be a baby-step toward smaller pieces of code and developer or tester pairing.

Likewise, production code should minimize duplication. When new requirements come in to change a bit of code that has been copied and pasted, the code needs to be changed in two places. Forgetting to change the code in two places can lead to errors.

The company probably has a coding style suggestion or best practices. Examples include things like: Functions should be a standard length (between, say, three and 30 lines of code), curly braces should go a standard place (on the same line or below the "if" statement), variables should have a certain type of name, and, hopefully, should be declared near where they are used (if possible, as for a "good" function to review, so you can tell good from bad). Ideally, before a code review process begins, ask for several coding examples, then ask the team to sort the printouts by quality. Compare the best code to the worst and the layers in-between. Doing this as a group exercise will allow the team to have different opinions. As a tester, ask questions about these different opinions. Be curious.

It is likely the team has some disagreements on what makes good "good." That's great. Be a catalyst for it. Break that down to working agreements (define how long is too long, how much indentation is too much). Then we'll have to use these simple rules in the code review process.

Here is how to get started.

A concrete example

Consider this small code fragment, which simulates the children's game FizzBuzz. In FizzBuzz, children count off numbers, saying "fizz" if the number is divisible by three and "buzz" if it is divisible by five. So the players trade off "one,two,fizz,four, buzz,fizz,seven, eight,fizz,buzz" and so on. Here's an implementation:

    static public string FizzBuzz(int i) {
      string result = "";
      for (int idx=0; idx<i;idx++)
       //Calculate the next number
        if ( idx%3==0) {
         } else {
            if (idx%5==0) {
            } else {
      return result;

As a new tester, you most likely will be confused by a lot of this. Instead of jumping in asking what is a percent sign, during the code review process you have the author walk you through the program, which first leads to confusion about the number to loop to ("i") versus the current round of the loop ("idx"). The programmer agrees to change the name. He explains that percent sign is the remainder when dividing; when the remainder is zero ("==0") then the number is divisible evenly. You also find out that backslash n, or "\n" means new line or line break.

You suggest that the placement of the curly braces needs to be consistent, that the function feels "busy." Also, why does idx start at zero and run as long as it is less than "i" -- shouldn't it start at one and end at i? Finally, you are confused about the number 15. The code looks like it will print "fizz" and be done, yet 15 is divisible by both three and five. Shouldn't it print fizz buzz?

Listing these problems leads to a flurry of activity. You mostly just stand back and watch.

Here's the improved version of the function, which is now two functions, which you helped make better, thanks to your contributions during the code review process:

public static string FizzBuzz2(int numToFizz) {
  string result = "";
  for (int loopVariable=1; loopVariable<=numToFizz;loopVariable++) {

   return result;
  public static string GetFizzBuzzForOneNumber(int fizznum) {
    string result="";
    if ( fizznum%3==0) {
    if (fizznum%5==0) {
    if (fizznum%3!=0 && fizznum%5!=0) {
     result = fizznum.ToString();
    return result+"\n";

The first major change is separating the functionality. GetFizzBuzzForOneNumber() does the calculation for a number, while FizzBuzz now just loops from 1 to numToFizz. The result is more functions that are smaller, easier to read and have fewer errors.

Not only that, but our comment, //Calculate the next number, can go away, because the function name tells the reader what the program is doing.

The goal of the code review process

In the example above we took a piece of confusing code in a language we didn't know (It was C#), asked a programmer to walk through it, and found some problems. The next question to ask is the goal of the code review process. For example, Professor Adam Porter at the University of Maryland has pointed out that many code reviews devolve to arguments about where to put the curly braces. His suggestion is to focus solely on finding defects (such as numbers that are divisible by both five and three).

Or you could focus on making the code readable and understandable by the maintenance programmer that comes along to make a fix next week, next month or next year.

In either case, a tester involved in the code review process can add value to the team while learning about code. In the next review, there won't be any questions about what "\n", "==", "public" or "static" mean. Instead, you'll be able to dive into the code.

Code review can even be a baby-step toward smaller pieces of code and developer or tester pairing. For now though, be confident. There are plenty of things testers can do to contribute to code review.

It might just be time to get started.

Next Steps

How to understand code when you're not a coder

Why testers need to understand network traffic

Everything you need to know about HTML and CSS

Dig Deeper on Code refactoring and management