Programação e Desenvolvimento Dirigidor por Testes
  • Programação e Desenvolvimento Dirigidor por Testes em Python
  • Autores e Agradecimentos
  • Uso do Livro
  • Contribua com o Livro
  • Licença
  • Organização do Livro
  • 1 Introdução
    • 1.1 Considerações Iniciais
    • 1.2 Configuração Inicial do Ambiente
    • 1.3 TDD Básico
      • 1.3.1 Exemplo Simples
    • 1.4 Considerações Finais
  • 2 TESTE DE SOFTWARE
    • 2.1 Considerações Iniciais
    • 2.2 Terminologia e Conceitos Básicos
    • 2.3 Fases de Teste
    • 2.4 Técnicas e Critérios de Teste
    • 2.5 Considerações Finais
  • 3 Desenvolvimento Dirigido por Teste
    • 3.1 Configuração do Ambiente
    • 3.2 Verificando o Ambiente com TDD
    • 3.3 Controle de Versão do Projeto
    • 3.4 Teste Funcional com UnitTest
    • 3.5 Teste de Unidade e a Evolução do Sistema
      • 3.5.1 Teste de Unidade de uma View
    • 3.6 Evoluindo o Teste Funcional
    • 3.7 Revisando o Processo do TDD
  • 4 TDD E BANCO DE DADOS
    • 4.1 Envio e Processamento de Requisição POST
    • 4.2 Banco de Dados no Django
  • 5 MELHORANDO E ORGANIZANDO OS CONJUNTOS DE TESTE
    • 5.1 Isolamento dos Testes Funcionais
    • 5.2 Esperas Implícitas, Explícitas e Time Sleeps
  • 6 ATACANDO O MAIOR DESAFIO DE FORMA INCREMANTAL
    • 6.1 Separando URL no Estilo REST
    • 6.2 Iterando para um Novo Design da Aplicação
    • 6.3 Refatorar Casos de Teste
    • 6.4 Separando Templates
    • 6.5 URL para Nova Lista
    • 6.6 Alterando Modelos
    • 6.7 URL Próprio para Cada Lista
Powered by GitBook
On this page
  • Técnica Funcional
  • Critério Particionamento em Classe de Equivalência
  • Critério Análise do Valor Limite

Was this helpful?

  1. 2 TESTE DE SOFTWARE

2.4 Técnicas e Critérios de Teste

Previous2.3 Fases de TesteNext2.5 Considerações Finais

Last updated 10 months ago

Was this helpful?

Para se conduzir e avaliar a qualidade da atividade de teste têm-se as técnicas de teste funcional, estrutural e baseada em defeitos (). Tais técnicas diferenciam-se pela origem da informação utilizada na avaliação e construção dos conjuntos de teste.

  • Na técnica funcional, os critérios e requisitos de teste são estabelecidos a partir da função de especificação do software;

  • Na técnica estrutural, os critérios e requisitos são derivados essencialmente a partir das características de uma particular implementação em teste; e

  • Na técnica baseada em defeitos, os critérios e requisitos de teste são oriundos do conhecimento sobre defeitos típicos cometidos no processo de desenvolvimento de software.

A figura a seguir ilustra o relacionamento entre técnica, critério, requisito e caso de teste.

(a)

(b)

(c)

(d)

Neste texto será dado ênfase à técnica de teste funcional e alguns de seus critérios. Para ilustrar a aplicação dos critérios de teste será utilizada a especificação de um programa simples, parte de um compilador, denominado Identifier. A especificação do referido programa é dada abaixo:

###############################################################################
# Especificação Identifier.py
# ---------------------------
#
# O programa deve determinar se um identificador é ou não valido em 
# ’Silly Pascal’ (uma estranha variante do Pascal).
#
# Um identificador válido deve começar com uma letra e conter apenas letras 
# ou dígitos. Caracteres acentuados não são válidos.
#
# Além disso, deve ter no mínimo 1 e no máximo 6 caracteres de comprimento.
###############################################################################

Técnica Funcional

Dois dos critérios funcionais mais conhecidos são:

  • Análise do Valor Limite: é um complemento ao critério Particionamento em Classes de Equivalência, sendo que os limites associados às condições de entrada são exercitados de forma mais rigorosa; ao invés de se selecionar qualquer elemento de uma classe, os casos de teste são escolhidos nas fronteiras das classes, pois há indícios que nesses pontos há uma maior concentração de defeitos. O espaço de saída do programa também é particionado e são exigidos casos de teste que produzam resultados nos limites dessas classes de saída.

Critério Particionamento em Classe de Equivalência

