Verificação e Testes de Programas

Verificação e Testes de Programas

A  etapa de design de software (do modelo conceitual, da interface e da arquitetura) visa encontrar as soluções que satisfaçam os requisitos do software. No design as  soluções são especificadas através de formalismos e modelos que possibilitam diferentes visões do software. Entretanto, para que o software funcione é preciso que as ideias concebidas durante do design seja codificadas em uma linguagem de programação para que possam ser traduzidas e executadas num computador, é neste ponto onde entra a verificação e testes de programas.

O programa produzido durante esta etapa pode conter falhas ou erros. Os erros podem ser ocasionados por diversos fatores. Um deles pode ser a interpretação errada dos modelos produzidos durante o design. Em outros casos o programador interpretou erradamente os comandos de um programa. A complexidade de um programa, seja pela complexidade de um algoritmo ou pelo seu tamanho, pode levar ao programador a gerar um software com bastante erros de funcionamento.

Definir o que é um erro ou falha num software não é uma tarefa simples. Podemos simplificar dizendo que um erro é quando o software não se comporta conforme foi especificado. Isto pode ocorrer quando o software não realiza um função esperada, fornece resultados não esperados, não consegue terminar quando esperado, etc.

Para se avaliar o funcionamento do teste é preciso definir quais os critérios necessários para consideramos que o mesmo está correto ou não, isto é, o que pode ser considerado um erro ou falha. Além disso, é preciso determinar quais métodos ou técnicas para verificação do funcionamento serão empregadas.

Este capítulo aborda as várias formas de verificar a correção do funcionamento de um software, ou simplesmente verificação de programas. Serão vistos alguns métodos e técnicas que permitem avaliar um programa tentando verificar se o mesmo está correto ou não.

8.1 Verificação de Programas e Qualidade de Software

Vimos no capítulo 1 que vários são os fatores que determinam a qualidade de software. Cada um destes fatores precisam ser considerados para garantirmos a qualidade do software. Para isto deve-se utilizar técnicas para avaliação e análise de cada um dos fatores de qualidade do software.

Os fatores de qualidade de software podem ser classificados em do processo ou do produto e internos e externos. Os fatores de qualidade do processo visam assegurar a qualidade do desenvolvimento do produto em todas as suas etapas. Os fatores relacionados ao produto permitem analisar a qualidade do software em si.

Embora todos os fatores sejam importante para a qualidade final do software, podemos destacar alguns deles como fundamentais para que o software exista com um produto que funcione em máquinas reais e resolva problemas dos usuários.

McCall classifica os fatores de qualidade do produto em três categorias:

  • fatores operacionais – aspectos relacionados com o funcionamento e utilização do software
  • fatores de revisão – relacionados com a manutenção, evolução e avaliação do software
  • fatores de transição – relacionados com a instalação, reutilização e interação com outros produtos

A categoria dos fatores operacionais relaciona alguns daqueles que são essenciais e indispensáveis para o funcionamento e utilização do software. Dentre os fatores que se enquadram nesta categoria podem citar:

  • correção
  • eficiência ou desempenho
  • robustez
  • integridade
  • confiabilidade
  • validade
  • usabilidade

A usabilidade engloba outros fatores relacionados com a utilização do software pelo seus usuários. Dentre os fatores da usabilidade podemos citar a utilidade, facilidade de uso, facilidade de aprendizado, a produtividade do usuário, a flexibilidade no uso e a satisfação do usuário. A avaliação da usabilidade de um software está diretamente relacionada à sua interface de usuário. Existem métodos e técnicas especificas para avaliação da usabilidade. Podem ser realizados, por exemplo, testes com os usuário que permitam medir alguns fatores de usabilidade ou aplicados questionários que avaliem a opinião dos usuário. A avaliação da usabilidade é objeto do Design de Interfaces de Usuário e não será considerado aqui.

A validade de um software é o fator que considera que o software está de acordo com os requisitos funcionais e não-funcionais que foram determinados durante a etapa de análise e especificação de requisitos. Um software correto não é necessariamente um software válido, mas a validação requer que ele esteja correto.

