What Are Tests?

Get introduced to the different kinds of tests, their various purposes, and their code coverage.

Overview

Software testing is a fundamental part of software development. Its primary purpose is to check whether our software is behaving in the way we expect it to. Below are some of the reasons we should write tests in our program:

  • Detect bugs: We write tests to detect defects, bugs, regressions, and more.

  • Customer satisfaction: If we fix bugs before releasing the project to the customer, they’ll be more satisfied with our work.

  • Documentation: Tests offer a different way of documenting the usage of our code.

  • Efficiency: We improve our efficiency as we get feedback in the early stage of development. Thus, we can pay extra attention to the most delicate features.

  • Improve knowledge: By writing tests, we also improve our general knowledge of the programming language.

  • Security: We can deliver a more secure program that is well tested against vulnerabilities.

  • Money: Bugs cost money, so the more bugs we fix, the more money will be saved.

History of tests

First, let’s clarify two terms that we will often see when dealing with tests: production code and test code. Production code is the code that will be deployed and will power up our program. Test code, on the other hand, refers to all the code that won’t be pushed to the production system, but is still necessary for producing the final product.

In the early years of programming, there was only production code, which was developed and pushed to let the programs run. To get rid of bugs, the programmers could only rely on debugging. Nowadays, tests have gained a central role in software development. Sometimes, they’re even written before the production code, as in test-driven development. Moreover, they become a building block of the software development life cycle. They’re also involved in the CI/CD approach, so they’re run in the early stage of development.

Different kinds of tests

In programming, there are different kinds of tests with unique purposes and differences:

  • Unit tests: These only test a single component of our code, such as a function or a method. Their purpose is to test the business logic of our code, so they’re entirely agnostic from the underlying implementation details. They’re the quickest to develop and run.

  • Integration tests: These test the behavior of more than one component together. They may interact with external resources, such as a database or a web service. They’re slower to write and run than unit tests, but they can provide more meaningful outcomes.

  • End-To-End tests (aka System tests): These cover the whole process from the start to the end. In the case of a web API, they run a real HTTP request and assert the actual HTTP response provided by the HTTP server. They’re very slow to write and run, but their feedback is precious.

  • UI tests: These test the user interface that can be used by a final user. Usually, they’re costly and hard to write and maintain.

For the rest of this course, we’re only going to deal with unit tests because they’re the central pillar of test-driven development.

Code coverage

Code coverage is a unit of measurement that can tell us the amount of code covered by tests. Usually, it’s expressed as a percentage value. It’s an objective way of understanding which components of the codebase are covered well and which need to be covered better. We don’t have to reach 100% code coverage in our projects. Instead, it’s better to focus on parts that need more attention as they may hold business-critical logic.

Various kinds of statements

The statements we write in our production code can be grouped into three categories: syntax lines, logic lines, and branch lines. Let’s use an example to understand these categories better. We’ll make use of the FizzBuzz kata, but first, let’s refresh the rules of the function. The FizzBuzz function accepts a number and returns a string based on:

  • If the number is divisible by three, it prints Fizz.
  • If the number is divisible by five, it prints Buzz.
  • If the number is divisible both by three and five, it prints FizzBuzz.
  • In all of the other scenarios, it prints the actual number passed in.

Below is our implementation of this kata written in Go:

Get hands-on with 1200+ tech skills courses.