A título de ilustração, considerando a especificação do programa Identifier e o critério Particionamento em Classes de Equivalência, são identificadas na tabela abaixo as condições de entrada e classes de equivalência válidas e inválidas segundo a interpretação dos autores.

Restrições de Entrada

Classe Válida

Classe Inválida

(1)

(2) (3)

Sim

(4)

Não

(5)

Sim

(6)

Não

(7)

Como foi mencionado anteriormente, ao aplicar um critério de teste considerando determinada fonte de informação, são gerados os requisitos de teste demandados pelo referido critério. No caso do critério Particionamento em Classe de Equivalência, esses requisitos correspondem a partições, como as exibidas na tabela acima. Observa-se que uma vez estabelecidos os requisitos, todo e qualquer conjunto de teste que satisfaça o critério terá ao menos cinco casos de teste: um para cobrir as classes válidas e outros quatro, um para cada classe inválida. Os números abaixo das partições servem para identificá-las.

Por exemplo, dada a tabela acima, um possível caso de teste para cobrir as partições válidas seria: ("a1", Válido). Observa-se que esse teste é capaz de satisfazer as partições (1), (4) e (6) pois tem tamanho 2, inicia com letra e contém apenas mais um dígito após a primeira letra.

O segundo caso de teste, capaz de cobrir a partição inválida (2) é o ("", Inválido), ou seja, a cadeia vazia.

As demais partições (3), (4) e (5) poderiam ser cobertas, por exemplo, com os casos de teste ("2B3", Inválido), ("Z-12", Inválido), ("A1b2C3d", Inválido), respectivamente.

Observe que no caso do critério Particionamento em Classe de Equivalência, todo e qualquer valor dentro da partição é considerado um representante da classe de equivalência e pode ser selecionado para dar origem ao caso de teste. No critério de teste a seguir, a diferença é apenas essa, ou seja, quem pode ser utilizado para compor o caso de teste.

Critério Análise do Valor Limite

  1. se a condição de entrada especifica uma quantidade de valores, por exemplo, de 1 a 255 valores, devem ser definidos dados de teste com nenhum valor de entrada, somente um valor, dois valores, 254 valores, 255 valores e 256 valores de entrada.

  2. usar a diretriz i) para as condições de saída.

  3. usar a diretriz ii) para as condições de saída.

  4. se a entrada ou saída for um conjunto ordenado, deve ser dada maior atenção ao primeiro e último elemento desse conjunto;

  5. usar a intuição para definir outras condições limites.

Considerando as partições definidas para o programa Identifier, a definição do que é letra ou dígito poderia ser mais detalhada, facilitando a identificação dos limites das classes de equivalência. Por exemplo, a tabela abaixo ilustra esse detalhamento. No caso, assume-se que há uma tabela de codficação de caracteres de modo que é possível determinar qual o caractere imediatamente anterior a "a", por exemplo.

Restrições de Entrada

Classe Válida

Classe Inválida

(1)

(2) (3)

(4)

(5)

(6)

(7)

Independentemente de qual técnica determinado critério pertence, o papel de todo e qualquer critério de teste é derivar requisitos de teste que de forma direta ou indireta, particionam o domínio de entrada do produto em teste, forçando o testador a selecionar ao menos um elemento de cada subdomínio pra poder satisfazer o critério em questão. Desse modo, critérios mais rigorosos particionam mais o domínio de entrada do que critérios menos rigorosos. As figuras abaixo, adaptada de ilustram a segmentação ocasionada por diferentes critérios de teste supostamente dos menos rigorosos (a) para os mais rigorosos (e).

O teste funcional também é conhecido como teste caixa preta pelo fato de tratar o software como uma caixa cujo conteúdo é desconhecido e da qual só é possível visualizar o lado externo, ou seja, os dados de entrada fornecidos e as respostas produzidas como saída (). Na técnica de teste funcional são verificadas as funções do sistema sem se preocupar com os detalhes de implementação.

O teste funcional envolve dois passos principais: identificar as funções que o software deve realizar e criar casos de teste capazes de checar se essas funções são realizadas pelo software (). As funções que o software deve possuir são identificadas a partir de sua especificação. Assim, uma especificação bem elaborada e de acordo com os requisitos do usuário é essencial para esse tipo de teste.

Particionamento em Classes de Equivalência: a partir das condições de entrada de dados identificadas na especificação, divide-se o domínio de entrada de um programa em classes de equivalência válidas e inválidas. Em seguida seleciona-se o menor número possível de casos de teste, baseando-se na hipótese que um elemento de uma dada classe seria representativo da classe toda, sendo que para cada uma das classes inválidas deve ser gerado um caso de teste distinto. O uso de particionamento permite examinar os requisitos mais sistematicamente e restringir o número de casos de teste existentes. Alguns autores também consideram o domínio de saída do programa para estabelecer as classes de equivalência ().