A confiabilidade de um software é uma qualidade subjetiva que depende de outros fatores como a correção, eficiência, robustez e integridade. Um software passa a ser confiável para os clientes e usuários quando o mesmo esta correto, realiza as tarefas de forma eficiente, funciona bem em situações adversas e que não permite violações de acesso ou danos a seus componentes.

A correção de um software é, portanto, apenas um dentre os muitos fatores de qualidade de um software que precisam ser avaliados. Entretanto ela é fundamental para que várias outros fatores de qualidade possam ser avaliados. A correção avalia o programa que é quem faz com que o software funcione e seja útil para alguém.

8.2 Formas de verificação de programas

A correção pode ser verificada de diversas maneiras. Mas não basta apenas verificar. É preciso identificar qual a falha ou erro e corrigir. Mais ainda, é preciso garantir que o software está livre de erros ou, pelo menos, que contenha um número muito pequeno de erros que não foram detectados.

Na correção de um programa é importante diferenciar erros de sintaxe de erros de semântica. Os erros de sintaxe ocorrem quando o programa não escrito corretamente, isto é, de acordo com a gramática formal da linguagem de programação e com as palavras chaves (comandos, tipos, identificadores, etc.) escritos corretamente. Os erros de sintaxe são normalmente detectados pelo analisador sintático do compilador ou interpretador da linguagem.

Os erros de semântica ocorrem por problemas de interpretação das instruções da linguagem. Estes erros são também conhecidos como erros de lógica de programação e tem uma interferência direta no funcionamento do programa. Os erros de semântica quase sempre ocorrem por uma interpretação equivocada do programador. Ele espera que o computador execute as instruções de uma determinada maneira quando na verdade ele está realizando de outra maneira. Como a semântica de uma linguagem de programação é definida de forma rigorosa, é normalmente o programador quem causa o erro de semântica. A verificação de programas tem por objetivo detectar os erros de semântica de um programa.

Existem diversas  formas de verificar se o funcionamento de um programa está correto ou não. Vamos considerar aqui três categorias de verificação:

  • inspeção de programas
  • testes de funcionamento
  • prova formal

A inspeção é uma forma analítica de verificação da correção na qual o código fonte do programa é analisado diretamente. Ela  pode ser estática ou dinâmica. A inspeção estática é feita mentalmente, num processo no qual o inspetor (que pode ser o próprio programador) percorre o código executando mentalmente cada uma das instruções. Este processo é denominado de rastreamento do código fonte.

A inspeção dinâmica é realizada com o auxílio de uma ferramenta de depuração (debugger). Estas ferramentas permitem a execução passo-a-passo de trechos do programa e a visualização de variáveis do programa.

Normalmente estas técnicas de inspeção são aplicadas para corrigir um erro já detectado em um programa, pela aplicação de testes de funcionamento.

Os testes de funcionamento têm por objetivo a detectar o maior número possível de erros. Deve-se executar o programa de maneira a forçar certos limites para os erros possam ser encontrados. Os testes não podem garantir que não existam erros num software, exceto em casos muito de programas muito simples. Em programas que possuam estrutura de controle como a repetição o número de caminhos possíveis de execução aumenta bastante de maneira a tornar inviável o teste exaustivo de todas as situações. É necessário definir os casos de teste de maneira que seja possível que os caminhos possíveis possam ser testados.

Os teste de funcionamento podem ser divididos em testes em ponto pequeno ou teste de unidades e em teste em ponto grande ou teste de integração.  Os teste de unidades visam verificar o funcionamento dos componentes, módulos ou unidades funcionais isoladamente. Os  testes de integração verificam se os componentes funcionam corretamente após a integração com os outros componentes.

A prova de programa é a forma mais precisa de verificar se um programa está correto ou não. Ela pode garantir que um programa está livre de erros. Isto é possível por um programa é um objeto formal, isto é, definido por uma linguagem de programação formal de base matemática. Podemos explicar esta idéia de forma simples.

Cada sentença de um programa é uma instrução para o computador realizar uma certa atividade. Este comportamento é o significado ou semântica da sentença do programa. para que o comportamento do computador seja sempre o mesmo para cada instrução, a semântica dos elementos de uma linguagem de programação deve ser definida formalmente. Desta forma se espera que cada elemento de um programa provoque uma transformação precisa em outros elementos. Analogamente, a combinação das instruções deve possibilitar mudanças também previsíveis no programa. Assim, espera-se todo um programa altere sempre o estado de outros elementos do programa da mesma maneira. Pode-se então provar que para uma dada condição inicial chega-se a uma condição final se as instruções forem executadas.

