A heurística MENOS

Simplificando testes em aplicações que trabalham com cálculos

Tiago Andrade
Revista eQAlizando (antiga Revista TSPI)
9 min readJan 31, 2022

--

Ábaco
https://pixabay.com/pt/photos/%c3%a1baco-sala-de-aula-contar-contador-1866497/

Introdução

Existem inúmeras técnicas de teste de software que podem ser utilizadas por QAs em diversos contextos. Dentre elas, temos a realização de testes baseados em heurísticas.

Caso não conheça o conceito de heurísticas e como elas são aplicadas no teste de software, sugiro a leitura do artigo “Heurísticas de teste de software” de Gabriel Santos.

Entretanto, ainda dentro da realização de testes baseados em heurísticas, podemos encontrar heurísticas para diversos contextos e situações. Alguns exemplos de heurísticas você pode encontrar no artigo “Explorando aplicações Android com a Heurística T-PAIN” do Rafael Bandeira e no artigo “A heurística da MALDADE” da Victoria Raupp.

Neste artigo, será apresentada uma heurística que visa simplificar os testes em aplicações que trabalham com cálculos.

Atualmente, trabalho com um produto da área de escrita fiscal, que calcula diversos tributos (IRPJ, CSLL, PIS, COFINS, IPI, ICMS, ISS, etc) e esses tributos podem ser calculados e apresentados em um campo contido em uma tela de movimento de notas, em um relatório de conferência, em um arquivo de texto a ser enviado para o governo, dentre outras situações, mas o que não falta é cálculo. Além disso, abundantes são exemplos de aplicações (contábeis, de folha de pagamento, financeiras, etc) que realizam cálculos.

Pensando nisso, baseado em testes que já realizei e bugs que encontrei nesse tipo de aplicação, organizei alguns pontos que considero relevantes em uma heurística chamada MENOS.

Quadro negro com conteúdo matemático
https://br.freepik.com/fotos-gratis/quadro-negro-inscrito-com-formulas-e-calculos-cientificos_5896959.htm

Características da Heurística

O nome MENOS vem de um acrônimo das seguintes características:

[M]áscara

arr[E]dondamento

[N]otação científica

Val[O]res inválidos

Divi[S]ão por zero

Segue um detalhamento de cada característica:

[M]áscara

Os cálculos normalmente são realizados através de valores numéricos que podem estar contidos em campos na própria tela do cálculo, podem estar salvos em um banco de dados ou mesmo podem ser retornados por uma consulta à uma API. Independentemente de qual seja a origem dos dados que compõem o cálculo a ser realizado, é importante se questionar sobre o impacto da máscara (ou da ausência dela) nestes dados.

A máscara é uma forma de você padronizar o preenchimento de um dado. Por exemplo: Em um formulário, ao preencher um campo de CNPJ, pode-se definir que o campo possua uma máscara que estipule que no preenchimento só serão aceitos números e que a cada certa quantidade de números haverá um ponto, uma barra ou um traço de forma que sempre nesse padrão 99.999.999/9999–99. Isso é importante no sentido de padronizar os dados e pode servir como proteção para inconsistências na aplicação.

Digamos que você está testando uma funcionalidade nova que possui uma tela que realiza um cálculo que utiliza dados preenchidos em cadastros que já existiam na aplicação. Digamos que, ao gravar um destes cadastros, um campo de alíquota (que não possua uma máscara delimitando a entrada com apenas caracteres numéricos) aceite o preenchimento do caractere “%” possibilitando que o usuário grave esse cadastro com esse campo preenchido com, por exemplo, “50%” e o valor seja armazenado exatamente desta forma no banco de dados.

Caso o desenvolvedor que implementou a funcionalidade do cálculo que você está testando, estivesse contando que sempre essa alíquota seria um dado numérico (enquanto o campo aceita preenchimento alfanumérico), pode surgir aí uma inconsistência gerando até mesmo uma exceção ao processar o cálculo.

Mensagem de exceção de erro de conversão
Exemplo de exceção ocorrida ao tentar realizar a conversão do dado “50%” para o tipo inteiro em Delphi

Neste mesmo exemplo, podemos então pensar o seguinte:

