13. Testing
Programming Project 2021/22

13.1. Introduction

The purpose of tests

Why do we test our software?

  1. Software systems are pervasive in our lives. Even small bugs have relevant impacts.
  2. Software is often used in mission critical scenarios where failure is unacceptable.
  3. Software defects cost money
    • to the users, and
    • to the developers!
  4. We want to confidently release a new version of our software.
  5. We want to document how our system should behave.

Testing terminology

Product specification: an agreement among the software development team that defines the product they are creating, detailing what it will be, how it will act, what it will do, and what it won't do.

Bug:

  • a problem in the software,
  • or a deviation from the product specification.
  • Also known as defect, fault, error, problem, anomaly...
  • May be big or small, intended or unintended.

For the purposes of this course, a software bug occurs when one of the following is the case.

  1. The software doesn't do something that the product specification says it should do.
  2. The software does something that the product specification says it shouldn't do.
  3. The software does something that the product specification doesn't mention.
  4. The software doesn't do something that the product specification doesn't mention but should.
  5. The software is difficult to understand, hard to use, slow, or—in the software tester's eyes—will be viewed by the end user as just plain not right.

A bug example

Let us exemplify bugs using a calculator.

  • Specification:

    • The calculator should perform correct addition, subtraction, multiplication, and division operations.
    • The calculator should not crash if multiple buttons are pressed simultaneously.
  • Bugs:

    • If you press + and nothing happens (1).
    • If you press 2 and 3 at the same time and the calculator stops responding (2).
    • The calculator does square root (3).
    • The calculator gives wrong results when the battery is low (4).
    • The buttons are too small (5).

Why do bugs occur?

Here is the result of a an assessment of bug causes.

Most bugs can be traced to the product specification because the specification

  • is not written,
  • is poorly written,
  • keeps changing, or
  • is not properly communicated.

Another relevant portion can be attributed to design because it may be

  • not well thought out,
  • rushed,
  • poorly communicated, or
  • changing repeatedly.

The third main category is only traceable to the mistakes in the code that maybe due to

  • complex nature of the software,
  • schedule pressure,
  • simple mistakes, or
  • poor documentation.

The cost of bugs

The costs of fixing bugs grow logarithmically with time:

Testing

Definition: The activity to verify if a software or a portion of a software behaves according to its specification.

Types of testing:

  • By approach:
    • white-box x black-box
    • static x dynamic
  • By level:
    • unit x integration x system x acceptance
      • Unit testing: the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation.
      • Integration testing: individual software modules are combined and tested as a group.
      • System testing: how various components of an application interact together in the full.
      • Acceptance testing: a quality assurance (QA) process that determines to what degree an application meets end users' approval.
  • By aspect:
    • functional x non-functional
      • Functional testing is a type of testing that seeks to establish whether each application feature works as per the software requirements.
      • Non functional testing is a type of software testing that verifies non functional aspects of the product, such as performance, stability, usability, and security.
        • Performance testing is the practice of evaluating how a system performs in terms of responsiveness and stability under a particular workload.
        • Usability testing refers to evaluating a product or service by testing it with representative users.
        • Security testing is a process intended to reveal flaws in the security mechanisms.
  • By automation:
    • automated x manual

Unit tests

A unit test is:

  • automated,
  • designed to verify a small piece of code,
  • fast,
  • isolated,
  • typically white-box.

A small piece of code usually refers to a method or a class.

Fast is subjective, but you should aim for a test suite that runs in a few seconds.

Unit tests themselves should be run in isolation from each other, so that you run tests in parallel, sequentially, or in any order.

Unit tests are not suitable for testing complex user interface or component interaction.

From: Vladimir Khorikov, Unit Testing Principles, Practices, and Patterns (2020). Manning Publications. Unit Testing Principles, Practices, and Patterns

Benefits of unit testing

  • Consolidates the specification

    Before we start with coding a component we must try to determine what the component must do.

    The act of building test cases at the start helps to clarify the expected behavior of the component. We build the test case for the possible inputs and the possible outputs. If we are unable to come up with a test, it means that the specifications are not clear enough and require revision.

  • Early error detection

    Unit tests are proof of working code. They are executed in every build and can detect failures at the first instance.

    Unit tests can detect not only coding bugs but flaws in product specifications as well. A unit test demonstrates progress; thus, as soon as a component is complete, it can be demo-ed to the stakeholders to find gaps, if any. The sooner a bug is uncovered, the cheaper it is to fix.

  • Supports maintenance

    Unit tests help in understanding the intended behavior in development cycles without being distracted by the actual code.

    Product specifications evolve over time with changes that lead to development cycles. In each of these cycles, the team has to understand how the existing code works before team members can make any changes. A well-written unit test suite helps to keep the development in focus for the team.

  • Improves design

    Unit tests make us think in terms of the expected input and the expected output.

    Unit tests are the first client of the code being tested. They uncover various issues that a client can face while interfacing with the code being tested. Unit tests can help in classifying responsibility boundaries for the components. That can improve product specifications by exposing gaps in the interface design.

  • Product documentation

    Unit tests describe how a piece of code works—that is, the expected output for a given input.

    They always describe the latest state of a specification, as they are kept in sync with the code changes.

Test coverage

The percentage of code which is tested by unit tests.

Criteria:

  • Statement
  • Branch
  • Function
  • Line

It helps you to identify which portions of your code have been tested.

  • 100% test coverage is unrealistic.
  • Test coverage is not the whole picture.

Testing frameworks

There are several testing frameworks available for Java, the most popular ones being:

In this course, we use JUnit 5.