Por que testar software?

Por que devemos realmente nos preocupar com testes de software? Porque bugs em sistemas existem aos montes e em toda parte!

Como uma pessoa que provavelmente usa muito da tecnologia de software, você deve ter encontrado alguns bugs de software em sua vida, seja em aplicativos no celular, jogos, redes sociais e todos os tipos de sistemas computacionais que fazem parte do nosso dia-a-dia.

Alguns deles provavelmente não o afetaram tanto. Por exemplo, talvez o aplicativo Alarme do seu celular tenha travado e você não tenha acordado a tempo para uma reunião. No entanto, alguns outros bugs podem ter afetado negativamente sua vida. Sociedades em todo o mundo enfrentam problemas críticos devido a bugs de software, desde dispositivos médicos que não funcionam corretamente e prejudicam os pacientes, até usinas de energia que fecham completamente.

E, embora esses sistemas de software que fornecemos como exemplos possam parecer distantes das tarefas diárias da maioria dos desenvolvedores, é extremamente fácil cometer erros, mesmo em sistemas de software menos críticos / complexos.

Para ilustrar como é difícil detectar bugs, vamos começar com um requisito:

Requisito: Min-max

Implemente um programa que, dada uma lista de números (inteiros), retorne o menor e o maior número dessa lista.

Parece um programa muito simples de implementar; talvez até um exercício para a disciplina de Algoritmos e Lógica de Programação. Uma primeira implementação em Java poderia ser a mostrada abaixo, onde smallest é o menor número e largest, o maior.

public class NumFinder {

  private int smallest = Integer.MAX_VALUE;
  private int largest = Integer.MIN_VALUE;
  
  public void find(int[] nums) {
    for(int n : nums) {
      if(n < smallest) smallest = n;
      else if(n > largest) largest = n;
    }
  }

  // Gets para menor e maior
}

A ideia por trás do código é a seguinte: examinamos todos os elementos da lista de números e armazenamos o menor e o maior número em duas variáveis ​​diferentes. Se n for menor que o menor número que vimos até agora (que começa com o maior número possível, representado por Integer.MAX_VALUE ou 2147483647), substituímos o menor número por n. A mesma ideia se aplica ao maior número: se n for maior que o maior número (que começa com o menor número possível, representado por Integer.MIN_VALUE, ou -2147483648) apenas o substituímos por n.

Vamos fazer uma "pequena verificação" no programa que acabamos de escrever. Uma maneira simples de fazer isso seria criar um método "principal" que exercite o programa algumas vezes. Suponha que o desenvolvedor então tente sua implementação com 4, 25, 7 e 9 como entradas.

public class Loader {

  public static void main(String[] args) {
    NumFinder nf = new NumFinder();
    nf.find(new int[] {4, 25, 7, 9});

    System.out.println(nf.getLargest());
    System.out.println(nf.getSmallest());
  }
}

O resultado deste programa é: 25, 4. Isso significa que a implementação "funciona" conforme o esperado. Em um contexto mais amplo, isso significaria que o desenvolvedor pode enviar essa nova implementação para o usuário final e permitir que ele use esse novo recurso.

Podemos mesmo...? Não, nós não podemos. A implementação atual não funciona para todos os casos possíveis, o que significa que temos um bug aí!

O programa não funciona corretamente para a seguinte entrada: uma matriz com valores 4, 3, 2 e 1. Para esta entrada, o programa retorna a seguinte saída: -2147483648, 1. De uma forma mais geral, essa implementação não consegue lidar com "números em ordem decrescente" de maneira adequada.

É isso, acabamos de encontrar um bug. Este talvez seja o momento certo para uma reflexão:

Se bugs podem ocorrer até mesmo em programas simples como os acima, imagine o que acontece em grandes sistemas de software complexos, dos quais a nossa sociedade depende?

Antes de mais nada, vamos corrigir o bug. De volta ao código-fonte, vemos que o bug é realmente causado pela instrução else if. O else if deveria ser apenas um if.

public class NumFinder {

    private int smallest = Integer.MAX_VALUE;
    private int largest = Integer.MIN_VALUE;

    public void find(int[] nums) {
        for(int n : nums) {
            if(n < smallest) smallest = n;

            // BUG estava aqui
            if(n > largest) largest = n;
        }
    }
}

Novamente, este é realmente um bug trivial. Depois de encontrá-lo, pode realmente parecer um erro infeliz. Mas esse tipo de erro não só pode acontecer, como acontece o tempo todo. Por quê?

A resposta é simples: os desenvolvedores lidam com sistemas de software altamente complexos. Sistemas de software compostos por milhões (senão bilhões) de linhas de código. Softwares que geram toneladas de dados por segundo. Software que se comunica com centenas (senão milhares) de sistemas externos de maneira assíncrona e distribuída. Softwares que tem milhões de solicitações de usuários por hora. É simplesmente impossível prever, durante o tempo de desenvolvimento, tudo o que pode acontecer.

É por isso que precisamos testar o software. Porque o mundo é extremamente complexo e bugs vão ocorrer! E pior: eles podem ter impactos gigantescos na nossa vida.

A solução? Testar rigorosamente e sistematicamente os sistemas que desenvolvemos.

Referências

Last updated

Was this helpful?