• Esse campo pode ser preenchido com letras e caracteres especiais?
• Esse campo pode ser preenchido com valores negativos?
• Caso não possa ser preenchido com valores negativos, está sendo permitido o operador “-” referente ao negativo?
• Caso possa ser preenchido com valores negativos, será que, além do operador “-” referente ao negativo, o campo está aceitando outros operadores como “+”, “*” ou “/”?

Essas proteções em campos podem evitar problemas não apenas na funcionalidade atual, mas também em funcionalidades futuras que podem utilizar os dados preenchidos nesses campos.

Porém, ao proteger um campo para que não seja permitido o preenchimento com letras, pode ser que seja removida também, indevidamente, a possibilidade de se utilizar alguns atalhos que dependem de letras como Ctrl + C, Ctrl + V ou Ctrl + X, o que, certamente, geraria um incômodo para o usuário. Seria um ponto interessante a se testar, pois o fato de não se poder preencher o campo com letras não deve impactar no uso desses atalhos que utilizam letras.

Ao utilizar uma máscara em um campo, é importante considerar também a possibilidade de máscaras aplicáveis de acordo com a região do usuário. Aqui no Brasil, para separar a parte inteira e a decimal de um número, utilizamos normalmente a vírgula. Mas, por exemplo, nos EUA é comum que seja utilizado ponto para essa finalidade. Alguns sistemas brasileiros também utilizam pontos para agrupar os dígitos (exemplo: 1.502.482,00), outros, de outras regiões, podem agrupar estes dígitos com vírgulas (exemplo: 1,502,482.00). Há também diferentes unidades monetárias que podem ter máscaras diferenciadas dependendo do contexto.

Arr[E]dondamento

Caso haja algum tipo de cálculo de divisão, percentual, raiz ou operações semelhantes é importante verificar como está sendo realizado o arredondamento.

O arredondamento normalmente vai limitar um valor a um número inteiro ou a um número decimal com uma quantidade de casas decimais estipulada. Normalmente, a primeira coisa que pode ser verificada nesse ponto é se a quantidade de casas decimais está correta. É comum, sobretudo para cálculos monetários, utilizarmos duas casas decimais. Mas dependendo do tipo de cálculo da aplicação, sendo necessário valores mais precisos, duas casas decimais podem ser insuficientes.

Considerando que o cálculo esteja aplicando a quantidade de casas decimais corretamente no resultado, um outro ponto a ser verificado é se o arredondamento está sendo feito corretamente.

Um ponto de atenção ao se testar um arredondamento é quando o primeiro dígito a ser eliminado é igual a 5. Nestes casos, a regra mais comum de arredondamento estipula que o 5 acrescentaria 1 ao dígito anterior.

Exemplos:
23,765 → 23,77
78,305 → 78,31

Porém, há várias regras de arredondamentos diferentes. Como exemplo, uma regra descrita na Resolução nº 886/66 do IBGE estipula que se o número 5 for seguido de qualquer número maior que 0, o dígito anterior será acrescido em 1.

Exemplos:
32,2256 → 32,23
8,80501 → 8,81

Entretanto, se o número 5 for o último número ou for seguido por 0, o dígito anterior só será aumentado se for ímpar.

Exemplos:
11,8350 → 11,84
62,485 → 62,48

Em uma breve pesquisa no Google é possível encontrar várias formas de arredondamentos diferentes. É importante saber qual é a mais adequada para a aplicação a ser testada.

[N]otação científica

A notação científica é uma forma de escrever números demasiadamente grandes ou pequenos de forma mais comprimida.

Exemplo: 7.000.000.000.000.000.000.000.000.000.000.000 → 7 X 10³³

Algumas linguagens de programação, automaticamente, aplicam a notação científica ao imprimir um número bem grande ou um número bem pequeno.

Veja o exemplo abaixo, em Delphi:

Aplicação exibindo número grande em notação científica
Aplicação em Delphi exibindo um resultado de um número grande em notação científica

O Delphi, ao converter string para float e vice-versa, pelas funções “padrões”, exibe números muito grandes (acima de 15 dígitos inteiros) ou muito pequenos (menores que 0,0001) através de notação científica.

Será que essa forma de exibição é válida para o usuário da aplicação? Será que ao gravar esse valor em um banco de dados, pode ocorrer algum erro? Essas são algumas questões que podem ser levantadas ao se testar esse ponto.

No caso do Delphi, uma possibilidade para forçar a exibição do número sem a notação científica é a utilização da função FormatFloat.