Exemplificando, vamos considerar inicialmente uma instrução de um programa Pascal

{x=5}
x := x + 1;
{x=6}

A expressão {x=5} indica a condição da variável antes da execução da instrução, enquanto que {x=6} mostra a situação após a execução da instrução. De acordo com a semântica da instrução pode-se garantir a condição final da variável é sempre a inicial incrementada de 1. Isto pode parecer óbvio numa única e simples instrução, mas torna-se um recurso bastante valioso quando temos um conjunto complexo de instruções. Por outro lado, a complexidade e os custos da aplicação de métodos de prova formal em programas muito grande é enorme.

8.3 Uma introdução à prova de programas

Para aplicarmos os métodos de prova é necessário recorrer às notações matemáticas baseadas em lógica. O cálculo de predicados, por exemplo, permite expressar as condições de programa e as regras de prova com base na semântica das instruções de uma linguagem. Linguagens de especificações formais com Z, VDM ou B, são também bastante utilizadas para prova de programas. Aliás, uma das grandes vantagens da aplicações de métodos formais em engenharia de software é que se pode provar matematicamente que um programa está correto em relação à sua especificação formal. Algumas ferramentas possibilitam a realização de provas automáticas, diminuindo a complexidade e os custos do método.

De uma forma geral a prova de programa requer  condições que devem ser expressas numa notação matemática e regras de provaque podem ser aplicadas de acordo com as instruções de um programas. Expressando as instruções por S (statements) e as condições por {C} podemos dizer que:

{C1} S1 {C2}  e   {C2} S2 {C3}

Que indica a instrução S1 modifica o programa de uma condição C1 para uma condição C2 e as instrução S2 de C2 para C3.

Quando queremos mostrar que um programa ou trecho de programa está correto indicamos qual a condição final (ou pós-condição) que deve ser atingida para uma certa condição inicial (pré-condição)

{Pré} programa {Pós}

No caso de um programa que realiza a divisão de dois números positivos a expressão de prova seria:

{y>0 & x>0} programa-divisão {y = x*q + r}

onde q é o quociente e r o resto. Mais adiante mostraremos

Uma regra de prova é expressa por uma notação do tipo:

E1, E2   E3

Indica que se E1 e E2 tenham sido provados, então deduzimos que E3 também é verdade. Por exemplo, a regra que vale para uma seqüência de instruções é a seguinte:

{C1} S1 {C2}, {C2} S2 {C3}       {C1} S1;S2 {C3}

Da mesma forma teríamos regras para as outras principais estruturas de controle como repetição e seleção. Vejamos o caso de uma repetição. Seja o trecho de um programa e as condições iniciais de sua variável:

{x >= 0}
while (x>0) do
	x:= x - 1;
end while
{x = 0}

Aplicando as regras de prova da repetição e da atribuição podemos provar que o programa está correto, isto é que para a condição inicial {x>=0} teremos a condição final {x=0}. A regra da repetição pode ser descrita como

               {Invariante & ExprCond} S {Invariante}             {Invariante}while (ExprCond) S {Invariante & not ExprCond}

Onde ExprCond é a expressão condicional do while e Invariante é uma expressão que deve ser verdade em todo o loop do while, e também antes e depois da sua execução. A idéia básica é que se o corpo S do while não torna o invariante falso — {Invariante & ExprCond} S {Invariante} — caso a ExprCond seja verdadeira, então deduz-se que a expressão inferior é verdadeira. Aplicando ao programa acima temos que o invariante é {x>=0} e a regra fica:

        {x>=0 & x>0} x := x – 1; {x>=0}             {x>=0}while (x>0) x := x – 1{x>=0 & not x>0}

Podemos verificar facilmente que a expressão de cima é verdadeira. Com base na regra podemos deduzir que a expressão inferior é verdadeira. Como {x>=0 & not x>0} é o mesmo que {x>=0 & x<=0}, temos que {x=0} o que está de acordo como o nosso programa.