Um dos problemas relacionado aos critérios funcionais é que muitas vezes a especificação do programa é feita de modo descritivo e não formal. Dessa maneira, os requisitos de teste derivados de tais especificações são também, de certa forma, imprecisos e informais. Como consequência, tem-se dificuldade em automatizar a aplicação de tais critérios, que ficam, em geral, restritos à aplicação manual. Por outro lado, para a aplicação desses critérios é essencial apenas que se identifiquem as entradas, a função a ser computada e a saída do programa, o que os tornam aplicáveis praticamente em todas fases de teste (unidade, integração e sistema). No caso do TDD, essa é a técnica de teste mais utilizada pois é sempre a partir do entendimento da especificação do que será construído que os testes são desenvolvidos ().

Tamanho do identificador

Primeiro caractere é uma letra

Demais caracteres são letras ou dígitos

Desse modo, têm-se o conjunto de teste T0=T_0 = T0​= {("a1", Válido), ("", Inválido), ("2B3", Inválido), ("Z-12", Inválido), ("A1b2C3d", Inválido) } como sendo um conjunto adequado para o critério Particionamento em Classe de Equivalência, considerando as partições definidas.

De acordo com , a experiência mostra que casos de teste que exploram condições limites têm uma maior probabilidade de encontrar erros. Tais condições correspondem a valores que estão exatamente ou imediatamente acima ou abaixo dos limitantes das classes de equivalência.

Assim, esse critério é usado em conjunto com o Particionamento de Equivalência, mas ao invés dos dados de teste serem escolhidos aleatoriamente, eles devem ser selecionados de forma que o limitante de cada classe de equivalência seja explorado. Segundo , além da escolha seletiva dos dados de teste, o outro ponto que difere este critério do Particionamento de Equivalência, é a observação do domínio de saída, diferentemente de outros autores, que já fazem essa consideração no próprio critério de Particionamento de Equivalência.

Embora não existam diretrizes bem definidas que levem à determinação dos dados de teste, sugerem que as seguintes recomendações sejam seguidas:

se a condição de entrada especifica um intervalo de valores, devem ser definidos dados de teste para os limites desse intervalo e dados de teste imediatamente subsequentes, que explorem as classes inválidas vizinhas desse intervalo. Por exemplo, se uma classe válida estiver no intervalo [1..100][1..100][1..100], os seguintes dados de teste devem ser derivados: 0, 1, 2, 99, 100 e 101. Ou seja, o limite, e um elemento abaixo (inválido) e um acima (válido) do limite.

Tamanho do identificador

Primeiro caractere é uma letra

Demais caracteres são letras ou dígitos

Para facilitar a geração dos casos de teste considere utilizar a para identificação dos símbolos válidos e inválidos de cada classe. Como pode ser observado, o critério Análise do Valor Limite pode ser considerado mais rigoroso pois exige bem mais casos de testes, e também satisfaz os requisitos demandados pelo critério Particionamento em Classe de Equivalência.

ttt
1≤t≤61 \le t \le 61≤t≤6
t≤0t \le 0t≤0
t>6t > 6t>6
ccc
xxx
ttt
1≤t≤61 \le t \le 61≤t≤6
t≤0t \le 0t≤0
t>6t > 6t>6
ccc
(a≤c≤z)∨(A≤c≤Z)(a \le c \le z) \lor (A \le c \le Z)(a≤c≤z)∨(A≤c≤Z)
(c<a∨c>z)∧(c<A∨c>Z)(c \lt a \lor c \gt z) \land (c \lt A \lor c \gt Z)(c<a∨c>z)∧(c<A∨c>Z)
xxx
(a≤x≤z)∨(A≤x≤Z)∨(0≤x≤9)(a \le x \le z) \lor (A \le x \le Z) \lor (0 \le x \le 9)(a≤x≤z)∨(A≤x≤Z)∨(0≤x≤9)
(x<a∨x>z)∧(x<A∨x>Z)∧(x<0∨x>9)(x \lt a \lor x \gt z) \land (x \lt A \lor x \gt Z) \land (x \lt 0 \lor x \gt 9)(x<a∨x>z)∧(x<A∨x>Z)∧(x<0∨x>9)
Pezzè e Young (2007)
Delamaro et al. 2016
Delamaro et al. 2016
Copeland, 2004
Percival, 2017
Myers et al. (2011)
Myers et al. (2011)
Myers et al. (2011)
Tabela ASCII
Delamaro et al. 2016
Relacionamentos entre Conceitos de Teste
(e)