Aplicação exibindo número grande sem notação científica
Mesma aplicação da imagem anterior, porém utilizando a função FormatFloat

Val[O]res inválidos

Esse ponto depende da regra de negócios em questão. No Programa de Testes e Qualidade de Software (PTQS), a aplicação “Lojinha”, que utilizamos para exercícios durante o curso, possui uma regra de negócio que um produto só pode ter um valor máximo de 7.000,00. Um valor acima disso não deveria ser aceito pela aplicação. Considerando que um cálculo possa ter um valor limite também, seja um valor intrínseco da regra de negócios ou mesmo um limite máximo de caracteres do campo, é válido um teste nesse caso.

Um outro exemplo de valor inválido podem ser os valores negativos. Caso o resultado do cálculo seja menor que zero, é possível demonstrar o valor como negativo?

Um outro exemplo é se a aplicação deveria trabalhar apenas números inteiros e está apresentando números com casas decimais.

Sendo assim, é importante analisar a regra de negócios e pensar em possibilidades de valores inválidos para o contexto e tentar forçar com que eles apareçam na aplicação.

Divi[S]ão por zero

Sabemos que a divisão é considerada o oposto da multiplicação. Sendo assim, em uma divisão de 10 / 2 = 5, poderíamos tirar a “prova real” onde 5 * 2 = 10. Mas e em uma divisão por zero? Se hipoteticamente 10 / 0 fosse igual a 0, logo 0 * 0 deveria ser igual a 10, o que não é. Enfim, divisão por zero é algo que não possui resultado na matemática.

É comum as divisões por zero gerarem exceções nas linguagens de programação. Veja um exemplo abaixo em Java:

Mensagem de exceção ocorrida em divisão por zero
Exceção gerada por uma divisão por zero em Java

Sendo assim, caso haja cálculos de divisão na aplicação, é importante que esses casos sejam testados.

É possível expandir essa ideia. E se no lugar do zero, eu deixar o campo vazio? E se no lugar do zero, a informação estiver como “null” no banco de dados? Há tratamentos para essas situações?

Resumo das características da heurística

Para facilitar uma consulta rápida das características da heurística, deixo aqui um resumo sobre cada uma delas:

Máscara

• Testar se os campos envolvidos no cálculo aceitam algum tipo de caractere que não seja pertinente ao cálculo (exemplo: letras, símbolo de negativo, etc).
• Caso possua alguma máscara que estipule que serão aceitos apenas números, testar também se os atalhos que dependem de letras (Ctrl + C, Ctrl + V ou Ctrl + X) continuam funcionando.
• Verificar se a máscara está sendo aplicada de acordo com a região que a aplicação será utilizada.

Arredondamento

Em operações envolvendo divisão, percentual, raiz ou semelhantes, testar:
• A quantidade de casas decimais após o arredondamento.
• Se o arredondamento está sendo realizado de forma correta de acordo com o tipo de arredondamento definido (um ponto importante é testar o caso onde o primeiro dígito a ser eliminado no arredondamento é igual a 5)..

Notação científica

• Testar cálculos com valores números bem grandes ou bem pequenos para ver se pode estar sendo gerada notação científica indevidamente.

Valores inválidos

• Testar valores inválidos de acordo com a regra de negócios (exemplos: o valor calculado pode resultar em um número negativo? Existe algum valor limite fora do alcance esperado?).

Divisão por zero

• Testar se a divisão por zero está sendo tratada.
• Testar divisão por valores em branco e/ou valores “null”.

Conclusão

Criei essa heurística com experiências que tive ao testar aplicações que envolvem cálculos. Espero que ela possa ajudar a quem trabalha com este tipo de aplicação. Sinta-se à vontade para utilizá-la, explorar seus conceitos mais a fundo, adaptá-la e melhorá-la. Inclusive, estou disponibilizando um pequeno formulário para que você possa me dizer as suas percepções sobre a heurística. Para preenchê-lo, basta clicar aqui.

Gostaria de agradecer ao Júlio de Lima pelo excelente conteúdo do Programa de Testes e Qualidade de Software (PTQS) e por todo o conhecimento que obtive sobre realização de testes baseados em heurísticas, ao Rafael Bandeira por ter me dado a ideia de escrever o artigo quando mostrei a heurística e pelo incentivo que me deu e à Cristhiane Jacques e ao Gabriel Santos pela revisão feita no artigo!

--

--