Usando o mesmo método podemos provar que o programa abaixo realiza corretamente uma divisão de y por x:

{y>0 & x>0}
r=y;
q=0;
while (r >= x) begin
	q := q + 1;
	r := r - x;
end;
{y = x*q + r & x>r>=0}

O invariante deste programa é y = x*q + r, que é a expressão que indica uma divisão e que gostaríamos que fosse válida ao final. A prova fica como exercício.

8.4 Testes de correção

O teste  é a maneira mais comum de fazermos a verificação da correção de um programa. Os testes consistem na execução controlada do programa com o objetivo de analisar o seu comportamento para verificar se ele comporta-se como esperado. A limitação de um teste está em ele poder identificar que existem erros, mas não poder garantir que erros não existem.

Vimos que podemos diferenciar os testes em testes de ponto pequeno e teste de ponto grande. Os teste de ponto pequeno ou de unidades possibilitam verificar trecho isolados de um programa, normalmente um componentes ou módulo. Os principais tipos de teste de ponto pequeno são os testes da caixa branca e os testes da caixa preta.

Os testes em ponto grandetem por objetivo verificar a correção de conjuntos de componentes interconectados. Eles são aplicados a componentes como um todo.

8.4.1 Fundamentos

A idéia fundamental por trás de um teste pode ser explicada de forma simples. Seja P um programa e D e I o domínio e a imagem, respectivamente. O domínio refere-se aos valores iniciais ou de entrada de D e I os valores resultantes ao final da execução de P. Por simplicidade, vamos considerar P que se comporta com uma função com domínio D e I. Obviamente, em casos reais, D e I podem conter seqüências de dados e P pode ter várias funções de entrada/saída.

Seja R os valores resultantes desejáveis determinados durante a especificação. Seja d dados do domínio D, dizemos que P(d) refere-se aos possíveis resultados de P para os dados iniciais d. Dizemos que um programa está correto se P(d) satisfaz R. P está correto se e somente se para todo dado d, P(d) satisfaz R. Dizemos que um programa nãoestá correto se o programa não termina de executar, ou se termina mas P(d) não satisfaz R.

A presença de um erro é demonstrada pela existência de dados d, tal que P(d) não satisfaz R. Muitas vezes é impossível verificar P(d) para todos os dados d do domínio D. Nestas situações é importante elaborar casos de testes.

Um caso de teste é um elemento d de D. Um conjunto de casos de teste T é um subconjunto de D. Um conjunto de teste T é dito ideal se, sempre que P for incorreto, existe um d pertencente a T que faz P(d) não satisfazer a R.

A escolha dos casos de teste é a etapa mais importante durante a realização de um teste. Como o objetivo é encontrar erros, deve-se escolher os casos de teste que force a detecção deles. Esta escolha depende do tipo de teste que podemos aplicar.

Vejamos um exemplo de como a escolha de casos de testes é deve ser criteriosa. Suponha o programa que verifica o valor máximo de dois números.

read(x); read(y);
if (x>y) then
	max := x;
else
	max := x;
end if;
write(max);

Se escolhermos como caso de teste os valores {x=3, y=2; x=4, y=3; x=5, y=1; x=10, y=5} nenhum deles revelará a existência de erro. Entretanto, com apenas dois casos de testes escolhidos com base na lógica do programa {x=3, y=2; x=2, y=3}, que explora o fato de que um teste comparativo é feito, revela o erro no segundo caso de teste. Ter muitos casos de testes não é garantia de testes bem-sucedidos. Mais importante é escolher casos de testes que ajudem a identificar erros.

Resumindo, as regras gerais para se realizar um  teste:

  1. Executar um programa com a intenção de descobrir um erro
  2. Um bom caso de teste é aquele que tem uma elevada probabilidade de revelar um erro ainda não descoberto.
  3. Um teste bem-sucedido é aquele que revela um erro ainda não descoberto.

8.4.2 Testes da caixa branca

Os teste da caixa branca estão baseados nos elementos internos de um trecho de programa.O objetivo é encontrar o menor número de casos de teste que permita que todos os comandos de um programa seja executado pelo menos uma vez. Os casos de teste são determinados a partir das estruturas de controle do programa. A idéia é escolher os casos de teste de forma a forçar que todos os caminho possíveis do fluxo de controle do programa sejam percorridos durante os testes. O teste do caminho básico, o teste de loops (laços) e o teste de estruturas de controles são tipos de teste da caixa branca.

No teste do caminho básico, o passo inicial  é determinar todos os caminhos possíveis. Para isto costuma-se elaborar um grafo de fluxo de controle do programa. O gráfico permite identificar os caminhos possíveis para que se possa elaborar os casos de uso. Como cada caminho é definido pelas expressões condicionais das estruturas de controle, deve-se determinar os casos de teste escolhendo valores de variáveis para os casos nos quais cada uma das expressões sejam verdadeiras ou não.

Vejamos um exemplo para um programa que calcula o máximo divisor comum (MDC) de dois inteiros.

read(x); read(y);
while x≠y do
	if (x>y) then
		x := x - y;
	else
		y := y - x;
	end if;
end while;
write("MDC=",x);

Observe que a estrutura de controle while possui dois caminhos possíveis. A condição do while sugere dois possíveis casos de teste. Um deles é para os valores de x=y e o outro é para valores de x≠y. No primeiro caso testa-se o programa para que o while não seja executado. No segundo, testa-se para que ele seja executado pelo menos uma vez.

No corpo do while temos uma estrutura de controle de seleção (if … then … else). Esta estrutura possibilita dois caminhos possíveis. A expressão condicional desta estrutura sugere mais dois casos de teste para os dois caminhos. É preciso escolher pelo menos um caso de teste no qual tenhamos x>y e outro no qual tenhamos x≤y. Combinando todas as possibilidades podemos definir quatro casos de teste.

  1. x=y e x>y
  2. x=y e x≤y
  3. x≠y e x>y, que pode ser reduzido x>y
  4. x≠y e x≤y, que pode ser reduzido x<y

Que podem ser reduzidos a três casos:

  1. x=y
  2. x>y
  3. x<y

Com isto cobrimos todos os caminhos possíveis.

Para casos de programas mais complexos podemos usar o grafo de fluxo de controle para determinarmos a o número de caminhos possíveis.

Seja um trecho de programa que calcula a média aritmética de 100 números ou menos que se situem entre valores-limite mínimo e máximo. Ele também computa a soma e o número total válido.

i = 1;
total.entrada = total.valido = 0;
soma= 0;
while valor[i] != -999 && total.entrada < 100 {
	total.entrada++;
	if valor[i] ≥ minimo && valor[i] ≤ maximo {
		total.valido++;
		soma = soma + valor[i];
	}
	i++;
}
if total.valido > 0
	media = soma/total.valido;
else
	media = -999;

O grafo de fluxo é derivado da seguinte maneira. Cada comando simples é representado por um nó. Cada estrutura de controle é representada por um grafo como mostra a figura a seguir. Para as estruturas de controle que possuem expressões condicionais, cada expressão é representada por um nó do grafo. Caso a expressão condicional seja composta por várias expressões condicionais, um nó para cada expressão deve ser representado no grafo.

Para o programa da média temos, portanto, o seguinte grafo de fluxo.

O número de caminhos possíveis pode ser determinado a partir do grafo de fluxo de várias maneiras:

  • Pelo número de regiões do grafo
  • Pela fórmula E – N + 2, onde E é o número de elos e N o número de nós (N)

No exemplo temos que o número de caminhos possíveis é 4.

  • O grafo tem 6 regiões
  • O grafo tem 17 elos e 13 nós, portanto, 17 – 13 + 2 = 6.

Os caminhos possíveis são:

  • Caminho 1: 1-2-10-12-13
  • Caminho 2: 1-2-10-11-13
  • Caminho 3: 1-2-3-10-11-13…
  • Caminho 4: 1-2-3-4-5-8-9-2…
  • Caminho 5: 1-2-3-4-5-6-8-9-2…
  • Caminho 6: 1-2-3-4-5-6-7-8-9-2

As reticências depois dos caminhos 4 a 6 indicam que qualquer caminho ao longo do restante já foi coberto pelos caminhos possíveis.

Os casos de teste devem ser escolhidos com base nas expressões condicionais que forcem o programa a percorrer cada um dos caminhos possíveis.

  • Casos de teste do caminho 1:
    • valor[1] = -999
    • Resultado esperado: média = -999 e outros totais com os valores iniciais
  • Casos de teste do caminho 2:
    • Para testar este caminho é preciso forçar que a média seja calculada
    • Utilizar:
      • 0 < k1, …, kn  < i ≤ 100
      • minimo ≤ valor[k1],…, valor[kn] ≤ maximo
      • valor[i] = -999
    • Resultado esperado: valor da média calculado corretamente baseado nos k valores e totais com valores apropriados
  • Casos de teste do caminho 3:
    • Utilizar:
      • 0 < k1, …, kn ≤ 100 < i e
      • minimo ≤ valor[k1],…, valor[kn] ≤ maximo e
      • valor[i] = -999
    • Resultado esperado: valor da média calculado corretamente baseado nos 100 primeiros valores e total.valido=n e total.entrada=n
  • Casos de teste do caminho 4:
    • Utilizar:
      • 0 < k1, …, kn  < i ≤ 100 e
      • valor[k1],…,valor[kj]  < minimo e
      • minimo ≤ valor[kj],…, valor[kn] ≤ maximo e
      • valor[i] = -999
    • Resultados esperados: valor da média calculado para os valores de kj a kn e total.valido=j e total.entrada=n
  • Casos de teste do caminho 5:
    • Utilizar:
      • 0 < k1, …, kn  < i ≤ 100 e
      • minimo ≤ valor[k1],…, valor[kj] ≤ maximo e
      • valor[kj],…, valor[kn] > maximo e
      • valor[i] = -999
    • Resultados esperados: valor da média calculado para os valores de k1 a kj e total.valido=n-j e total.entrada=n
  • Casos de teste do caminho 6:
    • Utilizar:
      • 0 < k1, …, kn  < i ≤ 100 e
      • maximo ≤ valor[k1],…, valor[kn] ou valor[k1],…, valor[kn] ≤ minimo e
      • valor[i] = -999
    • Resultados esperados: valor da média = -999 e total.valido=0 e total.entrada=n

8.4.3 Testes da caixa preta

Os testes da caixa preta são chamados de testes funcionais por estarem baseados nos requisitos funcionais do software. Espera-se poder verificar aquilo que se pretende que o programa faça. Exemplos de técnicas de teste da caixa são os grafos de causa-efeitotestes baseados em tabela de decisão e teste do valor limite.

O teste da caixa preta não é uma alternativa ao teste da caixa branca, mas uma abordagem complementar.Ele permite verificar a validade do software em relação aos requisitos. Por exemplo, suponha que o cliente solicitou que o software calculasse o valor médio das três notas dos alunos. O desenvolvedor construiu uma função que calcula a média aritmética. Os teste da caixa-preta devem permitir verificar que a função implementada não é a função correta.

De acordo com os requisitos, a média deve ser calculada pela fórmula media = (a*4 + b*5 + c*6)/15. Desta forma, para o caso de teste cujos valores sejam {a = 2, b=3, c=4}, o valor esperado é 3,1333, e para o caso {a = 5, b=6, c=8}, o valor esperado é 6,5333.

Aplicando alguma técnica de teste da caixa preta chega-se ao valor media = 3, para o primeiro caso de teste e media = 6,333 uma vez que o desenvolvedor implementou uma função que calcula a média aritmética e não a média ponderada.

Uma das técnicas utilizadas para o teste da caixa-preta utiliza grafos de causa-efeito. Esta técnica oferece um representação concisa  das condições lógicas e das ações correspondentes. A técnica segue 4 passos:

  1. Causas (condições de entrada) e efeitos (ações) são relacionados para um módulo e um identificador é atribuído a cada um.
  2. Um grafo de causa-efeito (descrito a seguir) é desenvolvido.
  3. O grafo é convertido numa tabela de decisão.
  4. As regras da tabela são convertidas em casos de teste.

Considere como exemplo um programa que realiza a cobrança de chamadas telefônicas. Os valores de cada chamadas são contabilizados de acordo com a duração, local de destino (para onde for feita a chamada) e faixa de horário.

  • Se o local de destino for o mesmo da origem (chamada local) e a faixa de horário for das 6:00 às 23:59 então valor do minuto é R$ 1,00.
  • Se chamada local e a faixa for 0:00 às 5:59 o valor do minuto de cada chamada é R0,50.
  • Se o local for um outro estado no país (chamada interurbana) e a faixa de horário for das 9:00 às 21:00 então o valor do minuto é calculado de acordo com o valor básico por estado.
  • Se chamada interurbana e faixa de horário for das 21:00 às 9:00 o valor do minuto é fixo, sendo R$1,00.
  • Se chamada internacional o valor não depende de faixa de horário e é calculado de acordo com o valor básico por país.

Para o programa cobrança temos então as causas

  • tipo da chamada: local (CL), interurbana (DDD) e internacional (DDI)
  • faixa de horário: 6-24, 0-6, 9-21, 21-9
  • estado ou país: AC,AM, AP, … (estados do Brasil), EUA, RU, JP, …

Os efeitos esperados são os cálculos de cobrança conforme especificado

  • F1= duração*R$1,00
  • F2= R$0,50
  • F3= duração*valor_localidade

O grafo de causa-efeito para a especificação acima é o seguinte:

Com base no grafo de causa-efeito a seguinte tabela de decisão pode ser elaborada.

CL X X
DDD X X
DDI X
6-24 X
0-6 X
9-21 X
21-9 X
valor_localidade X X
F1 F1 F2 F3 F3

Com base no grafo ou na tabela acima podemos derivar cinco casos de teste nos quais podemos verificar se para as entradas correspondentes (causas) o programa realiza os cálculos correspondentes (efeitos).

  • Caso1:  {tipo_da_chamada=CL, faixa_de_horário=6-24, valor_localidade=X}
  • Caso2:  {tipo_da_chamada=DDD, faixa_de_horário=21-9, valor_localidade=X}
  • Caso3:  {tipo_da_chamada=CL, faixa_de_horário=0-6, valor_localidade=X}
  • Caso4:  {tipo_da_chamada=DDD, faixa_de_horário=9-21, valor_localidade=X}
  • Caso5:  {tipo_da_chamada=DDI, faixa_de_horário=Y, valor_localidade=X}

Um outro tipo de técnica para os teste da caixa-preta pode ser utilizada para completar a técnica de causa-efeito. A técnica de análise do valor limite visa estabelecer casos de testes nos quais os valores de limites extremos serão avaliados.

Para o exemplo anterior poderíamos criar casos que testassem valores de faixa de horário próximos ao limite. Por exemplo, 5:59, 6:00, 6:01, 23:59, 0:00, 0:01,  e assim da mesma forma para as outras faixas de horário.

8.4.4 Testes em ponto grande

Fonte: http://www.dimap.ufrn.br/~jair/ES/c8.html

Sobre a DANRESA – Com mais de 14 anos de experiência no mercado de TI, a DANRESA é uma Consultoria de Informática com atuação em todo o território nacional, focada em duas linhas de serviços principais e complementares: Fábrica de SoftwareDesenvolvimento de Sistemas, Infraestrutura e Outsourcing de TI. A área de Desenvolvimento é voltada a Projetos de Negócios por meio de Sistemas Personalizados de TI de acordo com a especificidade de cada cliente, realizando levantamento dos processos, análise e programação através de sua fábrica de software ou com profissionais alocados no cliente. Já a área de Infraestrutura inclui serviços como Outsourcing de TI, Gerenciamento e Monitoramento de equipamentos de missão crítica como Servidores, Roteadores, Switches e Links de conectividade, Instalação e Manutenção de pontos de rede, voz e dados, Suporte Técnico por meio de Service Desk – em que os atendimentos são feitos por uma equipe especializada e certificada nas práticas do ITIL – entre outros. Com cerca de 400 colaboradores e 100 clientes, a DANRESA possui em sua carteira empresas como ANFAVEA, BASF (Suvinil), Ernst Young, Sem Parar, Schneider, CBC, Eurobras, Avape, Alves Feitosa Advogados, Instituto Airton Senna, Grupo Kaduna, CVC, WoodBrook, Salles Leite (Iguaçu Energia ), etc. Para mais informações, ligue: (11) 4452-6450