Sei sulla pagina 1di 99

PROCESSOS DE TESTE DE SOFTWARE

MARGRIT RENI KRUG

Editora Unisinos, 2015


SUMÁRIO

Apresentação
Capítulo 1 – O processo de teste de software
Capítulo 2 – Técnicas de teste
Capítulo 3 – Teste estrutural de software
Capítulo 4 – Teste baseado em erros (análise de mutantes)
Capítulo 5 – Automação do teste de software
Referências
Sobre a autora
Informações técnicas
APRESENTAÇÃO

Os softwares tornaram-se indispensáveis para o mundo dos


negócios, utilizados desde em pequenas empresas até em grandes
corporações, possuem status de sistemas auxiliares até sistemas críticos.
De acordo com Sommerville (2009), para os sistemas críticos, o item mais
importante é a confiança, uma falha nesses sistemas pode ocasionar
grandes problemas, com custos altíssimos para a organização ou perdas
irreversíveis. Falhas nos softwares são prejudiciais, independentemente
do tamanho e do tipo de organização, e, quando ocorrem, elas tendem a
ocasionar transtornos e prejuízos. Ao adquirir um software, tem-se o
objetivo de facilitar o dia a dia, simplificando, agilizando e tornando o
serviço ou as transações mais seguras (AMARAL et al., 2009).
O estudo Mercado Brasileiro de Software – Panorama e Tendências,,
realizado em 2012 pela ABES – Associação Brasileira das Empresas de
Software –, mostra que o Brasil obteve faturamento de 21,4 bilhões de
dólares no mercado de software e serviços, alcançando crescimento de
12,8% quando comparado a 2010. Por meio desse estudo, pode-se
visualizar a expansão desse mercado e a crescente utilização dos
softwares, com isso, percebe-se a necessidade de cada vez mais investir
na qualidade destes, pois, além de um diferencial, ela é essencial para a
boa utilização, a confiança do cliente e, também, para a empresa
fornecedora se destacar no mercado (ABES, 2012).
O aumento na utilização de softwares e a dependência das
informações para desempenhar diferentes atividades levam-nos a uma
preocupação quanto à qualidade do produto que está sendo desenvolvido.
Ao encontro da dependência diária do uso dos softwares pelo ser humano
e pelas organizações vem o fato de os softwares estarem cada vez mais
integrados e complexos, assim, existe a necessidade de que tudo esteja
funcionando de maneira correta, em que os requisitos funcionais e não
funcionais do software sejam plenamente atendidos. Isto levou ao avanço
da engenharia de software, em especial, pelo fato de os sistemas
computacionais terem passado a executar tarefas cada vez mais
complexas, o que levou a se exigir cada vez mais qualidade dos produtos
que chegam ao mercado.
Para assegurar a qualidade do software, a etapa de teste torna-se
indispensável no projeto e na implementação de um sistema. Um software
necessita ser bem planejado, bem projetado, codificado e testado.
Fundamentalmente, as técnicas de teste de software têm o objetivo de
detectar erros no código do programa (MYERS, 2004). O teste é, portanto,
uma atividade indispensável dentro do processo de desenvolvimento de
um sistema e de extrema importância para a garantia de qualidade do
projeto desenvolvido. Segundo Pressman (2011), o teste é um elemento
crítico para a garantia da qualidade de sistemas.
As técnicas de teste propostas pela literatura, que em muitos casos
não são aplicadas adequadamente nas empresas, talvez pelo fato de a
atividade de teste muitas vezes ser vista apenas como auxiliar do
desenvolvimento de software, separada das etapas de análise, projeto e
codificação. Com essa visão, os esforços gastos nessa atividade são
considerados “extras”.
Essa realidade deve mudar, pois as empresas deverão se
preocupar não mais apenas com a qualificação de seu processo de
desenvolvimento, mas também com a qualidade dos seus produtos, por
diferentes motivos, entre eles:

exigência do cliente: que está cada vez mais crítico e tem cada vez
mais acesso à informação, o que o possibilita comparar
diferentes produtos e serviços;
grande variedade de empresas desenvolvedoras de software: a
concorrência leva à necessidade de uma empresa se diferenciar
da outra, e com as atuais tecnologias existentes e a facilidade de
acesso a elas, todas as empresas têm chances de criar produtos
muitos semelhantes, o que irá diferenciá-los será a qualidade;
acesso à informação: os clientes estão mais informados e as
facilidades de comunicação levam mais rapidamente à
informação da ocorrência de um problema no fornecimento de um
produto ou serviço, tornando a visibilidade da empresa, por vezes,
comprometida.

Este livro tem como objetivo apresentar técnicas e estratégias que


podem ser utilizadas para compor um processo de teste de software em
uma organização.

A autora.
CAPÍTULO 1
O PROCESSO DE TESTE DE SOFTWARE
Este capítulo tem como objetivo apresentar uma reflexão sobre a importância de
definir e utilizar um processo de teste associado ao processo de software utilizado no
projeto de produtos de software. Algumas nomenclaturas utilizadas pelo teste de
software serão, também, apresentadas, além de contextualizar quando e como o teste
de software deve ser utilizado.

O teste sendo executado como uma etapa do processo de


desenvolvimento, e muitas vezes executado pelo próprio desenvolvedor e
pelos usuários, serve apenas para garantir que as especificações foram
implementadas (preocupa-se apenas com as funcionalidades do
software) (BASTOS, 2007). Por isso, a melhor maneira de testar um
software é ter um processo de teste definido e utilizado.
O teste de software, como por exemplo, no modelo cascata
(PRESSMAN, 2011), é aplicado ao final do ciclo de desenvolvimento, porém
ao longo dos anos e pela necessidade de agregar qualidade aos produtos
de software desenvolvidos torna-se importante planejar e aplicar
estratégias de teste (validação e verificação) o quanto antes e em paralelo
ao desenvolvimento do software. Assim, cria-se a necessidade de
implantar um processo de teste alinhado ao processo de
desenvolvimento.

1.1 Objetivos do teste de software

De acordo com Engholm (2010, p. 285),

O processo de teste de software tem por objetivo viabilizar a


execução de atividades relacionadas a teste de componentes de
software de aplicações desenvolvidas. Esse objetivo pode ser
alcançado pela utilização de planos e métodos preestabelecidos
e embarcados em processo de teste definido. Esse processo
compreende desde o preparo do ambiente de teste e roteiro a ser
utilizado na execução dos mesmos até a execução prática dos
testes e a elaboração dos relatórios de evidências e resultados
obtidos.

Para Myers (2004), o objetivo principal da atividade do teste de


software é o de encontrar defeitos: "A atividade de teste não pode mostrar a
ausência de 'bugs'; ela só pode mostrar se defeitos de software estão
presentes".
Esta parece ser uma abordagem bastante pessimista da atividade,
entretanto, provar que um programa está completamente correto é
considerado um problema não computável (MALDONADO, 1991). Tal visão
do problema faz com que a atividade de teste seja vista como um conjunto
de tarefas não produtivas, pois não geram produtos novos, que não
exigem criatividade e/ou desafios intelectuais para sua execução. Devido a
características similares às citadas, a maior parte dos desenvolvedores
acaba se dedicando mais às fases de análise, projeto e implementação,
do ciclo de desenvolvimento de software. O objetivo da atividade de teste
pode ser entendido da seguinte forma:

no início de cada fase verificar se esta etapa do projeto reflete


exatamente os requisitos e as definições da fase imediatamente
anterior, para com isso garantir que o produto encomendado e o
gerado pela atividade de desenvolvimento do software será o
mesmo através dos diferentes níveis de refinamento do projeto;
verificar se não existem erros de lógica no projeto e no código,
bem como no fluxo de dados, além de verificar se o entendimento
dos requisitos relacionados à interface, em todas as fases do
projeto;
identificar e interferir no erro, iniciando-se a depuração, sendo que
quanto antes for descoberta a falha, menos custoso será para
adequá-la;
ter em mente que, uma vez que errar é humano e a atividade de
desenvolvimento de software é um exercício bastante complexo,
os erros existem e devem ser descobertos, portanto, o sucesso
em um teste consiste em descobrir os erros e corrigi-los.

De acordo com Bastos (2007), o principal objetivo do processo de


teste é simplesmente encontrar o maior número possível de defeitos no
software. Para que esse objetivo seja alcançado, um documento básico
deve ser utilizado: os requisitos do negócio.
Gerar requisitos de teste baseados nos requisitos de negócio
facilita a obtenção dos objetivos do teste para determinada aplicação.
Deste modo, é possível garantir que todos os requisitos que precisam ser
testados sejam considerados, consequentemente, cobrem-se todas as
necessidades especificadas pelos usuários.
Segundo o BSTQB (2011), os testes podem possuir objetivos
diferentes: encontrar defeitos, ganhar confiança sobre o nível de qualidade,
prover informações para tomadas de decisão e prevenir defeitos. Assim,
mostra que a maturidade do processo de teste de uma empresa,
certamente, a levará a desenvolver softwares de melhor qualidade.
Pode-se afirmar que uma das fases da engenharia de software é o
teste de software, que tem como principal objetivo garantir que o produto
desenvolvido atinja um nível superior de qualidade. O teste é a única fase
do processo de vida de um software que é considerada “destrutiva”, pois
tenta provar que o produto gerado apresenta erros (SOMMERVILLE, 2009).
Porém, existem diversas definições sobre teste de software:

Glen Myers (1979) define que processo de teste deve executar um


programa com a intenção de encontrar defeitos.
Bill Hetzel (1987) define que teste deve ser qualquer atividade que
a partir de uma avaliação seja possível determinar se alcança ou
não os resultados desejados.
Pressman (2011) define que o objetivo do teste de software é
provar que o software não está funcionando corretamente ou,
ainda, mostrar a presença de erros.
Filho e Rios (2003) definem que o teste deve verificar se o produto
está desenvolvido conforme os seus requisitos, e se não está
fazendo o que não deveria fazer.

Outras definições poderiam ser citadas, mas todas elas querem


passar a informação que o teste de software busca avaliar o produto
conforme o que foi especificado.

1.2 Erro, falha e defeito

Para melhor entender os conceitos de teste, é necessário fazer


algumas diferenciações em relação aos conceitos de erro, defeito e falha.
Especialmente porque existem algumas diferenças conceituais dos
termos na literatura.
Conforme DeMarco (1991, p. 91),

É de conhecimento geral entre os analistas de software que


nunca se elimina o último defeito de um programa. Os defeitos
são aceitos como uma triste realidade. Esperamos eliminá-los
todos, um por um, mas nunca conseguiremos nos livrar deles.
Segundo o BSTQB (2011), o ser humano está sujeito a cometer um
erro (engano) na especificação, na modelagem, na modelagem ou no
código do software, que produz um defeito (chamado de b ug, em
referência ao inseto que foi encontrado em um relé de um computador em
1945). Se o defeito no código for executado, poderá causar uma falha, que
é facilmente percebida, pois gerará um resultado diferente do esperado
para aquela execução.
Portanto, o erro trata-se de uma ação humana, por exemplo, o não
entendimento de como executar um cálculo. Enquanto o defeito é causado
por um erro de entendimento, por exemplo, um código com a fórmula de
cálculo mal escrita. Assim, torna-se falha a tentativa de execução de um
defeito, no exemplo, a execução de um cálculo com geração de resultados
indevidos. A Figura 1 mostra uma analogia entre erro, defeito e falha.

Figura 1 – Erro, defeito e falha.


Fonte: elaborado pela autora.

Segundo Rios (2011), um erro é um problema introduzido pelo


programador, o defeito é o problema encontrado no software pelos
testadores e é decorrente de um erro e, por fim, a falha é o problema
ocorrido no software por um erro não detectado pelos testes.
Assim, quando Myers (2004) define que o objetivo do teste é
encontrar defeitos, entende-se que o foco do teste não é provar que as
funcionalidades estão corretas, mas sim buscar por inconsistências
difíceis de observar apenas pela execução do software sem critério.

1.3 O custo do teste

As fases de teste e manutenção consomem aproximadamente 60%


dos recursos utilizados no desenvolvimento de sistemas de software
(PRESSMAN, 2011). Os principais motivos para tal concentração de
recursos são:

o caráter "destrutivo" da atividade (pessoas tentando provar que o


que fizeram está errado);
sistemas mal especificados, em que há omissão de requisitos e
requisitos especificados erroneamente. Tal problema tem como
consequência a falta de uma especificação correta para
comparação das saídas geradas com as esperadas;
a rara utilização sistemática de técnicas de teste e manutenção,
em comparação às utilizadas nas primeiras fases de
desenvolvimento (análise, projeto e implementação);
a pequena quantidade de ferramentas que automatizem as
técnicas de teste e manutenção;
o caráter evolutivo dos sistemas de software, devido à adição de
funcionalidades e à sua evolução.

Portanto, a atividade de teste é o processo que executa um


programa com a intenção de descobrir um defeito. Um bom caso de teste
é aquele que tem uma elevada probabilidade de revelar um erro ainda não
descoberto. Então, um teste bem-sucedido é aquele que revela um erro
ainda não descoberto.
Se a atividade de teste for bem conduzida, ela descobrirá erros no
software e, como benefício secundário demonstrará que as funções de
software aparentemente estão trabalhando de acordo com as
especificações, que os requisitos de desempenho aparentemente foram
cumpridos. Além disso, os dados compilados quando a atividade de
testes é levada a efeito proporcionam uma boa indicação da confiab ilidade
de software e alguma indicação da qualidade do software como um todo.
Mas há uma coisa que a atividade de teste não pode fazer: demonstrar a
ausência de b ugs; ela só pode mostrar se defeitos de software estão
presentes.
Myers (2004) afirma que os testes realizados em pequenos
módulos (testes unitários) podem remover entre 30% e 50% dos defeitos
dos programas. Já os testes de sistema podem remover entre 30% e 50%
dos defeitos remanescentes. Desse modo, os sistemas podem ir para
produção ainda com aproximadamente 49% de defeitos, corroborando
com a afirmativa de Pressman (2011) de que é impossível garantir que um
software esteja 100% livre de defeitos. Por fim, as revisões de código
podem reduzir de 20% a 30% desses defeitos (MYERS, 2004). A Figura 2
mostra como o custo de encontrar defeitos durante o processo de
desenvolvimento pode crescer ao longo do avanço das etapas do projeto.
Figura 2 – A Regra 10 de Myers.
Fonte: adaptado de Galitezi (2012).

Do ponto de vista financeiro também pode ser verificado que quanto


mais cedo o problema for detectado, melhor. A regra 10 de Myers
estabelece que o custo da correção de defeitos tende a aumentar quanto
mais tarde forem detectados.
Com a aplicação de testes dentro de um processo de teste, o custo
de correção de defeitos na produção cai drasticamente (regra 10 de
Myers). O custo do software durante seu ciclo de vida, incluindo as fases
de desenvolvimento e de manutenção, tende a ser menor se ele for bem
testado (BASTOS, 2007).
O custo da verificação de software pode corresponder a mais da
metade do custo total do desenvolvimento e manutenção (PEZZÉ, 2008). O
uso de ferramentas de projeto e desenvolvimento associadas a um
processo definido e estruturado de desenvolvimento e teste pode reduzir a
frequência de erros, porém, ainda se está muito longe de produzir um
software livre de defeitos (PRESSMAN, 2011).
Incluir o processo de teste nas atividades do projeto de
desenvolvimento de um software vai um pouco além dos custos
relacionados à contratação de profissionais (testadores, analistas de
teste, líderes de teste etc.), aquisição de equipamentos e softwares de
apoio. Deve-se, também criar rotinas para apoiar essa atividade de
maneira adequada e eficiente, tais como a adição de etapas de validação
e documentação de apoio, além de definir quais serão as saídas do
processo (relatórios de incidentes e de evidência da aplicação do teste).
Além desses fatos, cabe ressaltar que, em algumas empresas, a
implantação de um processo de teste causa alguns incômodos
comportamentais, tais como (BASTOS, 2007):

o desenvolvedor tratar o testador como inimigo, pois o visualiza


como um profissional que está ali para apontar seus erros, e não
como um elemento que irá garantir que o produto que está sendo
desenvolvido tenha qualidade;
a equipe de teste não é qualificada, muitas vezes cria-se uma
equipe de teste com profissionais menos experientes e sem
conhecimento em estratégias e técnicas de teste de software;
a equipe de teste é responsável apenas pelo teste final e não se
envolve no seu planejamento.

1.4 Qualidade e teste de software

A dependência das empresas das funcionalidades de seus


softwares para manter e agilizar seus negócios exige que estes tenham
qualidade, porém, sem onerar o tempo de disponibilização e sem elevar o
seu custo (CRESPO et al., 2003). Para manter-se competitivo no mercado
de software, que se torna cada dia mais complexo, as empresas investem
cada vez mais em qualidade (GUERRA; COLOMBO, 2009). Segundo Maciel
et al. (2011, p. 2), “com a necessidade de alcançar maior qualidade na
construção de softwares as empresas sentem-se compelidas a modificar
suas estruturas organizacionais em busca de padrões de processos que
tragam qualidade a seus produtos e atividades desenvolvidas.”, essa
necessidade se torna perceptível com a crescente utilização de
normas/padrões no processo de software, tais como: CMMI, MPS.BR,
ISO/IEC 12207 e 15504.
Segundo informações da Softex (2011), as avaliações MPS
aumentaram nos últimos anos, dado que aponta para a crescente
preocupação em obter maior qualidade e controle sobre o processo de
desenvolvimento, “o atual mercado expressa sua objetividade ao controle
de qualidade dando ênfase na gestão de qualidade de processo” (MACIEL
et al., 2011, p. 3).
Na fase inicial da computação (décadas de 1950 e 1960), a
qualidade era uma responsabilidade exclusiva do programador, sendo que
padrões de garantia de qualidade para o software foram introduzidos no
desenvolvimento de software sob contrato militar durante a década de
1970. A partir daí, espalharam-se rapidamente para o desenvolvimento
comercial de software (PRESSMAN, 2011).
No entanto, a qualidade de software não está relacionada apenas à
qualidade do processo empregado em seu desenvolvimento, mas
também à satisfação percebida pelo usuário final. De acordo com Maciel et
al. (2011, p. 2) a norma ISO/IEC 9126 define qualidade de software como “a
totalidade de características de um produto de software que lhe confere a
capacidade de satisfazer necessidades explícitas e implícitas”, sendo as
explícitas as necessidades citadas pelos clientes e as implícitas as
necessidades subjetivas, que não são solicitadas, mas são consideradas
óbvias para o produto. Koscianski e Soares (2007) afirmam que a
qualidade do produto tem como objetivo a satisfação do cliente.
Uma das áreas da engenharia de software diretamente relacionada
à qualidade do produto de software é o teste de software. Como citam Rios
e Moreira (2006, p. 3), “Quando tratamos de testes, estamos também nos
referindo à qualidade do software. Não que sejam sinônimos, mas
certamente o nível de qualidade dos testes de um software é um fator
importante, entre outros, para definir a qualidade do produto final”.
A busca pela qualidade é realizada durante todo o processo de
desenvolvimento do software, toda a equipe precisa entender sua
importância e contribuir com esse objetivo. A qualidade é basicamente
dividida em duas partes: a qualidade de processo e a qualidade de
produto.
Segundo o BSTQB (2011), com a ajuda do teste é possível medir a
qualidade do software em termos de defeitos encontrados, por
características e requisitos funcionais e não funcionais do software, tais
como confiabilidade, usabilidade, portabilidade e manutenabilidade. O
resultado da execução dos testes pode gerar confiabilidade, pois quanto
mais defeitos forem encontrados e corrigidos, menor será o risco, em uma
execução futura, de uma falha.
Com a preocupação com a qualidade e a exigência dos
consumidores por softwares com custos e prazos cada vez menores, as
empresas sentiram a necessidade de investir mais em modelos e
processos de software, os quais auxiliam no desenvolvimento dentro dos
prazos, dos custos e da qualidade estipulada (MACIEL et al., 2011). Essas
empresas passaram, também, a dar maior visibilidade e investimento na
área de teste de software, que tem como objetivo verificar as
funcionalidades e características do produto (BRUNELI, 2006).
A etapa de teste faz parte do processo de desenvolvimento de
software, constando em diversos modelos e normas utilizados nas
organizações, porém, estudos indicam que existe uma tendência para a
terceirização do processo de teste (MOLINARI, 2011). Empresas que
desenvolvem softwares estão contratando empresas especializadas em
teste de software para a execução dessa etapa.
Os testes auxiliam a reduzir os possíveis defeitos a que o produto
possa estar suscetível. A palavra reduzir foi enfatizada, pois é tido como
impossível eliminar por completo todos os defeitos de um software.
Uma completa validação do programa, em qualquer estágio do ciclo
de vida, pode ser obtida através da execução do processo de teste para
cada valor de entrada possível. Se cada instância for bem-sucedida, o
programa foi verificado; senão, um erro foi encontrado. Este método é
conhecido como teste exaustivo e é a única técnica de testes que garantiria
a validade do programa. Lamentavelmente, não é viável. Na maior parte
dos casos, o domínio da função (conjunto de dados de entrada possíveis)
é infinito, ou quando finito, grande o bastante para fazer com que o número
de testes requeridos seja inviável.
Visando reduzir o número potencialmente infinito de testes do
processo de testes exaustivos para um número possível, deve-se
encontrar um critério para selecionar elementos representativos do
domínio da função. O critério selecionado deve refletir tanto a descrição
funcional quanto a estrutura do programa.
O subconjunto de elementos selecionado para ser usado no
processo de testes é chamado de conjunto de dados de teste ou test set.
No entanto, o problema é encontrar um test set adequado, que seja grande
o suficiente para englobar todos os valores válidos do domínio e
suficientemente pequeno para que se possa testar elementos de cada tipo
de entrada do conjunto.
A principal técnica de teste continua sendo executar o software
usando uma massa de testes que contenha dados representativos, como
entradas para o sistema ou módulo, e comparar a saída gerada com a
esperada. Diferenças representam falhas que devem ser corrigidas.
Um dos itens que têm sido mais estudados no contexto de
aprimoramento da qualidade de software é a questão de teste de software,
por ser uma forma de avaliar e agregar qualidade ao produto, reduzir
custos e retrabalho, melhorando a imagem da empresa e ampliando sua
capacidade competitiva.
1.5 Nomenclaturas do processo de teste de software

Segundo Guerra e Colombo (2009, p. 59), “O processo de testes de


software apresenta uma estruturação em etapas, atividades, artefatos,
papéis e responsabilidades que buscam a sistematização dos
procedimentos e controle dos projetos de testes.”, essas especificações
tornam-se necessárias para que haja controle dos testes e estes possam
ser reproduzidos de maneira eficiente sempre que necessário. Para
auxiliar nessa sistematização, existem os documentos básicos para a
execução do processo de teste que, segundo Filho e Rios (2003), são:
Guia operacional de teste; Estratégias de teste; Planos de teste; Roteiros
de teste; Casos de teste; Scripts de teste.
A parte mais visível do teste de software é a sua execução, porém,
para que ele atinja os seus objetivos, é necessário planejá-lo, dedicar
tempo ao seu planejamento, à modelagem dos casos de teste, à
preparação da execução e à avaliação dos resultados.
A estratégia de teste é um conjunto de decisões que devem ser
tomadas ao planejar o que, como e quando testar. Ao pensar nas
estratégias que serão utilizadas em um projeto de teste, deve-se levar em
consideração as regras de negócio da empresa e as prioridades dos
softwares que serão testados, assim a estratégia mistura tipos de teste
com técnicas de teste, que serão vistos nas próximas seções e capítulos.
Dependendo das características do software e do ambiente, e por que não
do usuário do software que está sendo testado, as estratégias podem ser
diferenciadas.
Para Pressman (2011), a estratégia de teste de software fornece um
roteiro que descreve os passos a serem executados como parte do teste,
define quando serão planejados e executados e quanto trabalho, tempo e
recursos irão necessitar. Portanto, qualquer estratégia de teste deve
incorporar planejamento dos testes, projeto de casos de teste, execução
dos testes, coleta e avaliação dos resultados.
Segundo BSTQB (2011), a estratégia de teste é a descrição de alto
nível dos níveis de teste a serem realizados dentro desses níveis feitos
para uma organização ou programa (um ou mais projetos).
O plano de teste definido pelo IEEE 829 (2008) é o documento que
descreve todo o planejamento do teste, tal como um projeto: com escopo,
abordagem, recursos e cronograma das atividades de teste. Deve definir o
que será testado e como será realizado (estratégias), deve detalhar as
tarefas a serem testadas e os responsáveis pelo teste de cada uma.
Também deve definir o ambiente de teste, os critérios de entrada e saída a
serem usados, além dos eventuais riscos associados ao projeto de teste.
Segundo Engholm (2010, p. 289), “O plano de teste delineia o
escopo, as aproximações, os recursos e o cronograma de todas as
atividades relacionadas aos testes do sistema, fazendo parte do controle
de qualidade do projeto”. Para Bastos et al. (2007, p. 114), “O plano de
teste é o documento que permitirá definir o nível de cobertura segundo o
qual os elementos mais críticos do software serão testados com
prioridade e com um nível de cobertura mais amplo”.
O plano de teste é o documento mais abrangente do projeto de
teste, dessa forma, mostra o projeto em toda sua dimensão. Sendo assim,
ele pode ser utilizado para dar suporte aos testadores mesmo quando o
software já estiver em operação e forem necessários novos testes devido
a alterações efetuadas. Ele também auxilia no gerenciamento dos
objetivos dos testes e delimita a sua cobertura, ou seja, indica os pontos
que devem receber a prioridade dos testes, seja pela questão de risco ao
negócio, seja pela importância do projeto (BASTOS et al., 2007).
Devido às características dos softwares, em especial atendendo às
demandas de portabilidade e, em alguns casos, multiplataformas, torna-
se necessário conter no planejamento do teste (plano de teste) os
ambientes necessários para aquela tarefa. Assim, segundo o IEEE 610, o
amb iente de teste contém hardware, instrumentação, simuladores,
ferramentas de software e outros elementos de suporte necessários para
a realização de um teste – preocupações que demandam recursos e
devem constar no cronograma e custo do projeto de teste.
Torna-se importante a definição dos cenários de teste, também
conhecidos como procedimentos de teste ou roteiros de teste, trata-se do
documento que especifica a sequência de ações para a execução de um
teste. Quando utiliza-se automatização do teste de software, esse roteiro é
chamado de script. Portanto, pode-se dizer que o cenário de teste é o
conjunto de casos de teste que serão executados para cobrir um ou mais
requisitos do software sob teste, aqui são abrangidas as regras de
negócio.
Como parte do plano de teste estão os casos de teste, que são
gerados conforme a estratégia e a técnica de teste escolhidas. Ele é
composto dos dados de teste e do resultado esperado. Os dados de teste
serão definidos no momento que são conhecidos os domínios de entrada
e saída do software a ser testado.
Segundo o BSTQB (2011), os casos de teste são os conjuntos de
valores de entrada, precondições de execução, resultados esperados e
pós-condições de execução para verificar o atendimento de um requisito
específico.
Como meio de aumentar as chances de testes bem-sucedidos,
além de pessoal técnico qualificado e infraestrutura adequada, é
necessário que o processo de teste seja bem definido e estruturado.
Alguém qualificado na área de testes poderá encontrar o melhor conjunto
de casos de testes para testar uma aplicação, já que é impossível testar
todas as possibilidades de um software. Esta impossibilidade vem da
característica do software ser composto por inúmeros comandos,
componentes e condições, tornando-se inviável testar todas as suas
possibilidades devido à sua complexidade e ao seu tamanho.
Desta forma a seleção dos casos de teste deve ser baseada nas
maiores probabilidades de encontrar um erro e nas áreas mais críticas do
negócio (MORAES; LAURINDO, 1999). De acordo com Amaral et al. (2009),
o teste deve ser criado com a intenção de descobrir o maior número de
erros possível. Desta forma, é possível conhecer e melhorar o sistema,
tornando-o mais seguro e confiável. Tendo em vista essas condições,
torna-se necessário alguém capacitado para a seleção do “conjunto de
casos de teste adequado, que seja grande o suficiente para englobar o
domínio e suficientemente pequeno para que se possa testar cada
elemento do conjunto. Desenvolver bons casos de teste é uma tarefa
complexa.” (KANNER, 2003 apud BRUNELI, 2006, p. 5).
Existe uma dificuldade em responder quando o teste deve terminar.
Pode-se dizer que o teste não termina, apenas se passa a
responsabilidade do teste para outro profissional, seja ele o
desenvolvedor, o testador ou o usuário. Porém, deve-se definir alguma
forma de quantificar o teste aplicado durante a fase de teste, para isto são
utilizadas as coberturas, que podem ser: cobertura de falhas, cobertura de
código e cobertura de testes.
O critério de cob ertura de testes permite a identificação de partes do
programa que devem ser executadas para garantir a qualidade do software
e indicar quando ele foi suficientemente testado (RAPPS; WEYUKER,
1985). Ou seja, determinar o percentual de elementos necessários por um
critério de teste que foram executados pelo conjunto de casos de teste. Isto
é, significa quantos casos de teste foram exercitados no roteiro utilizado.
Trata-se da razão entre o número de casos de teste gerados pela
estratégia escolhida e o número de casos de teste executados.
O critério de cob ertura de código determina os trechos de código
que foram ou não exercitados através da execução de um teste. De
maneira geral, um sistema para cobertura de código coleta informação
sobre o programa em execução e então combina isso com informações do
código-fonte para gerar um relatório sobre a cobertura de código de um
conjunto de testes. À medida que os testes são desenvolvidos, a cobertura
de código destaca aspectos do código que podem não estar sendo
adequadamente testados e que exigem testes adicionais. Este critério
indica duas situações importantes, se trechos do código não foram
executados pelos casos de teste gerados ou este trecho não precisa
existir ou os casos de teste não foram suficientes para a cobertura,
portanto deve-se gerar mais dados de teste e seus resultados esperados.
A cob ertura de falhas é utilizada em casos especiais, pois trata-se
de um teste demorado. Para ser aplicado, deve-se conhecer os tipos de
falhas às quais o software está sujeito, assim geram-se casos de teste
que no futuro poderão identificar as falhas. Este critério tem como
finalidade qualificar os casos de teste.

1.6 Ciclo de vida do teste

O ciclo de vida do teste de software pressupõe que testes sejam


realizados ao longo do ciclo de vida do projeto de desenvolvimento do
software, desse modo eles se tornam totalmente interdependentes, sendo
que o teste sempre irá depender das finalizações de cada etapa do
desenvolvimento. A Figura 3 mostra que o teste inicia simultaneamente
quando a equipe de desenvolvimento inicia o processo de
desenvolvimento. Ambas as equipes (teste e desenvolvimento) devem
utilizar-se das mesmas informações para realizarem seus planejamentos.

Figura 3 – Conceito “V” de teste de software.


Fonte: Rev ista Dev media (RODRIGUES, 2012).
Concebe-se assim o conceito “V” de teste (BASTOS, 2007), em que
os procedimentos de fazer e conferir convergem do início ao fim do projeto.
O fazer preocupa-se em implementar o software de acordo com seus
requisitos, e o conferir executa os procedimentos de teste com o objetivo
de minimizar ou eliminar riscos.
A engenharia de software possui diversas técnicas, critérios e
métodos e ferramentas que visam produzir um software de alta qualidade
e baixo custo. Mas mesmo com a aplicação desses elementos, erros
podem ocorrer. Para diminuir a ocorrência desses erros, existem as
etapas de verificação, validação e testes (MACHADO, 2011).
O teste dentro da engenharia de software é uma importante
ferramenta de opinião para identificar o andamento do projeto de
desenvolvimento. Com a crescente complexidade dos sistemas não é
surpreendente que cada vez mais uma parte maior do orçamento dos
projetos de software seja destinada diretamente ao seu teste (PETERS;
PEDRYCZ, 2001).
Dessa forma, é fundamental que a atividade de teste sempre
componha o processo de desenvolvimento de software, entretanto, na
maioria das empresas os testes nem sempre são tratados com a devida
seriedade. O que acontece normalmente são testes feitos pelo próprio
analista de requisitos ou programador, sem planejamento ou análise de
cobertura, de maneira superficial após o término do desenvolvimento e
pouco antes da entrega do produto (NITA, 2002).
Ainda para Nita (2002, p. 158),

Quando os testes não são realizados por uma equipe


independente e não têm um planejamento prévio, acaba-se
viciando as verificações executadas na aplicação ou deixando de
considerar situações relevantes, não ajudando na identificação e
eliminação de inconsistências de especificação ou falhas de
implementação. Também, ao se deixar a realização dos testes
apenas para o final do projeto, corre-se o risco de prejudicar a
fase de teste por não se ter tempo para verificar a aplicação como
planejado e resolver os problemas encontrados, por causa de
atrasos durante o desenvolvimento do software.

Além da independência do processo de testes, outro ponto que é


fundamental para o sucesso dessa etapa é que ela deve ser executada
durante todas as etapas do desenvolvimento de software.
Para Krug (2007, p. 8),

A atividade de teste deve ser usada em todas as etapas do


processo de desenvolvimento de software e que, ao invés de
apresentar uma última revisão, seja utilizada como milestone
entre todas as fases do projeto, pois erros, podem estar já nas
primeiras fases do projeto, e quanto mais tarde forem descobertos,
maiores impactos causarão.

A Figura 4 representa uma ideia de como seria a integração entre o


processo de desenvolvimento e o processo de teste com o objetivo de
encontrar os problemas o quanto antes para diminuir os custos do
processo.

Figura 4 – Modelo de integração entre os processos de desenvolvimento e de teste.


Fonte: Frassi (2010).

A construção de um software de qualidade requer a definição de um


processo de forma a encadear as atividades de projeto e verificação ao
longo do desenvolvimento. O software é um dos mais complexos artefatos
construídos de forma regular, se comparado a outros tipos de produtos. Os
requisitos de qualidade exigidos por um ambiente podem se diferenciar de
outros ambientes ou domínios de aplicação e ser incompatíveis com eles.
Além disso, ao longo do tempo, o ambiente e as necessidades se alteram,
seja pela evolução dos softwares aplicativos ou pela evolução do hardware
(PEZZÉ, 2008).
O teste de software é uma atividade relacionada diretamente à
validação do software. Quanto à validação, esta é frequentemente
confundida com verificação de software. Entretanto, existe uma diferença
conceitual entre elas: a verificação garante que o software implemente
corretamente uma função específica, enquanto que a validação garante
que o software construído é adequado aos requisitos do cliente. Boehm
(1981) diferencia as duas atividades através de duas perguntas:

Verificação: "Estamos construindo certo o produto?"


Validação: "Estamos construindo o produto certo?"

Segundo Pezzé (2008), a verificação e a validação começam assim


que se decide por construir um produto de software, ou até antes, como no
caso do estudo de viabilidade da construção de um novo software, em que
não são só considerados os custos de desenvolvimento e as
funcionalidades, mas também a qualidade exigida e o seu impacto no
custo total.
Onde o teste se encaixa no modelo “V” (também conhecido como
V&V)? Se for realizada uma análise sobre o que é teste, pode-se concluir
que teste é a validação do produto. Então, no contexto do desenvolvimento
de software, pode-se dizer que o teste será aplicado em diferentes fases
do processo de desenvolvimento. Inicialmente, ao validar os requisitos
junto ao cliente, pode-se dizer que se tem um teste, essa validação
denomina-se de estática, pois ela é realizada sobre a documentação e não
necessita que exista código desenvolvido para ser realizada. Por outro
lado, depois da validação inicial, que, geralmente, é realizada pelo usuário,
tem-se a validação dinâmica, o que se chama de teste, pois para ser
realizada necessita que todo ou parte do software seja executado. Então,
pode-se agregar o T ao VV&T para garantir que os produtos desenvolvidos
atendam aos requisitos funcionais e não funcionais.
Rios (2011) define verificação como a realização de
inspeções/revisões sobre os produtos gerados pelas diferentes etapas do
processo de teste e validação, como a avaliação se o sistema atende aos
requisitos do projeto (usuário). Os testes unitários, de integração, de
sistema, aceitação, homologação e de regressão podem ser classificados
como testes de validação. Já as revisões de requisitos e de modelos, as
inspeções de código e as revisões e inspeções técnicas em geral podem
ser algumas das atividades de verificação.
A atividade de testes (conduzida de forma incremental) consiste em
quatro etapas executadas após o planejamento dos testes, conforme
ilustrado na Figura 5: (1) projeto dos casos de teste, (2) preparação dos
dados de teste, (3) execução dos casos de teste e (4) avaliação dos testes
por meio da comparação do resultado dos testes com o resultado
esperado (MYERS, 2004; PRESSMAN, 2011; SOMMERVILLE, 2009).

Figura 5 – Processo de teste dividido em quatro etapas.


Fonte: Vicente (2010, p.36).

Segundo Rätzmann (2002), um processo de teste simples envolve


três etapas, sendo elas: planejamento, execução e avaliação. A Figura 6
mostra essas etapas.
Figura 6 – Etapas genéricas do processo de teste de software.
Fonte: Rätzmann (2002).

Na verdade nenhuma das visões está errada. O que varia são as


atividades realizadas dentro de cada etapa, pois alguns autores utilizam
menos etapas, mas com mais atividades dentro delas.
Cabe ressaltar que é difícil decidir quando o teste é suficiente, pois
deve-se levar em consideração vários aspectos, tais como a criticidade do
software (riscos tecnológicos, riscos do negócio etc.). Portanto, definir
quando parar de testar é uma tarefa complexa e pode-se dizer que nunca
se termina de testar um software, apenas passa-se a responsabilidade do
teste para outra etapa do ciclo de vida, pois as falhas podem ser causadas
por condições ambientais, que podem surgir ao longo do ciclo de vida do
produto.
Sendo assim, torna-se extremamente importante a implantação de
um processo de teste nas empresas desenvolvedoras de software,
alinhado ao processo de desenvolvimento. Principalmente para facilitar as
atividades de planejamento do projeto, pois assim a etapa de teste não
ficará apenas como a etapa final antes da entrega do produto. Deve-se ter
em mente que o teste de software necessita de tempo para ser realizado e
que está diretamente relacionado aos requisitos do software (inclusive os
requisitos não funcionais), assim necessitando, também de configurações
de hardware e software para ser desempenhado. Para isso, a equipe de
teste deve se envolver em todas as etapas do projeto desse software.

1.7 Níveis ou estágios do teste de software

A atividade de teste deve ser usada em todas as etapas do


processo de desenvolvimento de software e, em vez de representar uma
última revisão, deve ser realizada entre todas as fases do projeto, pois os
erros podem estar já nas primeiras fases dele, e quanto mais tarde forem
descobertos, maior impacto causarão (DEUTSCH, 1995). Do ponto de
vista financeiro, um estudo realizado pela IBM (1981) mostra que enquanto
um erro encontrado e corrigido durante a fase de projeto custa 1 unidade
monetária, se ele for encontrado durante a atividade de testes de código,
custará 15 unidades. Após o lançamento do produto, a correção do
mesmo erro custará entre 60 e 100 unidades monetárias.
Uma ideia defendida por Pressman (2011) é a de que, no ciclo de
desenvolvimento de software, a fase de testes deveria ocorrer durante todo
o processo de desenvolvimento e após o término de cada versão, mas
geralmente os cronogramas apertados e os imprevistos empurram os
testes para a última fase do projeto e não permitem que um processo
efetivo de testes no produto seja realizado.
Os objetos testados são todos aqueles que aparecem durante o
processo de desenvolvimento de software. Isto inclui módulos de código,
especificações de requisitos e projeto, estruturas de dados e qualquer
outro objeto que surja durante o processo de desenvolvimento e
implementação de software.
Segundo Filho e Rios (2003), foi a partir dos anos 1980 que a etapa
de testes passou a ganhar maior importância. Nesse período começam a
surgir metodologias específicas para teste e este passou a ser conduzido
como um processo formal. A atividade de testes faz parte do controle da
qualidade. O controle da qualidade surgiu da “necessidade de se avaliar, e
controlar a produção de um determinado produto”. A etapa de teste está
bastante relacionada à qualidade do software, através dela, quando bem
estruturada, é possível avaliar a qualidade do produto, verificando se suas
características estão dentro dos padrões estabelecidos e se suas
funcionalidades estão de acordo com os itens requeridos.
O teste de software se baseia em testar um produto de software de
forma controlada em busca da sua aderência aos requisitos e à possível
existência de falhas, as quais devem ser reportadas ao desenvolvimento
ou responsável para que possam ser corrigidas, com o objetivo de
melhorar o produto. A atividade de testes é considerada como algo não
trivial, já que exige conhecimento e definição de diversos critérios, que irão
refletir, ou não, no sucesso de uma boa avaliação da qualidade do
software. (CRESPO et al., 2003).
Em seu estudo, Moraes e Laurindo (1999) indicam que ao
desenvolver um programa, o desenvolvedor deseja que este esteja isento
de erros, mas a atividade de testes é justamente para evidenciar que o
sistema, talvez, não atenda a todos os requisitos e apontar a existência de
erros. Por assumir como verdade a posição de que o seu software não
apresenta erros, não é o mais conveniente, ou indicado, que o
desenvolvedor teste seu próprio programa. Eles apontam para a
necessidade de pessoas isentas ao desenvolvimento para a condução de
testes, com preferência a pessoas que pertençam à área de garantia da
qualidade.
No modelo “V” de desenvolvimento de software (Figura 3), para cada
um dos níveis do desenvolvimento há um nível de teste correspondente. A
Figura 7 mostra a integração entre os níveis de teste.

Figura 7 – Níveis de teste.


Fonte: elaborada pela autora.

O planejamento e as especificações dos testes ocorrem de cima


para baixo e a execução ocorre no sentido inverso. Nota-se que os testes
são classificados em quatro níveis, sendo eles:

Testes unitários: são os primeiros testes a serem executados,


consistem em testar individualmente as menores unidades do
software. Sua finalidade é garantir que a lógica do programa
esteja correta e completa.
Testes de integração: consistem em validar a compatibilidade
entre os componentes integrados. Para a realização destes
testes, é necessário o conhecimento da arquitetura interna do
software.
Testes de sistema: estes validam o software como um todo,
quanto maior o sistema, mais complexos serão os testes. São de
difícil planejamento, exigem total entendimento dos requisitos.
Testes de aceitação ou homologação: são os últimos testes a
serem realizados, possuem a finalidade de validar todas as
funcionalidades, são realizados pelos usuários finais antes de o
software ser disponibilizado no ambiente de produção.

1.7.1 Teste unitário

O teste unitário, também chamado de teste de unidade, é exclusivo


do código do programa e tem objetivo de verificar, de forma separada,
pequenas partes do código. (BASTOS et al., 2007).
Segundo Lopes e Carneiro (2011, p. 4), “o teste unitário testa se
cada funcionalidade especificada na codificação e desenho do software foi
implementada corretamente, são geralmente realizados por
desenvolvedores, utilizando a técnica de Caixa branca”.
O teste unitário é o mais baixo nível na escala de teste, sendo
aplicado nos menores componentes de código criados, visando garantir
que eles atendam às especificações, em termos de características e
funcionalidades. (RIOS; MOREIRA, 2006).
Esse teste é, geralmente, realizado pelo próprio programador, pois
exige um ambiente de produção adequado e especializado para
acompanhar os testes realizados.

1.7.2 Teste de integração

O teste de integração dos módulos individualmente averiguados no


teste de unidade seria o primeiro momento no qual pode existir
cooperação na atividade de teste. O teste de integração é uma técnica
sistemática para a construção da estrutura de programa, que ao mesmo
tempo procura descobrir erros relacionados à interface. O objetivo é, a
partir dos módulos testados no nível de unidade, construir a estrutura do
programa que foi determinada pelo projeto. Esse tipo de teste deve ser
realizado por algum componente da equipe [de?] desenvolvimento,
especialmente alguém que conheça os requisitos do software, mas que
não tenha participado diretamente do desenvolvimento dos módulos que
estão sendo integrados.
A integração pode ser incremental ou não incremental. A integração
não incremental, executada através da abordagem do b ig-b ang,
combinando-se antecipadamente todos os módulos, não costuma ser
eficaz, dada a amplitude de um teste do programa como um todo. Torna-se
difícil isolar um erro, e quando é corrigido, novos erros são gerados na
estrutura do programa. Já a integração incremental é mais eficiente,
podendo seguir a abordagem top-down ou a b ottom-up.
A integração dos módulos deve ser realizada de forma incremental.
A abordagem de integração não incremental não é recomendada, já que o
escopo de código a ser considerado na ocorrência de um erro é bastante
grande, tornando-se difícil localizá-lo. Por isso, neste curso, somente a
abordagem incremental será abordada.
Na abordagem incremental, devem ser construídos módulos de
apoio, denominados drivers e stub s. Um driver é um módulo que chama
o(s) módulo(s) sendo testado(s), tendo em seu corpo apenas
inicializações de variáveis globais, chamadas de rotinas e inicializações
dos parâmetros necessários. Um stub é um módulo que é chamado
pelo(s) módulo(s) sendo testado(s), contendo em seu corpo apenas a
atribuição de valores que serão retornados, quando for necessário. No
teste incremental, a necessidade de utilização de drivers e/ou stub s é
determinada através da estratégia utilizada. As duas estratégias mais
utilizadas são a top-down e a b ottom-up.
Na estratégia top-down, a integração inicia com o módulo principal(o
módulo inicial) do sistema. Depois disso, devem ser selecionados
módulos considerando-se que seu módulo superior (o módulo chamador)
tenha sido bem integrado. Para o teste de um módulo superior, é
necessária a utilização de stub s. Os módulos stub s não devem conter
apenas mensagens indicando que o fluxo de controle passou por eles,
mas sim retornos de valores ou a realização de funções específicas,
sempre que necessário. Caso houver um erro na construção dos stub s,
poderá haver uma falha no sistema, e a sua detecção implicará tempo e
custos perdidos (MYERS, 2004).
Na integração top-down, o processo de integração se dá em uma
série de cinco passos: 1) o módulo de controle principal é usado como um
driver de teste e os stub s são substituídos por todos os módulos
diretamente subordinados ao módulo de controle principal; 2) dependendo
da abordagem de integração escolhida, os stub s subordinados são
substituídos, um de cada vez, por módulos reais; 3) testes são realizados
à medida que cada módulo é integrado; 4) durante a conclusão de cada
conjunto de testes, outro stub é substituído pelo módulo real; e 5) teste de
regressão (isto é, a realização de todos ou de alguns dos testes
anteriores) pode ser realizado a fim de garantir que novos erros não
tenham sido introduzidos.
A maior desvantagem da integração top-down é a necessidade de
ter stub s e as dificuldades de teste resultantes que podem estar
associadas a eles e o overhead causado pela necessidade de
desenvolvimento de stub s e drivers. A integração b ottom-up por sua vez,
inicia a construção e os testes com módulos atômicos, ou seja, módulos
localizados nos níveis mais baixos da estrutura do programa. Uma vez que
os módulos são integrados de baixo para cima, o processamento exigido
para os módulos subordinados em determinado nível está sempre
disponível, e a necessidade de stub s é eliminada.
Uma estratégia de integração b ottom-up pode ser implementada
com os seguintes passos: 1) módulos de baixo nível são combinados em
clusters (ou construções) que executam uma subfunção de software
específica; 2) Um driver (um programa de controle para teste) é escrito
para coordenar a entrada e a saída do caso de teste; 3) O cluster é testado;
4) Os drivers são removidos e os clusters são combinados dirigindo-se
para cima na estrutura do programa. A principal desvantagem da
integração b ottom-up é que “o programa não existe como entidade até que
o último módulo seja adicionado” (MYERS, 2004).
Um dos problemas com a estratégia top-down é que o fornecimento
de valores geralmente não é feito de forma direta no momento inicial, já
que módulos que contêm funções de entrada e/ou saída costumam se
localizar na base do diagrama de chamadas. Desta forma, os valores de
entrada necessários aos módulos [que estão?] sendo testados devem ser
fornecidos pelos stub s. Para um conjunto variado de valores de entrada,
deve-se editar um stub atribuindo novos valores em suas inicializações, ou
então construí-lo de tal forma que sua estrutura permita diretamente a
seleção de valores para cada execução. Assim que um conjunto de
módulos, com seus stub s, é testado, cada um dos stub s é substituído pelo
módulo real correspondente, de forma que o teste de integração termine
quando o sistema todo estiver integrado e tiver as interfaces entre seus
módulos bem testada.
A sequência através da qual são integrados os módulos pode variar,
dependendo do critério adotado para tal. Podem ser escolhidos primeiro
os módulos mais críticos, os que possuem funções de entrada e/ou saída
ou ainda aleatoriamente. Essa decisão vai influenciar no esforço
necessário para a codificação dos stub s. Um problema que deve ser
evitado é a passagem para o teste de um outro módulo sem completar a
integração do anterior. Algumas outras considerações sobre a escolha da
sequência são apresentadas em Mosley (1993) e Myers (2004).
A estratégia b ottom-up, por sua vez, inicia selecionando os módulos
da base do diagrama de chamadas. Para que o teste seja realizado, não é
necessária a construção de módulos stub s, mas sim de drivers, para que
os módulos reais do sistema sejam chamados. Os drivers devem conter
inicializações de variáveis globais e de variáveis passadas como
parâmetros nas chamadas aos módulos. Desta forma, podem ser
construídas várias versões de um módulo driver, para permitir a
submissão de vários conjuntos de valores, bem como construí-lo de
maneira que esta variação seja feita automaticamente (como citado
anteriormente com os módulos stub s).
Um dos grandes problemas da estratégia b ottom-up, é que não é
construído, inicialmente, um esqueleto do programa. O programa funcional
passa a existir somente quando o último módulo é integrado. A vantagem
sobre a estratégia top-down é que as funções de entrada e/ou saída são
geralmente integradas no início do teste, fazendo com que não sejam
necessárias tantas versões de drivers quanto de stub s na estratégia top-
down.

1.7.3 Teste de sistema

O teste de sistema tem como objetivo principal de pôr


completamente à prova o sistema de software (PRESSMAN, 2011). Ou
seja, após realizados o teste de validação inicial, o teste de unidade e de
integração, o sistema é testado em conjunto com outros sistemas de
software e elementos de hardware, os quais serão utilizados comumente
após a sua liberação.
A ideia desse tipo de teste, que é realizado pela equipe de teste, é
simular o uso do software em um ambiente semelhante ao de produção,
assim testa-se o software na tentativa de retratar o uso real.
Segundo Neto (2007, p. 56),

O teste de sistema avalia o software em busca de falhas por meio


da utilização do mesmo, como se fosse um usuário final. Dessa
maneira, os testes são executados nos mesmos ambientes, com as
mesmas condições e com os mesmos dados de entrada que um
usuário utilizaria no seu dia-a-dia de manipulação do software.
Também é verificado se o produto satisfaz seus requisitos.

Esse estágio de teste é realizado por testadores após todos os


testes de integração, pois valida o sistema como um todo podendo
analisar os requisitos funcionais e não funcionais, como desempenho,
volume, documentação, robustez. (LOPES; CARNEIRO, 2011).
De acordo com Peters e Pedrycz (2001, p. 383), “o teste de sistema
visa garantir que o software como uma entidade completa esteja de acordo
com os requisitos operacionais correspondentes”.
Nessa etapa, é fundamental a especificação de um plano de teste,
que pode ter o formato simples de um checklist, ou então ser formado por
uma lista de procedimentos a serem realizados. Em ambos os casos, o
plano deve abranger todos os requisitos funcionais e de desempenho do
sistema. Além disso, a documentação do usuário deve ser utilizada nesse
momento. Os manuais e sistemas de ajuda (online ou impressos) devem
estar de acordo com a funcionalidade do software. Também a inclusão de
tutoriais e exemplos de complexidade média de uso do sistema são
bastante úteis para que o usuário entenda como o sistema funciona. Para
haver consistência entre os documentos e o próprio sistema de software, é
interessante que seja realizada a revisão da configuração do software, em
paralelo com o teste de aceitação. Pressman (2011) afirma que, após cada
caso de teste de validação ter sido realizado, existirá uma das duas
condições a seguir: (1) os requisitos funcionais e de desempenho
conformam-se à especificação, ou (2) um desvio das especificações é
descoberto e uma lista de deficiências é criada. A seguir, são
apresentadas algumas estratégias para o teste de validação de um
sistema.
Devido ao fato de o teste de sistema ter como objetivo a simulação
do uso real do software, é nesse nível que se encontra a maioria dos tipos
de teste, avaliando o atendimento aos requisitos funcionais e não
funcionais do sistema.
Requisitos não funcionais são aqueles relacionados à
confiabilidade, velocidade, disponibilidade, dentre outras características.
Na eventualidade de ocorrer uma falha em requisito não funcional, ela
poderá tornar todo o sistema ineficaz. Por exemplo, são requisitos não
funcionais:

Requisitos éticos: dados de cunho privativo não serão


apresentados aos usuários.
Requisitos legais: o sistema deverá atender às normas legais,
tais como padrões, leis etc.
Requisitos de eficiência: deverá processar n requisições por um
determinado tempo.
Requisitos de confiabilidade: o sistema deverá ter alta
disponibilidade, como permanecer 99% do tempo disponível.
Requisitos de portabilidade: o sistema deverá rodar em qualquer
plataforma.

Os requisitos funcionais fazem parte da arquitetura do aplicativo de


um sistema, enquanto os requisitos não funcionais denotam a arquitetura
técnica de um sistema. Dentre os testes executados nessa fase, podem
ser citados: teste de carga, teste de funcionamento, teste de usabilidade,
teste de recuperação, teste de segurança, teste de estresse e teste de
desempenho (PRESSMAN, 2011).

1.7.4 Teste de aceitação ou homologação

O teste de aceitação corresponde ao teste realizado pelo usuário,


que deve ser realizado após o teste de unidade, o teste de integração e o
teste de sistema. De acordo com Pressman (2011, p. 539), a “validação
(fase de aceitação) é bem-sucedida quando o software funciona de uma
maneira razoavelmente esperada pelo cliente”. As expectativas do cliente
devem estar registradas em um documento de especificação, que deve ter
sido escrito no início do desenvolvimento do sistema.
São os testes feitos pelo usuário, que dificilmente opera o sistema
da forma prevista, e visam descobrir erros cumulativos que poderiam
deteriorar o sistema no decorrer do tempo. O teste alfa é executado por um
cliente nas instalações do desenvolvedor. O software é usado num
ambiente natural com o desenvolvedor acompanhando e registrando erros
e problemas de uso. Os testes do tipo alfa são conduzidos em ambiente
controlado. Já o teste beta é realizado em uma ou mais instalações do
cliente pelo usuário final do software. Geralmente o desenvolvedor não
está presente. Assim, o teste beta é uma aplicação viva do software, num
ambiente que não pode ser controlado pelo desenvolvedor (PRESSMAN,
2011). Os problemas são registrados pelo usuário e repassados
regularmente ao desenvolvedor, que corrige o software antes de lançar o
produto para venda.
As principais preocupações nesse estágio de teste são as
características de funcionalidade e usabilidade. O usuário irá testar o
software para verificar se ele atende às suas necessidades, isto é, se
atende às especificações, além de identificar a facilidade de uso e de
encontrar as funcionalidades do software.

1.7.4.1 Teste alfa

No teste alfa, o usuário utiliza o sistema de software nas instalações


do desenvolvedor. Os desenvolvedores acompanham o trabalho do cliente,
anotando problemas de uso, erros e queixas em relação à percepção do
cliente sobre o sistema. Ou seja, o teste alfa é conduzido em um ambiente
controlado.
Um dos problemas do teste alfa é que raramente o usuário
consegue comportar-se tão “naturalmente” como no seu ambiente real de
trabalho, devido à presença, muitas vezes incômoda, do desenvolvedor.
Uma alternativa para dispensar essa presença seria a utilização de
sistemas que registram todas as interações do usuário.

1.7.4.2 Teste b eta

Já no teste beta (mais conhecido e utilizado do que o teste alfa), o


usuário utiliza o sistema em suas próprias instalações. O desenvolvedor
não está presente, o que acaba caracterizando uma aplicação real do
usuário, já que o ambiente não pode ser controlado pelo desenvolvedor. O
usuário registra todos os problemas encontrados e repassa-os para o
desenvolvedor, que realiza as modificações necessárias.
Os usuários que devem ser escolhidos para o teste beta devem
possuir algumas das características listadas a seguir:

Capacidade crítica no uso do software, tendo a tendência natural


de querer testar situações pouco comuns ou de exceção.
Bom entrosamento com a empresa desenvolvedora, já que o
usuário deve entender que a versão que ele está utilizando está
em teste beta, sendo ainda passível de erros e melhoramentos.
Por isso, nenhuma operação que coloque em risco
procedimentos ou dados da empresa deve ser realizada com
aquela versão.
Preferencialmente, deve ser leigo em informática, não fazendo
assim considerações que podem levar a interpretações errôneas
do erro observado.
Ser organizado e dispor de tempo para o teste, a fim de que todas
as observações sejam registradas, contribuindo para o
aperfeiçoamento do produto final.

1.8 Tipos de teste

Na norma ISO/IEC 9126 (2001), estão descritas as características e


subcaracterísticas para determinar a qualidade de produtos de software,
tais como: funcionalidade, confiabilidade, usabilidade, eficiência,
manutenibilidade e portabilidade. Para garantir a qualidade dos produtos
de software, existem tipos de testes específicos a serem executados,
alguns deles são:

Teste de função ou teste de funcionalidade: não confundir com a


técnica de teste funcional, que será vista no próximo capítulo. O
objetivo deste teste é validar se as funcionalidades do software
estão conforme o que foi especificado.
Teste de confiabilidade ou teste de segurança: garante que os
dados (ou sistema) possam ser acessados apenas por
determinados usuários.
Teste de contingência (integridade): avalia a robustez do software
(resistência a falhas).
Teste de usabilidade: valida os aspectos da usabilidade do
software, como estética, consistência na interface do usuário,
ajuda online, assistentes e agentes, documentação do usuário
etc. Isto é, verifica se o produto de software é fácil de utilizar, de
aprender e se é atraente ao usuário ao qual se destina (BSTQB,
2011).
Teste de volume: verifica a capacidade do software de lidar com
grandes volumes de dados.
Teste de carga ou teste de estresse: avalia e valida a aceitação
dos limites operacionais do software de acordo com cargas de
trabalho variável. Segundo o BSTQB (2011), é realizado com o
intuito de avaliar o comportamento do componente ou sistema
com carga crescente, por exemplo, número de usuários que um
site consegue suportar. Também é considerado um teste de
desempenho, pois avalia um componente ou sistema utilizando
uma carga além dos requisitos especificados (BSTQB, 2011).
Teste de estresse: avalia como o software responde em
condições anormais, como cargas de trabalhos extremas,
serviços indisponíveis, memória insuficiente etc.;
Teste de desempenho: compara o desempenho de um software
com outro software com cargas idênticas.
Teste de portabilidade: verifica a capacidade do produto de
software ser transferido de um ambiente (organizacional,
hardware ou software) para outro, por exemplo, a capacidade de
um sistema web funcionar em diferentes navegadores ou
diferentes equipamentos.
Teste automatizado: a automação dos testes pode ser útil a
diferentes estratégias, como realizar testes de regressão de
forma rápida, para a redução de envolvimento humano em
atividades repetitivas; para testes de desempenho habitualmente
se usam ferramentas para simular grandes volumes de acessos
(CAETANO, 2008).
Teste de configuração: garante que o software funcione conforme
o esperado em diferentes configurações de hardware e software.
Teste de instalação: assegura que o software seja instalado
conforme o esperado em diferentes configurações de hardware e
software.
Teste de recuperação: verifica o comportamento de recuperação
do software após o aparecimento de falhas.

Além dos testes descritos acima, há o teste de regressão, cujo


objetivo é retestar o software para validar se uma funcionalidade continua
funcionando após uma modificação no software.
Esses são apenas alguns exemplos dos diversos tipos de testes,
porém para a seleção do tipo de teste ou da ferramenta utilizada, é
necessário conhecimento. Os testes são utilizados de acordo com a
necessidade do que se está testando e também da fase do
desenvolvimento que o módulo, produto ou sistema se encontra. Para a
automação de teste, o trabalho de análise pode ser ainda maior, já que é
necessário verificar as vantagens e desvantagens de automatizar, além do
estudo das ferramentas para a seleção da que melhor nos atende naquele
momento (CAETANO, 2008).
A estratégia de teste escolhida irá definir quais tipos de teste serão
utilizados naquele projeto De acordo com Pressman (2011, p. 539), “uma
estratégia de teste de software integra técnicas de projeto de casos de
teste numa série bem-definida de passos que resultam na construção
bem-sucedida de software”. Algumas considerações gerais sobre
estratégias de teste:

o teste deve iniciar no nível de módulos e prosseguir na direção


da integração de todo o sistema;
diferentes técnicas de teste podem ser utilizadas em diferentes
momentos;
a atividade de teste é realizada pela equipe de desenvolvimento
ou por um grupo independente – a ênfase deste curso é
justamente na realização do teste em equipe, o que aperfeiçoa e
refina a estratégia de teste utilizada;
as atividades de teste e depuração são atividades diferentes,
entretanto, a depuração deve ser inserida em qualquer estratégia
de teste.

1.8.1 Teste de segurança

O teste de segurança tem o objetivo de garantir que o sistema se


comporta adequadamente mediante tentativas ilegais de acesso, tais
como as que são comumente feitas por hackers. Os mecanismos de
segurança implementados no sistema devem protegê-lo efetivamente
desses acessos indevidos.
Esse teste é utilizado para, segundo a ISO/IEC 9126 (2001), avaliar
a capacidade do produto de software para que apresente níveis aceitáveis
dentro do estabelecido de segurança, minimizando as chances de ocorrer
riscos e danos a pessoas, negócios, software, propriedades ou ambiente.
Os testadores devem tentar penetrar no sistema de várias formas,
tais como, obtenção ilegal de senhas, desarme do sistema, tentativas de
acesso durante a recuperação do sistema, após inserção de falha
intencional, entre outros. É importante que o teste não seja feito pelos
próprios desenvolvedores, a fim de evitar que testem apenas os
mecanismos de segurança implementados, já que estes são de seu
conhecimento.

1.8.2 Teste de estresse


O teste de estresse deve confrontar o sistema com situações
anormais de uso. A pergunta que deve ser feita pelo testador é
(PRESSMAN, 2011): até que ponto podemos elevar isto antes que falhe?
Para responder a essa pergunta, o testador deve utilizar o sistema
com recursos em quantidade, frequência e volume anormais, tais como
procuras excessivas de dados em disco, aumento excessivo de índices de
dados, abertura de muitas janelas, até que haja um problema de falta de
memória, utilização de arquivos com formato não compatível com os
esperados pelo programa, entre outros.
O teste de estresse também deve ser feito por programadores que
não desenvolveram o sistema. Pode ser utilizado um checklist com
situações padrão de provocação de “estresse no sistema”.

1.8.3 Teste de desempenho

O teste de desempenho é fundamental para sistemas de tempo


real. Nessa etapa, deve-se verificar se o desempenho do software está de
acordo com seus requisitos especificados, em que o desempenho de
execução do software é testado, dentro do contexto de um sistema
integrado.
Pressman (2011) sugere que muitas vezes o teste de desempenho
pode ser feito combinado com o teste de estresse. Nessas situações,
software e hardware são controlados a fim de observar seu
comportamento perante às situações nas quais foram colocados durante
essas fases de teste.
O teste de desempenho deve ser feito por outros programadores
que não desenvolveram o sistema, entretanto, é interessante que o próprio
programador atue como um “testador de suporte”, a fim de fornecer
informações que possam ser necessárias.

1.8.4 Teste de usabilidade

Para avaliar a usabilidade de um sistema, podemos aplicar uma


metodologia chamada Avaliação Heurística, definida por Nielsen e Molich
(1994), em que são abordadas dez questões:
1. Visibilidade do status do sistema;
2. Compatibilidade entre o sistema e o mundo real;
3. Controle e liberdade para o usuário;
4. Consistência e padrões;
5. Prevenção de erros;
6. Reconhecimento em lugar de lembrança;
7. Flexibilidade e eficiência de uso;
8. Projeto minimalista e estético;
9. Auxiliar os usuários a reconhecer, diagnosticar e recuperar erros;
10. Ajuda e documentação.

1.8.5 Teste de caso de uso

De acordo com Jacobson (1992), um caso de uso é uma maneira


específica de utilização do sistema, executando parte de sua
funcionalidade. Cada caso de uso é constituído por uma sequência de
eventos iniciada por um ator (alguém ou algo que interage com o sistema).
O conjunto de casos de uso especifica todas as maneiras diferentes de
utilização do sistema. A utilização de casos de uso é simples e prática,
entretanto a sua proposta original carece de descrições objetivas de
utilização deles.
Mesmo que empresa não esteja desenvolvendo sistemas utilizando
o paradigma orientado a objetos, a utilização de casos de uso é
perfeitamente possível e adequada no processo de teste a ser implantado.
Os casos de uso fazem parte da especificação de alto nível do sistema,
não sendo, portanto, alterados caso o paradigma de desenvolvimento seja
alterado.
Mattingly (1998) apresenta algumas considerações práticas para a
especificação e o refinamento dos casos de uso, que, apesar de terem
sido propostos originalmente para as fases de análise e projeto, podem
ser utilizados diretamente no procedimento de teste. Os seguintes
objetivos para a utilização de casos de uso foram apresentados por
Mattingly (1998) e podem ser observados no processo de teste:

Definir, utilizando a linguagem do usuário, o sistema a ser


construído com base em três visões: do usuário final, do testador
e do desenvolvedor.
Casos de uso podem ser refinados em casos de teste de
aceitação.
Casos de uso podem fornecer a base para a construção da
documentação para o usuário final.

As seguintes diretivas devem ser seguidas para a definição dos


casos de uso:

Nunca devem ser escritos por usuários, já que estes tendem a


elaborar casos de uso complexos, descrevendo telas do sistema,
dificultando sua manutenção e testabilidade.
Basear a construção dos casos em entrevistas com usuários,
abordando as seguintes questões, em relação ao sistema de
software:

problemas que devem ser resolvidos por ele;


seus objetivos;
seus usuários diretos;
intenções desses usuários;
seus usuários indiretos;
intenções desses usuários;
outros sistemas que interagem com o sistema;
necessidade de notificação aos usuários quando alguns
eventos ocorrem;
tarefas feitas pelos usuários de forma frequente;
relacionamento entre o trabalho que um usuário precisa
fazer e o sistema.

1.8.6 Teste de regressão

Os testes de regressão devem ser utilizados sempre que o software


sofre uma alteração. Em geral, isso significa aplicar os mesmos testes
realizados anteriormente para garantir que os resultados não tenham sido
afetados pelas mudanças realizadas na aplicação, não só na parte
alterada, como em outros segmentos do sistema.
O teste regressão é realizado após alguma alteração ou introdução
de uma parte no sistema, para garantir que não houve efeitos indesejados
dessas alterações no restante do sistema, que nada parou de funcionar
ou que esteja funcionando de modo inadequado (BASTOS et al., 2007).
O grande problema para executar esse tipo de teste é o gasto
excessivo de tempo e a cansativa repetição das operações, o que contribui
para que eles não sejam realizados ou para que sejam, apenas em parte.
Como esses testes são vitais para garantir a qualidade do produto
justifica-se introduzir a automação de testes (MOLINARI, 2009).
Não se deve confundir teste de regressão com reteste. Embora os
dois compartilhem uma característica em comum, que se refere à
reutilização dos casos de teste já utilizados, o que os diferencia é o
momento e o motivo de sua aplicação. O teste de regressão irá utilizar os
mesmos casos de teste utilizados anteriormente para avaliar se o software
após uma alteração não teve as suas funcionalidades alteradas, por isso,
torna-se importante a reaplicação dos mesmos dados de entrada para ter
o mesmo comportamento quando o teste foi aceito.
Já o reteste utiliza os mesmos casos de teste para avaliar se os
erros encontrados durante a fase de teste foram realmente retirados do
software pelos desenvolvedores. A reutilização dos dados de teste irá
evidenciar que o comportamento inadequado para aquela situação não
existe mais.

1.9 Testabilidade

A ISO 9126 (2003) estabelece um conjunto de atributos que têm


impacto na capacidade do software de manter o seu nível de desempenho
dentro de condições estabelecidas por um dado período de tempo.
Uma das características para o software ser classificado como bom,
segundo a ISO 9126 (2003), refere-se à testabilidade, que está
diretamente relacionada à facilidade de realizar manutenções no sistema.
A Figura 8 mostra os atributos para um software ser desenvolvido com
qualidade.
Figura 8 – Atributos, segundo a ISO 9126, para um software de qualidade.
Fonte: Nascimento (2010, p. 23).

A testabilidade de um software, de acordo com Pressman (2011), é


um conjunto de características que define o quão fácil é testar um
determinado software. As características que levam um software a ter alta
testabilidade são:

Operabilidade: implementação do software visando a qualidade,


evitando qualquer impedimento na execução de algum teste, isto
é, quanto mais operacional [for?]o software que está sendo
testado, melhor será o teste.
Observabilidade: entradas e saídas de fácil visualização e
identificação e acessibilidade ao código-fonte. Deve-se conseguir
observar o comportamento do sistema (caminho) que leva da
entrada até a saída.
Controlabilidade: maior controle possível das variáveis e estados
do software, assim consegue-se mapear possíveis erros
encontrados na fase de teste.
Decomponibilidade: modularização do software em unidades que
possam ser tratadas e testadas de forma independente. Aqui
facilitando o teste de integração e a criação de drivers e stub s.
Simplicidade: construção de uma codificação padronizada e
simples.
Estabilidade: alterações pontuais e controladas, que não tornem
nenhum teste já existente inválido.
Compreensibilidade: arquitetura do software de fácil
compreensão, assim como sua documentação, que deve ser
organizada e precisa.

A testabilidade deve ser incorporada no software desde o início do


seu projeto, em todas as suas fases de desenvolvimento, segundo
Tannouri (2013). As fases de codificação e testes são essenciais para a
testabilidade, sendo que os planos de testes e a criação de testes
unitários devem cumprir todas as características que irão medir o quanto o
software será testável.
Chattergee (2004) destaca a importância que a testabilidade tem no
ciclo de vida de desenvolvimento de software, assegurando que, com a
aplicação correta dos testes, a maioria dos defeitos possa ser encontrada
e corrigida antes que o produto final seja entregue. Sendo assim, um
software testável torna muito mais fácil a execução dos planos de testes,
aumentando consideravelmente as chances de se alcançar a satisfação
do usuário.

1.10 Dificuldades na implantação de um processo de teste

Apesar das ferramentas, da estruturação, da sistematização e dos


esforços para a criação de metodologias e padrões que auxiliem na busca
da qualidade e contribuam para o processo de testes, nem sempre esse
objetivo obtém sucesso; diversas organizações apresentam dificuldades
em implantar um processo eficiente de teste. Filho e Rios (2003)
ressaltam algumas características do porquê de muitas empresas ainda
fracassarem na implantação do processo de teste, dentre elas estão:

O processo de teste ainda não alcançou um nível de maturidade


dentro das empresas; muitas vezes acaba não sendo visto como
um verdadeiro processo, sendo executado de maneira informal,
sem as técnicas, as qualificações e os recursos necessários.
Atividade de teste se mistura com a de desenvolvimento, sem
uma gestão adequada dessa atividade, acarretando em testes
incompletos, refletindo em problemas de qualidade que poderiam
ter sido evitados, mas que só serão descobertos após
implantação, elevando significativamente o custo de descoberta e
correção.
Abordagem de teste inadequada, muitas vezes por falta de
conhecimento técnico da equipe de teste ou falta de recurso
disponibilizado pela organização.
Falta de equipe independente e especializada em testes na
organização, cabendo essa atividade ao desenvolvedor, que, em
muitos casos, não gosta, não tem perfil ou conhecimento técnico
adequado para a execução dessa tarefa.
Pouca utilização de ferramentas de automação, já que alguns
testes necessitam dessas ferramentas para obter êxito.

Crespo et al. (2003) também fala da dificuldade de testar e implantar


uma metodologia de teste, apontando como algumas das causas o
elevado custo do teste e a falta de conhecimento das organizações sobre o
seu custo-benefício e a falta de profissionais especializados na área, o
que acarreta no desconhecimento de procedimentos, técnicas e
planejamento adequado dos testes. Filho e Rios (apud BRUNELI, 2006, p.
1) citam que:

Um dos grandes problemas encontrados na implantação de uma


metodologia de teste reside no fato dele ainda ser visto como um
causador de aumento dos custos e prazos dos projetos, podendo,
deste modo, vir a criar hostilidade entre os membros do projeto e
os responsáveis pelos testes e problemas com usuários.

Vários estudos (BASTOS, 2007; RIOS, 2006) indicam que quanto


mais tarde o erro é descoberto, mais caro ele se torna. Visando a
qualidade e a economia nos custos dos softwares, muitas empresas
voltaram as atenções para as atividades de testes. Com isso, a visão
descrita anteriormente está sendo substituída por outra que “privilegia a
qualidade e, como consequência, enfatiza o maior esforço no processo,
entendendo que testar é um investimento em qualidade e que este produz
um retorno positivo e contribui decisivamente para o sucesso do projeto.”
(BULLOCK, 2005 apud BRUNELI, 2006, p. 14).
CAPÍTULO 2
TÉCNICAS DE TESTE
O teste pode ser aplicado de maneiras muito diferentes, isso depende de
diversos fatores, tais como o ambiente da empresa cliente, o processo implementado
pela empresa desenvolvedora do software, as características do software, a importância
do software na empresa, entre outros. Por isso, este capítulo apresenta as técnicas de
teste de software, que podem ser aplicadas de maneira individual ou conjunta. As
técnicas apresentadas aqui serão empregadas nos diferentes níveis de teste já
apresentados.
Neste capítulo serão estudadas as técnicas de teste baseadas na documentação
do software, as quais não necessitam de detalhes da implementação (codificação) para
começar a elaboração dos casos de teste. Esta técnica é geralmente aplicada pela
equipe de teste, pois independe do conhecimento e da evolução da etapa de
desenvolvimento do software.

As técnicas de teste de software referem-se ao como serão


testados, especialmente relacionada à fonte de informação utilizada para o
teste. As técnicas de teste se preocupam com as formas de geração de
teste e podem utilizar algumas dessas formas:

Conhecimento e intuição da equipe de teste: teste baseado na


experiência – aqui não existe uma estratégia seguida, o que
dificulta a avaliação da qualidade dos casos de teste gerados.
Baseado na especificação: os testes são gerados com base na
documentação do sistema, esta estratégia será detalhada em
teste funcional.
Baseado na estrutura do código: a partir do código, são gerados
fluxos que auxiliarão na geração dos dados do teste. Essa técnica
será detalhada no teste estrutural.
Baseado nos defeitos a serem testados: os testes são
construídos com a intenção de encontrar determinados defeitos
ou tipos de defeitos.
Baseado na natureza da aplicação: de acordo com a natureza da
aplicação, alguns testes devem ser considerados. Esta técnica
está diretamente relacionada ao ambiente de teste e aos
procedimentos e cenários associados aos requisitos funcionais,
especialmente, aos requisitos não funcionais do sistema.

As técnicas preocupam-se agora com a geração dos dados de teste


para que estes, com o mínimo esforço, atendam ao objetivo do teste, que é
encontrar o maior número de defeitos. Para Pressman (2011), diferentes
técnicas de testes são adequadas em diferentes momentos.
Os critérios de teste selecionam e avaliam casos de teste com o
intuito de revelar a presença de defeitos ou estabelecer um nível elevado
de confiança na correção do produto quando erros não são revelados
(MALDONADO, 1991). Além disso, os critérios e as técnicas de teste
influenciam nos tipos de defeitos que serão encontrados. Conforme Zhu
(1997), esses critérios são geralmente derivados a partir de quatro
técnicas: funcional, estrutural, baseada em defeitos e baseada em
estados, que diferem na abordagem utilizada para gerar e avaliar casos de
teste.
Segundo Howden (1987), o teste pode ser classificado de duas
maneiras: teste baseado em especificação (specification-b ased testing) e
teste baseado em programa (program-b ased testing). Seguindo essa
classificação, podemos dizer que a técnica funcional e a baseada em
estados são fundamentadas em especificação, enquanto a técnica
estrutural e a baseada em erros são baseadas em programas. Neste livro
serão detalhas as técnicas baseadas na especificação e as baseadas na
implementação.
Sendo assim, é necessário conhecer todas essas técnicas para
saber escolher a mais adequada para diferentes momentos, garantindo a
solução e a melhor qualidade dos casos de teste que serão realizados.
Algumas técnicas são utilizadas nos vários estágios do ciclo de vida
do software. Estas incluem os métodos informais tradicionais, como os
testes de mesa, bem como técnicas como walkthroughs e inspeções
estruturadas. Simulações e testes estruturais e funcionais também podem
ser aplicados ao longo do projeto. Neste capítulo serão apresentadas
algumas das técnicas existentes e sua aplicação.

2.1 Walkthough

Os objetivos da revisão formal feita através da técnica de


walkthrough são: 1) descobrir erros de função, lógica ou implementação
em qualquer representação do software; 2) verificar se o software que se
encontra sob revisão atende a seus requisitos; 3) garantir que o software
tenha sido representado de acordo com padrões predefinidos; 4) obter um
software que seja desenvolvido uniformemente; 5) tornar os projetos mais
administráveis; e 6) verificar as decisões tomadas ao longo do projeto pela
equipe de desenvolvimento.
Walkthrough é uma técnica formal e manual, sendo uma evolução
da técnica de teste de mesa. A principal diferença entre eles é que a
responsabilidade pela execução do teste de mesa é do programador,
enquanto o procedimento de walkthrough tem por objetivo remover a maior
parte da responsabilidade pela verificação do programador. Esta técnica
funciona em um esquema de equipe, geralmente dirigido por um
moderador e incluindo os desenvolvedores do software e mais alguns
membros que não devem estar envolvidos com o esforço de
desenvolvimento. É baseada na leitura da especificação dos requisitos, do
projeto ou mesmo do código, em reuniões formais com regras específicas
para avaliação. O processo de revisão se dá da seguinte forma: o líder da
equipe de revisão, ou outro integrante da equipe, fornece dados de teste e
lidera a equipe por meio de uma simulação manual do sistema. Os dados
de testes são executados e os resultados do teste registrados.
O propósito da técnica de walkthrough é estimular a discussão.
Muitos erros são descobertos através do questionamento das decisões
dos desenvolvedores nos diversos estágios, mais do que examinando os
dados de teste.
A aplicação da técnica de walkthrough pode, portanto, ocorrer em
diversas fases do projeto. Durante a fase de projeto preliminar, essa
técnica pode ser utilizada para determinar se os requisitos satisfazem as
medidas de testabilidade e adequabilidade desse estágio do
desenvolvimento. Se requisitos formais foram definidos, métodos formais,
como as técnicas de prova de corretude, podem ser aplicados para medir
a aderência aos fatores de qualidade.
Essa técnica pode ser executada novamente no estágio de projeto
preliminar, especialmente na avaliação da testabilidade e adequação do
módulo ao seu projeto de interface.
Finalmente, essa técnica pode ser aplicada no estágio de
implementação (codificação). Cada módulo deve ser analisado em
separado e depois integrado ao produto final.

2.2 Prova de corretude

A prova de corretude é técnica de análise estática. Em um nível


informal, ela reduz o número de passos envolvidos em um walkthrough.
Em um nível mais formal, a lógica matemática é aplicada para dar suporte
ao problema de provar que um programa está de acordo com sua
especificação.
Essa técnica consiste em validar a consistência de uma saída de
acordo com o programa e a entrada. Em um programa, se puder se
mostrar que a sua execução gera a saída verdadeira para os valores
possíveis das variáveis de entrada, então prova-se que o programa está
correto. É mais comumente utilizada para testes durante a fase de
implementação.

2.3 Simulações

A simulação é qualquer técnica de validação que não envolva


execução. Portanto, pode-se considerar walkthrough e a prova de corretude
como formas de simulação.
Entende-se que a simulação é uma forma de utilização de um
modelo executável para representar o comportamento de um objeto. Essa
ferramenta de testes é bastante útil.
A simulação, geralmente, é utilizada em sistemas de tempo real, em
que a interface com o mundo real é crítica e a integração com o hardware
do sistema é fundamental. Ela leva em conta o ambiente ao qual o
software se destina. Pode ser usada na fase de implementação para
garantir que o software funcionará quando implantado. Utiliza-se a
simulação também para testar softwares embarcados, pela necessidade
de avaliar o comportamento do software em um ambiente controlado e
algumas situações em que o hardware ainda não se encontra fabricado.

2.4 Teste funcional

O teste funcional, também conhecido como teste de caixa-preta


(b lack b ox) ou teste baseado na especificação, é uma técnica que deriva
os casos de teste a partir da análise da funcionalidade (dados de
entrada/saída e especificação) do programa, sem levar em consideração a
sua estrutura interna (MYERS, 2004).
O principal fundamento do teste de caixa-preta é imaginar o sistema
como uma caixa fechada que deve ser testada sem visualizar ou entender
o código. Um exemplo de teste funcional é fazer uma compra na internet,
onde é necessário simplesmente interagir com o site, sem entender o que
acontece por trás da página. Desta maneira, podem ser testadas as
informações de pagamento, de entrada de dados e de emissão de
comprovantes e/ou de boleto. Com esse teste é possível também testar a
usabilidade, porque trata quase que exclusivamente das atividades do
usuário com o sistema e os seus retornos. A Figura 9 mostra as divisões
do processo de teste funcional.

Figura 9 – Divisões do processo de teste funcional.


Fonte: elaborada pela autora.

A Figura 9 facilita a visualização das etapas do processo de teste


funcional. É possível identificar que entram dados de teste, em seguida, o
sistema faz sua execução e, por fim, os resultados são exibidos na saída.
O lado positivo da utilização de critérios funcionais é que eles
podem ser aplicados em todas as fases de teste e em produtos
desenvolvidos com qualquer paradigma de programação, inclusive
componentes caixa-preta, pois não levam em consideração a
implementação (VINCENZI et al., 2003). Existem dois problemas da
utilização de teste funcional. O primeiro é referente a especificações
ausentes ou mesmo incompletas que tornarão difícil a aplicação dos
critérios funcionais. O segundo problema é referente à limitação dos
critérios de teste funcional, que não garantem que partes essenciais ou
críticas do produto em teste sejam exercitadas.
As categorias de erros mais evidenciadas pelo teste funcional são:
erros de interface, funções incorretas ou ausentes, erros nas estruturas de
dados ou no acesso a bancos de dados externos, erros de desempenho e
erros de inicialização e término (PRESSMAN, 2011). O teste funcional é
geralmente aplicado quando todo ou quase todo o sistema já foi
desenvolvido. O conjunto de casos de teste derivado no teste funcional
deve satisfazer os seguintes critérios (MYERS, 2004):

reduzir, em uma contagem que seja maior do que 1, o número de


casos de teste adicionais que devem ser projetados para se
conseguir testes satisfatórios;
revelar algo sobre a presença ou ausência de classes de erros,
em vez de um erro associado somente ao teste específico que se
está utilizando.

A seguir serão apresentadas as técnicas mais clássicas de teste


funcional, são elas: particionamento de equivalência, análise do valor-
limite, teste sistemático, grafo causa-efeito e tabela de decisão.

2.4.1 Particionamento de equivalência

A teoria da decomposição de equivalência, como proposto por Myers


(2004), tenta reduzir a quantidade total de casos de teste necessários pela
decomposição das condições de entrada em uma quantidade finita de
classes de equivalência. Dois tipos de classe de equivalência estão
classificados: o conjunto de entradas válidas para o programa é
considerado como classe de equivalência válida, e todas as outras
entradas são incluídas na classe de equivalência inválida. Identifica, por
meio da documentação, quais são as entradas que possuem restrições
ou regras, esta identificação é feita através da documentação.
Esse critério de teste objetiva reduzir o número de casos de teste
para um nível gerenciável mantendo, ainda, uma cobertura razoável de
testes (COPELAND, 2004).
A classe de equivalência, ou particionamento de equivalência, é o
processo de, sistematicamente, reduzir o enorme (ou infinito) conjunto de
possíveis casos de testes para um conjunto menor, porém tão efetivo
quanto o conjunto inicial.
Segundo Pressman (2011), esse critério divide o domínio de
entrada em duas classes distintas, válida e inválida, sendo que, o número
de casos de teste deve ser limitado, selecionando-se aqueles que, em
hipótese, representam toda a classe. Myers (2004) define duas
propriedades que esse critério deve cumprir:

1. Reduzir o número de casos de teste que devem ser


desenvolvidos para alcançar um objetivo predefinido de teste.
2. Abranger um grande conjunto de outros possíveis casos de
teste.

Pode-se dizer que a principal vantagem no uso dessa estratégia é a


divisão nas classes válidas e inválidas, assim tornando o teste mais fácil,
pois o testador sabe o que deve testar e quais são as validações
necessárias para cada entrada, além de servir como um checklist para o
teste.
Além de limitar de forma eficiente a quantidade de testes, essa
técnica considera que todos os elementos de determinada partição são
equivalentes, ou seja, se um caso de teste de uma classe de equivalência
descobre (ou não) um defeito, todos os outros casos de teste dessa
classe também se comportam de forma equivalente.
As classes de testes podem ser definidas analisando o domínio de
entrada segundo os seguintes critérios (PRESSMAN, 2011):

discriminação de um valor numérico específico;


exigência de um determinado intervalo de valores;
especificação de um membro de um conjunto de valores
relacionados;
definição de uma condição booleana.

O domínio de entrada de um programa é dividido em classes, a


partir das quais os casos de teste podem ser derivados. O objetivo é
executar o programa com o menor número de casos de teste possível, de
forma que estes identifiquem classes de erros.
Uma classe de equivalência representa um conjunto de estados
válidos ou inválidos para condições de entrada. As seguintes diretrizes são
apresentadas em Pressman (2011). A Figura 10 mostra um exemplo da
aplicação do critério baseado em classe de equivalência.

Função que cadastra um identificador através de uma tela. Este


identificador, para ser válido, deve começar por uma letra e conter
apenas letras e números, além de possuir no máximo seis caracteres.

Classe de Equivalência
Entrada Válida Inválida
Tamanho do identificador (T) 1<=T<=6 T<1
T>6
Primeiro caractere é letra Sim Não
Demais caracteres são válidos Sim Não

Figura 10 – Exemplo de aplicação do particionamento em classe de equivalência.


Fonte: Delamaro (2007, p.139).

Os casos de teste devem ser selecionados de forma a possibilitar


que o maior número de atributos de uma classe de equivalência seja
exercitado de uma só vez. Os casos de teste para o particionamento de
equivalência baseiam-se numa avaliação de classes de equivalência para
uma condição de entrada. Uma classe de equivalência representa um
conjunto de estados válidos ou inválidos para condições de entrada.
Tipicamente, uma condição de entrada é um valor numérico, um intervalo
de valores, um conjunto de valores relacionados ou uma condição
booleana. As classes de equivalência podem ser definidas de acordo com
as seguintes diretrizes:

1. Se uma condição de entrada especificar um intervalo, uma


classe de equivalência válida e duas classes de equivalência
inválidas são definidas.
2. Se uma condição de entrada exigir um valor específico, uma
classe de equivalência válida e duas classes de equivalência
inválidas são definidas.
3. Se uma condição de entrada especificar um membro de um
conjunto, uma classe de equivalência válida e uma classe de
equivalência inválida são definidas.
4. Se uma condição de entrada for booleana, uma classe válida e
uma inválida são definidas.

2.4.2 Análise do valor limite

É um refinamento da técnica de particionamento de classe de


equivalência, na qual, com o passar do tempo, notou-se que os defeitos se
manifestavam nos limites das partições. No momento de selecionar um
caso de teste, de determinada classe, são escolhidos casos que estejam
nos limites da classe. Algumas diretrizes são apresentadas em Pressman
(2011) para esta seleção (sendo semelhantes às diretrizes apresentadas
no particionamento em classe de equivalências):

para um intervalo delimitado pelos valores a e b , deve-se projetar


casos de teste com os valores a e b , e logo acima e logo abaixo
de a e b ;
para uma série de valores, os casos devem incluir valores
máximos e mínimos, além de valores logo acima e logo abaixo
destes;
para estruturas internas de dados do programa que têm limites
preestabelecidos (por exemplo, vetores), deve-se projetar casos
de teste que incluam esses valores limite, além de valores fora do
limite, mas muito próximo deste.

Segundo Copeland (2004), os passos necessários para utilizar


esse critério são simples, detalhados no exemplo a seguir:

1. identificar as classes de equivalência;


2. identificar os valores limites de cada classe;
3. criar casos de teste para cada um dos valores limites, valores
superiores e inferiores aos limites.

Para que seja possível determinar valores limite, é preciso que


estejamos tratando de uma partição com elementos ordenáveis, na qual
seja possível dizer que o elemento A é maior que o elemento B. Exemplos
de aplicações viáveis de valores limite:

tamanho de fonte de um texto;


idade de uma pessoa.

Exemplos de aplicações inviáveis de valores limite podem ser os


que utilizados no post sobre partição por equivalência:

cidades atendidas em um sistema de venda com entregas;


tipo de contrato, tipo de foto.

Conforme Myers (2004), os critérios particionamento em classe de


equivalência e análise do valor limite se diferenciam pelo fato de em vez de
selecionar qualquer elemento de uma classe de equivalência, de forma
representativa, a análise do valor limite exige que um ou mais elementos
sejam selecionados de forma que cada extremidade da classe de
equivalência seja objeto de teste.
O particionamento depende dos requisitos, do domínio do programa
e da criatividade do programador. O particionamento, todavia, deveria ser
executado durante todo o ciclo de vida do software.
Na fase de definição do problema, os requisitos funcionais provêm
um particionamento aproximado. No estágio de projeto, a definição das
funções adicionais permite um refinamento da primeira partição.
Finalmente, no estágio de codificação, a implementação dos módulos
projetados gera novos refinamentos.
O uso de uma metodologia de testes top-down permite que cada um
desses refinamentos seja usado na construção de casos de teste no nível
apropriado. O mais alto nível de refinamentos pode ser usado para guiar
os testes de integração entre os módulos representados pelo mais baixo
nível de refinamentos.
A análise de valor limite, portanto, é uma técnica de projeto de casos
de teste que serve como complemento para a técnica de particionamento
de classes. Ao invés de selecionar qualquer valor de uma classe de
equivalência, a análise do valor limite leva à seleção de casos de teste nas
“extremidades” da classe. Em vez de se concentrar somente nas
condições de entrada, ela deriva os casos de teste também do domínio de
saída. Se uma condição de entrada especificar um intervalo delimitado
pelos valores a e b, os casos de teste devem ser projetados com valores a
e b, logo acima e logo abaixo de a e b, respectivamente.
Embora aumente os casos de teste, a técnica de análise de valor
limite garante que erros comuns de interpretação de requisitos sejam
evitados, assim livra-se de problemas em que se inclui um valor ou exclui
por não conseguir identificar se inclui ou não aquele extremo. As Tabelas 1
e 2 mostram os casos de teste gerados para a especificação da Figura 10,
onde respectivamente mostra-se os casos de teste para atender ao critério
do particionamento em classe de equivalência e análise de valor limite.

Quadro 1 – Casos de teste para particionamento em classe de


equivalência
T Primeiro Demais Resultado esperado
Caractere Caracteres
4 Sim Sim Identificador cadastrado
0 --- --- Erro no tamanho do identificador
9 --- --- Erro no tamanho do identificador
4 Não ---- Erro primeiro caractere não é letra
4 Sim Não Erro demais caracteres não são válidos
para identificador
Fonte: elaborado pela autora.

Observa-se no Quadro 1 que não existe nenhum rigor na geração


dos casos de teste, basta que estes sigam as diretrizes de atender aos
critérios das partições válidas e inválidas de cada variável de entrada.
Porém, ao observar o Quadro 2, pode-se perceber/notar que já existe um
rigor ao escolher os dados de teste para cada variável.

Quadro 2 – Casos de teste para análise de valor limite


T Primeiro Demais Resultado Esperado
Caractere Caracteres
1 Sim Sim Identificador cadastrado
6 Sim Sim Cadastra identificado
0 --- --- Erro no tamanho do identificador
7 --- --- Erro no tamanho do identificador
1 Não ---- Erro primeiro caractere não é letra
1 Sim Não Erro demais caracteres não são válidos
para identificador
Fonte: elaborado pela autora.

Observa-se um aumento no número de casos de teste quando


usada a análise de valor limite, mas com isso possibilita-se encontrar um
número maior de defeitos, especialmente na ocorrência de uma
consistência incorreta no caso do tamanho do identificador, em que se
pode, por engano, esquecer de comparar se é maior e igual ou menor e
igual.

2.4.3 Teste sistemático

Definido como uma abordagem sistêmica de testes funcionais,


essa técnica propõe combinações de alguns critérios de testes funcionais
objetivando obter, do código em testes, um índice de cobertura da
implementação tão alto quanto do teste estrutural. Esse tipo de teste faz
uso da experiência do testador, em que este incluirá nos valores a serem
utilizados no teste alguns valores que julgue pertinentes e que, conforme
sua experiência, serão utilizados pelos usuários, tais como NULL,
espaços, entre outros. O Quadro 3 demonstra possíveis casos de teste
sistemático para a especificação da Figura 10.
Além dos critérios abordados no critério de análise de valor limite,
outros pontos, como forma de sistematizar a execução do teste, devem ser
considerados, conforme estes itens apontados:

1. Necessariamente, devem ser criados pelo menos dois casos de


teste com cada partição de equivalência, minimizando, assim, o
problema de erros coincidentes que mascaram falhas.
2. Para valores numéricos discretos, devem ser considerados os
dados de entrada e saída e casos de testes são gerados para
cada classe.
3. Para intervalos de valores numéricos, também devem ser
considerados os dados de entrada e saída, e os casos de testes
são derivados contemplando os limites e um valor interno de
cada intervalo.
4. Devem ser gerados casos de teste com valores diferentes do
esperado e com casos especiais, tanto para os dados de
entrada quanto para os dados de saída.
5. Casos de teste que exploram valores ilegais são necessários
para mostrar que o software em teste trata desvios do caminho
de sucesso. Assim, considerar valores fora dos limites máximo e
mínimo de um intervalo, por exemplo, são casos de teste
relevantes.
6. Ao criar casos de teste que contemplem números reais, deve ser
observada uma especificidade: esse tipo de dado não possui
um limite exato. Normalmente, números reais são inscritos em
base de dez, armazenados em base de dois e finalmente
recuperados em base de dez, gerando dados inconsistentes.
Assim, devem ser criados casos de teste que contemplem essa
situação, adotando um intervalo de exatidão de erro, com
diferentes valores limite. Além disso, devem ser criados casos
de teste que considerem valores reais muito pequenos e o valor
zero.
7. Para valores de intervalo variáveis, que dependem de uma ou
mais variáveis, devem ser criados casos de teste que
contemplem todas as possibilidades de combinação dos
possíveis valores.
8. Quando a informação a ser testada envolve vetor ou matriz de
dados, devem ser criados casos de teste que avaliem o tamanho
da matriz e os dados da matriz. O tamanho da matriz deve ser
testado, em todas as dimensões e em todas as possíveis
combinações, no seu tamanho mínimo, máximo e em valores
intermediários. Para os valores dos dados do array, devem ser
consideradas as questões levantadas anteriormente.
9. Para textos ou string de dados, é necessário validar a variação do
tamanho e a validade de cada caractere, considerando o alfabeto
apenas de caracteres ou o alfanumérico ou, ainda, apenas o de
pontuação.

Quadro 3 – Casos de teste para teste sistemático


T Primeiro Demais Resultado Esperado
Caractere Caracteres
1 Sim Sim Identificador cadastrado
6 Sim Sim Identificador cadastrado
0 --- --- Erro no tamanho do identificador
7 --- --- Erro no tamanho do identificador
1 Não ---- Erro primeiro caractere não é letra
1 Sim Não Erro demais caracteres não são
válidos para identificador
A --- --- Erro no tamanho do identificador
1,9 --- --- Erro no tamanho do identificador
Erro no tamanho do identificador
1 Branco Sim Erro no primeiro caractere do
identificador
1 Sim Branco Erro nos demais caracteres do
identificador
Fonte: elaborado pela autora.

Diz-se que este teste é baseado na experiência, pois conforme as


características do software, alguns tipos de erros são possíveis, além do
fato de que conhecendoos softwares e os erros cometidos pelos
desenvolvedores, pode-se criar alguns casos de teste extras para as
partições inválidas. O teste sistemático, se comparado com o
particionamento em classe de equivalência e análise de valor limite, é o
primeiro que demonstra preocupação não apenas com o domínio de
entrada, mas também com o domínio de saída.

2.4.4 Grafo causa-efeito

Os critérios de particionamento em classe de equivalência, análise


de valor limite e teste sistemático preocupam-se com os valores de
entrada de maneira isolada, desse modo, não possibilitam a geração de
casos de teste em que a combinação de dois ou mais campos de entrada
torna-se importante.
O grafo causa-efeito representa concisamente entradas, condições
lógicas e saídas correspondentes. As seguintes quatro etapas são
sugeridas (MYERS, 2004; PRESSMAN, 2011):

1. determinação das causas e efeitos de um módulo, identificando-


os unicamente;
2. desenvolvimento de um grafo causa-efeito;
3. conversão do grafo em uma tabela de decisão;
4. conversão das regras da tabela de decisão em casos de teste.

O grafo é construído a partir de estruturas que combinam as


entradas, tais como: “ou”, “e” e “negação”. A Figura 11 mostra um exemplo
de aplicação do grafo.

Um programa lê dois caracteres e de acodo com seus valores


mensagens serão impressas. O primeiro caractere deve ser “A” ou “B”. O
segundo, um dígito. Caso esteja correto, um arquivo é atualizado.Se o
primeiro caractere é incorreto, enviar a mensagem X, e se o segundo é
incorreto, envia a mensagem Y.

Causas:

Caractere na coluna 1 é “A”


Caractere na coluna 1 é “B”
Caractere na coluna 2 é um dígito.

Efeitos:

atualiza arquivo;
mensagem X;
mensagem Y.
Onde: V = ou, Λ = e, enquanto negação =
Figura 11 – Exemplo de construção do grafo causa e efeito.
Fonte: Delamaro (2007, p. 140).

2.4.5 Tabela de decisão

A tabela de decisão, segundo a literatura, baseia-se na ideia da


divisão das causas e efeitos definidos a partir de uma especificação e, em
especial, possibilitando a condenação dos campos.
Difere-se da estratégia utilizada pelo grafo causa e efeito pela forma,
tornando-se uma maneira mais efetiva e sua aplicação mais viável na
prática. A principal vantagem do uso dessa estratégia refere-se à definição
da quantidade de casos de teste necessária para testar determinada
especificação, pois após a construção da tabela, em que se definem todas
as possíveis combinações de causas para geração de efeitos, o número
de casos de teste será igual ao número de colunas da tabela. O Quadro 4
mostra a tabela de decisão definida a partir da especificação da Figura 11.

Quadro 4 – Tabela de decisão


Causas
1 V -- F V F
2 -- V --- -- ---
3 V V V F F
Efeitos
20 V V F F F
21 F F V F V
22 F F F V V
Fonte: adaptado de Delamaro (2007, p. 141).

Observa-se no Quadro 4 que com cinco casos de teste consegue-


se testar todas as causas que levam aos efeitos definidos para esta
função. Assim, torna-se mais fácil definir o tamanho do teste.
CAPÍTULO 3
TESTE ESTRUTURAL DE SOFTWARE
Este capítulo tem como objetivo apresentar o teste estrutural de software. Esse
teste é um tipo especializado de teste, pois necessita de informações relacionadas à
implementação do código-fonte e de conhecimento em linguagem de programação
para ser utilizado, isto é, necessita de instrumentação do código e, para isso, conhecer
a linguagem de programação (ou o paradigma de programação) é importante.

O teste estrutural, também chamado de teste de caixa-branca ou


teste baseado na implementação, visa conhecer o funcionamento interno
de um produto e verificar que a operação interna do produto tem um
desempenho de acordo com as especificações e que os componentes
internos foram adequadamente postos à prova. Usando métodos
estruturais, o engenheiro de software pode derivar casos de teste que
garantam que todos os caminhos independentes dentro de um módulo
tenham sido exercitados pelo menos uma vez, que todas as decisões
lógicas para valores falsos ou verdadeiros sejam executadas, que os
laços em suas fronteiras e dentro de seus limites operacionais sejam
testados e que as estruturas de dados internas sejam exercitadas para
garantir sua validade.
Diferentemente dos testes funcionais, que se preocupam com a
função que o programa desempenha sem atentar para como a função foi
implementada, o teste estrutural enfoca a implementação e a estrutura da
função. Embora geralmente usado durante a fase de codificação, testes
estruturais devem ser usados nas fases do ciclo de vida do software nas
quais o software é representado formalmente. A intenção do teste
estrutural é encontrar dados de teste que terão cobertura suficiente de
todas as estruturas presentes na representação formal. As principais
razões para a aplicação de testes de caixa-branca são:

Erros lógicos e pressuposições incorretas são inversamente


proporcionais à probabilidade de que um caminho de programa
seja executado: geralmente o processamento principal possui
menor incidência de erros por ser mais conhecido e mais
esmiuçado do que, por exemplo, um processamento de caso
especial.
Muitas vezes acreditamos que um caminho lógico não tem a
probabilidade de ser executado quando, de fato, ele pode ser
executado regularmente: pressuposições inconscientes sobre o
fluxo de controle e de dados podem levar-nos a cometer erros de
projeto que são descobertos somente quando se inicia a
atividade de teste de caminho.
Erros tipográficos são aleatórios: a probabilidade de ocorrência
de erros de digitação quando da conversão do projeto para código
é considerável. Alguns serão descobertos durante a compilação
do programa, mas outros podem permanecer até a fase de
testes.

No teste estrutural, os casos de teste são derivados a partir da


análise da estrutura interna do programa. O objetivo dos casos de teste é
causar a execução de caminhos identificados no programa, baseados no
fluxo de controle e/ou no fluxo de dados. Os principais problemas dessa
abordagem são:

programas com laços (repetições) possuem um número de


caminhos infinito, já que a análise da estrutura interna do
programa é feita estaticamente. Desta forma, seria necessário
aplicar o teste exaustivo ao programa, o que é considerado
impraticável (MYERS, 2004);
existência de caminhos não executáveis (infeasib le paths) no
programa, que ocasionam o desperdício de tempo e recursos
financeiros na tentativa de gerar casos de teste que possam
executar esses caminhos;
a execução bem-sucedida de um caminho do programa
selecionado não garante que este esteja correto, já que com outro
caso de teste um erro pode ocorrer.

A fim de minimizar esses problemas, são utilizados critérios de


seleção de caminhos, que podem ser divididos em dois grupos, de acordo
com as características nas quais mais se baseiam: fluxo de controle e
fluxo de dados.
Estes critérios, conhecidos como "critérios de cobertura", ou
"critérios de seleção", são condições que devem ser preenchidas pelo
teste, as quais selecionam determinados caminhos que visam cobrir o
código ou a representação gráfica deste. Um critério é válido se a
execução de pelo menos um dos casos de teste detectar erros no
programa. E é ideal se ele fornece um conjunto de casos de teste que
detecte todos os erros do programa que o critério se propõe a detectar.
3.1 Critérios baseados no fluxo de controle

Os critérios de cobertura baseados no fluxo de controle


fundamentam-se na seleção de um conjunto C de elementos (arcos,
laços, nodos ou subcaminhos) no Grafo de Fluxo de Controle (GFC) do
programa em teste (para teste de unidade) ou no Diagrama de Chamadas
(DC) do sistema (para os testes de subsistema e de sistema).
Para a representação de um módulo do sistema através de um
GFC, o código do módulo deve ser decomposto em um conjunto de blocos
disjuntos, de forma que a execução do primeiro comando de um bloco
acarrete a execução de todos os outros comandos, em ordem, neste
bloco. Todos os comandos de um bloco têm um único predecessor, com a
exceção do primeiro, e um único sucessor, com a exceção do último. Um
GFC estabelece correspondência entre nodos e bloco, e entre arcos e
desvios de fluxo de controle. Desta forma, ele pode ser representado pela
tripla (N,E,s), onde N representa o conjunto de nodos, E o conjunto de
arcos e s o nodo de entrada (MALDONADO, 1991). A Figura 12 apresenta
as principais estruturas de um GFC. Já a Figura 13 apresenta um exemplo
de DC (cuja adaptação em relação ao modelo usado na literatura é
apresentado em (SILVA, 1995).
Um caminho em um GFC é uma sequência de nodos (n1, n2,...,nk),
tal que exista um arco de ni para ni+1 . Exemplos de critérios baseados no
fluxo de controle da unidade são listados a seguir, sendo identificado
quando estes são satisfeitos (MYERS, 2004):

Cobertura por nodos (ou comandos): todos os nodos/comandos


devem ser executados pelo menos uma vez.
Cobertura por arcos (ou decisões): todos os arcos/decisões
devem ser executados pelo menos uma vez.
Cobertura de todos os caminhos: todos os caminhos possíveis
devem ser executados pelo menos uma vez (problema:
programas com laços).
Cobertura por condições: todas as condições de uma decisão
devem ser executadas pelo menos uma vez.
Cobertura por condição e decisão: combinação dos critérios "por
condições" e "por decisões".
Cobertura por condições múltiplas: todas as combinações
possíveis em cada decisão devem ser executadas pelo menos
uma vez.
Figura 12 – Principais estruturas de um GFC.
Fonte: Pressman (2011, p. 568).
Figura 13 – Exemplo de diagrama de chamadas de sistema.
Fonte: Silv a (1995, p. 23).

Um diagrama de chamadas representa as relações


interprocedurais do sistema, mostrando as possíveis ordens de execução
dos módulos. Em Silva (1995), foram propostos três critérios de seleção
de caminhos para subsistemas ou sistemas, baseados nos critérios de
unidade. O Quadro 5 apresenta a relação entre os critérios propostos e os
critérios nos quais estes se basearam:

Quadro 5 – Relação entre critérios de unidade e critérios de sistema


Critérios de Unidade Critérios de Sistema
todos-caminhos todos-caminhos-interprocedurais
todos-arcos todos-arcos-chamada
todos-nodos todos-módulos
Fonte: elaborado pela autora.
Com base em um diagrama de chamadas, define-se caminho
possível de execução como sendo uma lista de nomes de módulos,
ordenada de acordo com as chamadas realizadas, em que o primeiro
elemento da lista é o módulo principal. Assumiu-se que após desviada a
execução para o módulo chamado, o fluxo de execução sempre retorna ao
módulo chamador. Desta forma, a execução do sistema sempre termina
com o controle do módulo principal.
Um caminho de execução é uma lista de nomes de módulos, sendo
consideradas apenas as chamadas realizadas em determinada execução.
É feita a análise dinâmica, a partir da execução do programa
instrumentado. Os critérios são definidos a seguir:

Todos-caminhos-interprocedurais: o caminho possível de


execução é convertido em uma expressão regular. Ou seja, não se
tem como resultado subcaminhos, e sim a expressão resultante.
A partir dessa expressão, é construído um autômato finito não
determinístico, para a avaliação do caminho de execução.
Todos-arcos-chamada: os arcos do diagrama de chamadas são
comparados com o caminho de execução, procurando arcos que
não tenham ainda sido executados. O critério é satisfeito quando
todos os arcos estiverem incluídos no mesmo.
Todos-módulos: cada módulo deve ser executado pelo menos
uma vez.

Existem diferentes maneiras de realizar os testes baseados em


fluxo de controle. Escolhe-se o critério conforme a cobertura desejada,
assim, tem-se: cobertura de caminho básico, cobertura de comando,
cobertura de decisão, cobertura de condição e cobertura de repetição.

3.1.1 Cobertura de caminho básico ou teste baseado na complexidade

Proposta por McCabe (1976), possibilita que o projetista do caso de


teste derive uma medida da complexidade lógica de um projeto
procedimental e use-a como guia para definir um conjunto básico de
caminhos de execução. Os casos de teste derivados para exercitarem o
conjunto básico têm a garantia de executar cada instrução do programa
pelo menos uma vez durante a atividade de teste.
Embora o teste do caminho básico seja simples e altamente efetivo,
ele não é suficiente por si só. Outras variações de teste de estrutura de
controle são discutidas. Elas ampliam a cobertura dos testes e melhoram
a qualidade do teste de caixa-branca.
Para determinar quantos e quais são os caminhos que devem ser
testados, uma técnica bastante utilizada é a complexidade ciclomática.
Trata-se de uma métrica de software que proporciona uma medida
quantitativa da complexidade lógica de um programa. Quando usado no
contexto do método de teste do caminho básico, o valor computado da
complexidade ciclomática define o número de caminhos independentes do
conjunto básico de um programa e oferece-nos um limite máximo para o
número de testes que deve ser executado para garantir que todas as
instruções sejam executadas pelo menos uma vez.
Um caminho independente é qualquer caminho através do
programa que introduza um novo conjunto de instruções de
processamento ou uma condição nova. Se cada caminho básico for
testado, cada instrução do programa terá a garantia de ser executada pelo
menos uma vez e cada condição terá sido executada com resultado
verdadeiro e falso.
A complexidade ciclomática tem suas bases na teoria dos grafos.
Nesse método, as construções estruturadas do programa são
representadas na forma de grafos de fluxo (PRESSMAN, 2011). Uma ou
mais instruções procedimentais denomina-se nó. Os arcos do grafo de
fluxo, que indicam o fluxo lógico do processamento, são denominados
ramos. Se um nó contém uma condição, ele é denominado nó predicativo.
Pode-se observar a aplicação desses conceitos na Figura 14.
Figura 14 – Grafo de fluxo de controle.
Fonte: Pressman (2011, p.568).

A complexidade é computada das seguintes formas:

O número de regiões do gráfico de fluxo corresponde à


complexidade ciclomática.
A complexidade ciclomática, V(G), para um fluxo de grafo G, é
definida como:

V(G) = E – N + 2, em que E é o número de ramos do grafo e N, o


número de nós do grafo de fluxo.

A complexidade ciclomática, V(G), para um grafo de fluxo G, é


definida como

V(G) = P + 1, em que P é o número de nós predicativos contidos no


grafo de fluxo G.
Para projetar casos de teste utilizando esse método, deve-se definir
os caminhos de teste, e para defini-los, são necessários os seguintes
passos:

1. usando o projeto ou o código como base, trace um grafo de fluxo


correspondente;
2. determine a complexidade ciclomática do grafo de fluxo
resultante;
3. determine um conjunto básico de caminhos linearmente
independentes;
4. prepare casos de teste que forcem a execução de cada caminho
no conjunto básico;
5. verifique se o resultado realizado é igual ao resultado esperado.

A Figura 15 mostra um exemplo da construção de um grafo de fluxo


de controle a partir de um trecho de código e mostra o valor da
complexidade ciclomática para esse código.
Figura 15 – Exemplo de criação do GFC.
Fonte: elaborada pela autora.

A complexidade ciclomática do programa descrito na Figura 14 é 3.


Este valor foi calculado de duas maneiras. A primeira, através do número
de nós predicativos (comandos de decisão), em que se tem 1 while e 1 if
(1+1 + 1 (este da fórmula), ou através da quantidade de arcos (9) subtraída
do número de nós (8) e adicionada ao valor 2 (da fórmula), então 9 – 8 + 2
= 3.
O que significa este valor no critério baseado na complexidade?
Significa que teremos 3 caminhos para percorrer no código, gerando-se,
desse modo, os casos de teste. Assim, no exemplo da Figura 15, os
caminhos resultantes seriam: 1, 2, 3, 4, 5, 7, 3, 8; 1, 2, 3, 4, 6, 7, 3, 8 e 1, 2,
3, 8.
Mas por que é importante conhecer a complexidade ciclomática ou
os caminhos de teste resultantes do critério de caminho básico? Para
conseguir identificar caminhos não factíveis ou caminhos impossíveis de
serem percorridos em uma única execução do programa. A existência
desse tipo de caminho demostra que o programa pode estar
estruturalmente incorreto, dificultando a identificação de defeitos,
aumentando a complexidade e o tempo para a automatização do teste,
além de interferir na performance e no espaço ocupado por este código. A
Figura 16 mostra um código em que existem caminhos não factíveis.

Figura 16 – Caminhos não factíveis.


Fonte: elaborada pela autora.

A existência de caminhos não factíveis não será percebida pelo teste


funcional, pois a função está correta, porém, influenciará no desempenho
desse código e necessitando que a sua estruturação lógica seja alterada.

3.1.2 Cobertura de comando

O objetivo do teste baseado em cobertura de comando é definir


casos de teste que executem todos os comandos pelo menos uma vez
(passando por todos os nodos do grafo). Pode-se dizer que a métrica é o
número de nodos cobertos.
Para a geração dos casos de teste, deve-se definir caminhos de
teste que exercitem cada comando do código pelo menos uma vez. A
cobertura é fácil de satisfazer, no programa do triângulo, da Figura 16,
bastariam três casos de teste para realizar a cobertura de todos os
comandos (caminhos 4, 5, 6, 7,8, 9, 11, 12; 4, 5, 6, 7, 9, 10, 11, 13 e 4, 5, 6,
7, 9, 11, 12, 13),No entanto, se existe algum valor condicional em um
destes caminhos que não é exercitado, o erro será mascarado.
No caso do exemplo da Figura 15, os caminhos de teste para
atender a essa cobertura seriam 1, 2, 3, 4, 5, 7, 3, 8 e 1, 2, 3, 4, 6, 7, 3, 8.

3.1.3 Cobertura de decisão

Para atender ao critério de cobertura de decisão, os testes devem


cobrir cada saída possível de um nodo que tenha uma condição. A métrica
é o número de arestas cobertas.
Pode-se observar que em algumas situações a cobertura de
decisão implica a cobertura de comando, mas o inverso nem sempre é
verdade, isto deve-se ao fato do uso de comando if, que em algumas
situações não apresenta o else.
No exemplo da Figura 15, os caminhos de teste para atender esse
critério seriam 1, 2, 3, 4, 5, 7, 3, 8; 1, 2, 3, 4, 6, 7, 3, 8 e 1, 2, 3, 8.

3.1.4 Cobertura de condição

Em adição aos testes de caminho básico, outros testes estruturais


podem e devem ser aplicados. Um deles é o teste de condição. O teste de
condição é um método de projeto de casos de teste que põe à prova as
condições lógicas contidas num módulo de programa. Este método
concentra-se em testar cada condição do programa e propõe-se a
descobrir as seguintes classes de erros:

erro de operador booleano (incorretos/em falta/ em excesso);


erro de variável booleana ;
erro de parênteses booleanos;
erro de operador relacional;
erro de expressão aritmética.

As estratégias de teste de condição têm duas vantagens. Primeiro, a


medição da cobertura do teste de uma condição é simples. Segundo, a
cobertura de teste das condições de um programa oferece orientação para
a geração de testes adicionais ao programa. O propósito do teste de
condição é detectar não somente erros nas condições de um programa,
mas também outros erros no programa.
Nesse critério de geração de casos de teste, para cada decisão,
deve-se cobrir os dois resultados possíveis. Por exemplo, no caso de um if
((A>0) or (B<10)), os casos de teste teriam que cobrir as seguintes
situações:

A = 3 e B = 20 (A verdade e B Falso);
A = 0 e B = 5 (A falso e B verdade).

3.1.5 Cobertura de repetição

Os laços são amplamente utilizados na estrutura dos programas.


Raros são os programas que não utilizam a estrutura de loop para controle
de execução.
O teste de laços se concentra exclusivamente na validade das
construções de laços, sendo que podemos definir as classes de laços
como laços simples, laços concatenados, laços aninhados e laços não
estruturados.
As condições de teste para cada classe de laços simples é a
seguinte (PRESSMAN, 2011):

1. pule o laço inteiramente;


2. somente uma passagem através do laço;
3. duas passagens através do laço
4. m passagens através do laço, onde m<n;
5. n-1, n e n+1 passagens através do laço.

As condições de teste para cada classe de laços aninhados é a


seguinte (MYERS, 2004):

1. Comece pelo laço localizado mais internamente. Fixe todos os


laços em valores mínimos.
2. Realize testes de laços simples para o laço mais interno,
mantendo ao mesmo tempo os laços externos em seus valores
de parâmetro de interação mínimos.
3. Trabalhe para fora, realizando testes para o laço seguinte, mas
mantendo todos os outros laços externos em valores mínimos.
4. Continue até que todos os laços tenham sido testados.

3.2 Critérios baseados no fluxo de dados

Os critérios baseados no fluxo de dados apoiam-se na análise de


fluxo de dados do programa, utilizada tradicionalmente na implementação
de compiladores para a otimização de código. Esse tipo de análise
considera as relações entre definições e usos de variáveis, resolvendo
algumas falhas encontradas nos critérios baseados no fluxo de controle.
Então, esse critério gera o teste a partir das interações que envolvem as
definições de variáveis e subsequentes referências a essas definições.
Um dos princípios da análise do fluxo de controle é que um caminho
que nunca foi executado não pode ser considerado confiável (MYERS,
2004). Do mesmo modo, o resultado de uma computação que nunca é
aplicado também não pode ser considerado confiável, o que justifica a
consideração da análise do fluxo de dados no teste de programas.
O teste de fluxo de dados exige a cobertura de caminhos que podem
não ser exigidos pelo critério de teste de fluxo de controle. No GFC da
Figura 17, para satisfazer cobertura de condição, basta cobrir os caminhos:
1, 2, 4, 5, 7 e 1, 3, 4, 6, 7. Porém, se o nodo 2 for um nodo definição para
uma variável v qualquer e 6 um nodo uso para v, esse caminho não será
testado.
Isto ocorre porque no teste de fluxo de controle consideram-se
apenas caminhos completos (do nodo inicial ao final). No teste de fluxo de
dados os subcaminhos tornam-se importantes. Consideram-se os
caminhos que ligam um nodo definição a um nodo uso.

Figura 17 – Exemplo de grafo de fluxo de controle.


Fonte: elaborada pela autora.

As estratégias de fluxo de dados são úteis para selecionar


caminhos de teste de um programa que contenha instruções de laços e if
aninhados. O problema de medir a cobertura de teste e a seleção de
caminhos de teste para o teste de fluxo de dados são mais complexos do
que os correspondentes problemas para o teste de condição.
Para o teste de unidade, o GFC é estendido, acrescentando-se aos
nodos e arcos as relações de definições e usos de variáveis, gerando um
grafo def/uso (definições/usos). Uma definição de variável ocorre quando
um valor é armazenado em uma posição de memória. Um c-uso (uso
computacional) (RAPPS, 1985) ocorre quando a variável é utilizada do lado
direito de uma computação. Um p-uso (uso em predicado) (RAPPS, 1985)
ocorre quando uma variável é utilizada em uma comparação. Definições e
c-usos são associados aos nodos, enquanto que p-usos são associados
aos arcos.
Pode-se dizer que um nodo n no GFC é um nodo definição de uma
variável v se v recebe um valor no comando representado por n aqui
denominamos def(v,n). Já um nodo n no GFC é um nodo uso de uma
variável v se o valor de v é usado (referenciado) no comando representado
por n, com isto denota-se esse fato por use(v,n). Nodos definição estão
presentes em comandos de atribuição, comandos de entrada e em
parâmetros por referência que são alterados no corpo da rotina. Enquanto
nodos de uso encontram-se em comandos condicionais, comandos de
saída e em parâmetros por valor ou parâmetros por referência que não
são alterados no corpo da rotina. Já podem existir nodos híbridos, tais
como na equação i = i + 1.
Um caminho do GFC que não contenha uma definição de uma
variável nos nodos ni,...,nm é chamado de caminho livre de definição.
Já o conceito de caminho-d-u (definition-use) em relação a uma
variável v em um GFC torna-se importante, pois é um subcaminho do GFC
tal que o nodo inicial m do caminho é um nodo definição de v e o nodo final
n é um nodo uso de v (use(v,n)). Enquanto o caminho-d-c (definition-clear)
em relação a uma variável v em um GFC é um caminho-d-u tal que não
existe outro nodo definição de v no caminho além do nodo inicial m. E o
teste baseado no fluxo de dados pretende identificar as seguintes
situações:

caminho-d-u que possui um caminho-d-c são caminhos em que a


variável é inicializada duas vezes antes de ser usada.
nodos uso que não pertencem a nenhum caminho-d-u
correspondem a variáveis usadas sem terem sido previamente
inicializadas;
nodos definição que não pertencem a nenhum caminho-d-c
correspondem a variáveis inicializadas, mas não usadas.

Vários critérios foram propostos por Rapps e Weyuker (1985). Três


deles são apresentados a seguir, como exemplos em que o GFC
representa um grafo definição/uso e P um conjunto de caminhos
completos do GFC.

Todas-definições (all-defs): P satisfaz este critério se para todo


nodo i do GFC e para todo x, P inclui um caminho livre de
definições, isto é, para cada nodo definição de cada variável de P,
cobre-se pelo menos um caminho-d-c para algum nodo uso. As
Figuras 18 e 19 mostra um exemplo da aplicação do critério all-
defs.
Todos-p-usos: P satisfaz este critério se para todo nodo i do GFC
e para todo xdef(i), P inclui um caminho livre de definições c.r.a x
de i para todos os elementos de dpu(x,i).
Todos-usos (all-uses): P satisfaz este critério se para todo nodo i
de GFC e para todo x, P inclui um caminho livre de definições, isto
é, para cada variável v de P cobre-se pelo menos um caminho-d-c
de cada nodo definição de v para cada nodo uso de v e cada nodo
sucessor deste nodo uso. A Tabela 5 mostra os caminhos de
teste para atender ao critério all-uses.
Figura 18 – Exemplo de GFC para geração de caminhos da cobertura de fluxo de
dados.
Fonte: elaborada pela autora.
Figura 19 – Tabela de nodos definição e uso e caminhos de teste para all-defs.
Fonte: elaborada pela autora.

A primeira tabela da Figura 19 será utilizada para os dois critérios,


all-defs e all-uses. Sabe-se que a quantidade de nodos em cada coluna,
respectivamente definição e uso de cada variável, irá determinar a
quantidade de caminhos de teste que serão gerados e,
consequentemente, o tamanho do teste.

Tabela 1 – Caminhos de teste para all-uses


Variável Caminho
tab 2-3-4-5-6
tab 2-3-4-5-6-7-12
t 3-4-5-6-7
t 3-4-5-6-8
t 3-4-5-10-11
i 4-5-6
i 4-5-10
i 4-5-6-8
i 4-5-6-7-12
i 8-5-6
i 8-5-10
i 8-5-6-8
i 8-5-6-7-12
Fonte: elaborada pela autora.

Nota-se na Tabela 1 um aumento considerável nos caminhos de


teste baseado no critério all-uses, se comparado aos definidos pelo critério
all-defs, porém, cabe ressaltar que a possibilidade de descobrir os
defeitos é diretamente proporcional ao número de casos de teste gerados
pela estratégia escolhida.
CAPÍTULO 4
TESTE BASEADO EM ERROS (ANÁLISE DE MUTANTES)
Os critérios de teste funcional e de teste estrutural apresentam como objetivo
gerar casos de teste. No caso do teste estrutural, inicialmente, são gerados os caminhos
de teste, os quais irão percorrer o grafo de fluxo de controle para atender algum critério
de cobertura para então gerar casos de teste que incentivem a execução dos caminhos
gerados. Por outro lado, o teste baseado em erros, algumas vezes denominado de teste
baseado em falhas, o qual necessita de instrumentação do código-fonte do software,
torna-se um teste mais especializado e ao mesmo tempo não tão aplicável
comercialmente, devido à complexidade e ao tempo de aplicação. [Ambos?] têm
como objetivo qualificar os casos de teste, que podem ser gerados através das
estratégias do teste funcional ou do teste estrutural.

Os elementos requeridos pelo critério "análise de mutantes" são


baseados em erros comuns que o programador pode cometer durante o
desenvolvimento de software (VINCENZI, 1997). O critério surgiu na
década de 1970, sendo baseado em um método clássico de detecção de
erros lógicos em circuitos digitais – o modelo de teste de falha única
(VINCENZI, 1997). Assume-se que programadores experientes codificam
programas quase corretos. Desta forma, afirma-se que grande parte dos
erros dos programas são introduzidos por variações sintáticas, que
embora não se constituam em erros sintáticos, constituem-se em erros
semânticos.
A partir de um programa P, o qual assume-se como correto ou
próximo de correto, gera-se um conjunto de programas semelhantes a P,
denominados mutantes (DEMILLO, 1978). As diferenças entre P e seus
mutantes estão em pequenas variações sintáticas dele. A seguir, devem
ser gerados casos de teste que sejam capazes de provocar diferenças de
comportamento entre P e seus mutantes. As diferenças são geradas a
partir da utilização de um conjunto de operadores denominados
operadores de mutação, podendo ser associado a cada operador uma
classe de erros. A análise de mutantes consiste em quatro etapas:
geração de mutantes, execução de P a partir de um conjunto de casos de
teste T, execução dos mutantes a partir de T e análise dos mutantes.
A análise dos mutantes ocorre da seguinte forma: se um mutante Pi
apresenta resultados diferentes dos apresentados por P, diz-se que este
mutante está morto, pois T identificou o erro no mutante. Caso Pi
apresentar resultados iguais aos apresentados por P, diz-se que ele
continua vivo, o que pode ocorrer caso T não contenha casos de teste
capazes de distinguir Pi de P ou porque ambos os programas executam
as mesmas funções, sendo equivalentes. No primeiro caso, novos casos
de teste devem ser gerados para que a distinção ocorra. Um problema no
segundo caso é que a questão de equivalência entre programas é uma
questão impossível de decidir.
Mas porque gastar tempo e energia preocupando-se e testando
minúcias lógicas quando poderíamos gastar melhor nosso esforço
demonstrando que os requisitos do programa foram cumpridos? Em
outras palavras, por que não gastamos todas as nossas energias em
teste de caixa-preta?
Porque:

Erros tendem a se infiltrar em nosso trabalho quando projetamos


e implementamos funções, condições ou controles que estejam
fora da função principal. O processamento cotidiano tende a ser
bem entendido, enquanto o processamento de um "caso
especial" tende a "cair por terra".
Quando um programa é traduzido para código-fonte de linguagem
de programação, é provável que alguns erros de digitação
ocorram. Muitos deles serão descobertos por mecanismos de
verificação de sintaxe, mas outros passarão a ser detectados até
que os testes se iniciem. É provável que exista um erro tipográfico
tanto num caminho lógico obscuro como num caminho da
corrente principal.

Cada uma dessas razões oferece um argumento para a realização


de testes de caixa-branca. Os testes de caixa-preta, não importa quão
cuidadosos sejam, podem não relevar os tipos de erros observados
anteriormente.. Os testes de caixa-branca têm maior probabilidade de
descobri-los.
Portanto, a análise de mutantes ou teste baseado em erros consiste
em incluir propositalmente algum erro no programa e observar o seu
comportamento com erro comparando-o com o comportamento do
programa original, dito livre de erros, assim possibilitando o fornecimento
de indicadores para gerenciar o processo de teste, especialmente a
porcentagem de erros remanecentes, e a qualidade dos casos de teste
que estão sendo gerado.
Para que essa técnica de teste seja aplicada, deve-se conhecer os
tipos de erros conhecidos, criando-se um modelo chamado de operadores
de mutação. Como exemplo, pode-se destacar:
substituição de uma variável por outra;
substituição de uma variável escalar por um vetor;
substituição de um vetor por uma variável escalar;
substituição de operador relacional;
substituição de operador aritmético.

O que se observa é que esse tipo de teste é extremamente


demorado, pois para um programa pode-se gerar inúmeros mutantes,
uma vez que a partir do programa original geram-se programas com
pequenos erros e criam-se casos de teste capaz de detectá-los. E para
verificar se um teste detecta o erro introduzido, compara-se o
comportamento do mutante com o do programa original. As Figuras 21 e
22 mostram, respectivamente, o programa original com seus casos de
teste e o programa mutante com a necessidade de acréscimo de casos de
teste para descobrir o erro.

Figura 20 – Exemplo de um programa original com casos de teste.


Fonte: elaborada pela autora.

Figura 22 – Programa Mutante com seu conjunto de dados de teste.


Fonte: elaborada pela autora.

O objetivo é matar os mutantes gerados através dos casos de


testes. Um teste T mata um mutante P’ se o resultado da execução de P’
para T é diferente do resultado da execução de P para T. Processo de teste
de mutação é:
Iniciar com o programa P a ser testado e um conjunto de testes T
(possivelmente vazio).
Gerar um conjunto M de mutantes de P, através de operadores de
mutação (pequenas alterações sintaticamente corretas) no
programa original.
Verificar se os testes em T matam todos os mutantes em M.
Se todos os mutantes foram mortos, o conjunto T é adequado, e o
processo é encerrado. Senão, acrescenta-se um teste para cada
mutante M sobrevivente, até que o conjunto T seja adequado.

A grande vantagem no uso dessa técnica é que torna-se possível a


obtenção da cob ertura de falhas (ou erros), pois se consegue a partir de
um número conhecido de erros (operadores de mutação) avaliar quantos
desses erros foram descobertos em um código. Com esta técnica
consegue-se, ainda, qualificar os casos de teste, especialmente para o
uso no teste de regressão.
CAPÍTULO 5
AUTOMAÇÃO DO TESTE DE SOFTWARE
O teste tornou-se uma realidade na empresa de desenvolvimento de software e
já se criou um processo, no qual documentos, níveis de teste, tipos de teste e técnicas
foram institucionalizados e fazem parte do plano de teste do projeto. Agora é
necessário ganhar velocidade na aplicação e geração dos casos de teste, além de dar
apoio à organização e à comunicação durante a fase de teste. Para isso é preciso
automatizar o teste, tarefa para a qual existem inúmeras ferramentas que atendem a
um ou mais propósitos e que podem ser comerciais ou de uso livre. Este capítulo tem
como objetivo apresentar algumas características das ferramentas de automação do
teste de software.

Se considerarmos que o esforço aplicado na atividade de testes


corresponde, em média, a até 40% do esforço total (MYERS, 2004) e que
muitas das técnicas de teste podem ser descritas em forma de
programas, as ferramentas capazes de reduzir o tempo de teste, sem no
entanto reduzir sua eficiência, são muito importantes.
A automação do teste de software nasce como uma necessidade
das empresas desenvolvedoras de aumentar a qualidade de suas
soluções. Ela pode desempenhar um papel importante em várias técnicas,
níveis e tipos de teste. Em alguns casos, ela será menos sofisticada,
simplesmente oferecendo suporte para a condução de testes manuais.
A automação do processo de teste pretende reduzir problemas
comuns de desempenho, descobrir falhas, evitar entraves com o aumento
da escalabilidade e reduzir ao máximo as brechas de segurança.
Miller (1979) e Dunn (1984) descrevem uma série de categoria de
ferramentas de teste que vem sendo desenvolvida por pesquisadores
profissionais, que pode ser observada resumidamente a seguir
(PRESSMAN, 2011):

Analisadores estáticos: Esses sistemas de análise de programa


suportam a “comprovação” de informações estáticas – afirmações
fracas sobre a estrutura e o formato de um programa.
Auditores de código: Esses filtros de propósito especial são
usados para verificar a qualidade do software, a fim de garantir
que ele atenda a padrões mínimos de codificação.
Processadores de asserção: Esses sistemas pré-
processadores/pós-processadores são empregados para dizer
se as afirmações fornecidas pelo programador, denominadas
asserções, sobre o comportamento de um programa são de fato
cumpridas durante as execuções reais do programa.
Geradores de arquivos de teste: Esses processadores geram, e
preenchem com valores previamente determinados, arquivos de
entrada típicos para programas que estão em teste.
Geradores de dados de teste: Esses sistemas de análise
automatizados auxiliam o usuário a selecionar dados de teste que
fazem um programa comportar-se de uma forma particular.
Verificadores de teste: Essas ferramentas medem a cobertura
interna dos testes, frequentemente expressa em termos que
estão relacionados à estrutura de controle do objeto de teste, e
relatam o valor da cobertura ao especialista em garantia de
qualidade.
Comparadores de saída: Esta ferramenta torna possível a
comparação de um conjunto de saídas de um programa com
outro conjunto (previamente arquivado) para determinar a
diferença entre eles.
Sistemas de execução simbólica: Essa ferramenta realiza testes
de programas usando entrada algébrica, em vez de valores de
dados numéricos. O software que é testado parece, desse modo,
testar classes de dados, em vez de ser um caso de teste
específico. A saída é algébrica e pode ser comparada com os
resultados esperados que são especificados algebricamente.
Simuladores de ambiente: Essa ferramenta é um sistema
computadorizado especializado que possibilita que o analista
modele o ambiente externo do software de tempo real e depois
simule dinamicamente as condições operacionais reais.
Analisadores de fluxo de dados: essa ferramenta rastreia o fluxo
de dados mediante um sistema (semelhante em muitos aspectos
aos analisadores de caminho) e tenta descobrir referências a
dados, indexação incorreta e outros erros relacionados a dados.

O termo automatizar teste é utilizado para descrever o processo pelo


qual o software é avaliado, sem a intervenção humana e com o objetivo de
garantir a sua qualidade. Consiste em definir ao computador as atividades
de teste que seriam realizadas de forma manual (MUNIZ, 2012).
Para Fewster (1999), o processo de automação de testes significa
reduzir o esforço necessário em diversos tipos de testes, ou, também,
aumentar o número de testes executados em um determinado tempo.
Segundo Pressman (2011), o processo de automação de testes
vem sendo o fator principal na diminuição nos custos de testes e pela
produção de sistemas mais confiáveis. Portanto, as ferramentas de teste
automatizam atividades do processo de testes e são muitos úteis para os
testes de regressão.
O processo de teste, correção e reteste pode gerar uma situação de
desespero entre a equipe de teste e de desenvolvimento, especialmente
se houver um cronograma com datas agressivas e que não podem ser
renegociadas. Nessa situação, a automação pode ser uma boa alternativa.
Existem algumas técnicas utilizadas para automação, que são
empregadas na criação dos scripts (roteiros) de teste em algumas
ferramentas, em especial para criar casos de teste funcional, são elas:

Record & Playb ack: consiste em gravar as ações efetuadas por


um usuário sobre a interface gráfica dos sistemas, transformando
essas ações em scripts que podem ser executados quando e
quantas vezes for necessário. Os dados de entrada e resultados
da execução são gravados junto com o script, para que sejam
utilizados na comparação com o estado atual do sistema quando
da nova execução dos testes.
Programação de Scripts: bastante semelhante à técnica Record &
Playb ack, consiste em customizar os scripts gravados para que
tenham comportamentos diferentes do original, podendo assim
contemplar uma maior quantidade e variedade de resultados
esperados. Possibilita criar novos testes sem a necessidade de
uma nova gravação, efetuando-se apenas alterações em pontos
isolados dos scripts.
Data-Driven: técnica mais avançada de programação de script.
Consiste em manter apenas os procedimentos e as ações de
teste no script, retirando deles os dados que serão utilizados e
mantendo em um arquivo separado, garantindo maior agilidade
na hora de escolher os testes a serem executados, visto que, para
tanto, é necessária apenas a manipulação dos arquivos de
dados.
Keyword-Driven: procedimentos que representam a lógica de
execução são retirados do script, que passam a conter apenas as
ações específicas de teste da aplicação identificadas por
palavras-chave.

As ferramentas, segundo Caetano (2007), são, normalmente,


agrupadas em oito áreas:
automação de testes de regressão;
gestão de defeitos;
testes de eerformance/estresse;
manuais;
rastreabilidade;
cobertura de código;
gestão de testes;
apoio a execução dos testes.

Segundo Oliveira (2007), existem no mercado vários tipos de


ferramentas para testes de softwares. O objetivo de todas elas é o mesmo:
garantir a qualidade do software detectando o maior número de erros
possível antes da entrega para o cliente. Essas ferramentas possuem
características diferentes apresentadas no Quadro 6.

Quadro 6 – Comparativo entre algumas ferramentas de teste de software


Ferramenta Tipo Foco Propósito Linguage
Junit Teste de Métodos das Verifica o Java
Unidade classes funcionamento
dos métodos
das classes
CBDUnit Teste de Automatizar Testa Java,
Unidade geração de componentes C++
casos de teste do código.
Jmeter Teste Desenvolvimento Simula fluxos
Funcional de aplicações de aplicações
Web Web ,
simulando
acessos
múltiplos
Xpediter Procedures e Detecta
Triggers em execuções
Banco de Dados incorretas
NuMega Componentes Faz diagnóstico Visual
das aplicações de erros e Basic, C+
problemas de Delphi
desempenho Java
QACenter Teste Aplicações Web Detecta
Funcional problemas e
erros em
páginas Web .
Na versão
mainframe
simula
múltiplos
usuários
Suíte TestStudio Estrutura de Configura e
gerenciamento compartilha o
de testes tempo entre as
fases,
considerando o
ciclo de vida do
projeto
Robot Processo de Gerenciamento: HTML,
teste cria, modifica e Java, Visu
automatiza os Basic, C+
processos de Delphi
teste
VisualTest Teste Sistemas Auxilia os
Funcional Operacionais testadores a
criar testes para
aplicações
Windows
Logest Teste Estrutura do Gera casos de Pascal
Estrutural Código teste, baseado
na análise
estrutural
Jtest Teste Classes Testa uma Java
Funcional, classe ou
Estrutural e conjunto de
Regressão classes,
previne que
erros sejam
inseridos no
código
WebTestTools Teste Aplicações Web Simula carga
Funcional em servidores
Web , valida
HTML e verifica
link
SilkPerformance Teste de Servidores .NET, Simula acesso Java e .N
Unidade e Web Services e simultâneo de
Componentes EJBs usuários
Nocaute Teste de Aplicações Java Testa códigos Java
Unidade dentro ou fora
de um servidor
Web
PureCoverage Áreas Apresenta C++ e Ja
exercitadas ou opções que
não do código auxiliam o
testador a
identificar as
áreas do código
que foram ou
não testadas
C++Test Teste de Classes Testa classes C, C++
Unidade, imediatamente
Funcional, escritas usando
Estrutural e drivers e stub s
Regressão
Fonte: adaptado de Oliveira (2007).

Como é possível identificar no Quadro 6, existem atualmente


diferentes ferramentas para a etapa de testes de software. Ferramentas
distintas quanto ao tipo de teste, ao foco e ao propósito para que foram
desenvolvidas, sendo assim, cada organização deve realizar uma
avaliação e optar por aquela que se encaixa da melhor forma a sua
necessidade.
REFERÊNCIAS

ABES – Associação Brasileira das Empresas de Software. Mercado


Brasileiro de Software: Panorama e Tendências. São Paulo: ABES, 2012.

AMARAL, D. et al. Metodologias de Teste de Software. Revista de


Informática Aplicada, v. 5, n.2, Porto Alegre, 2009.

ASSOCIAÇÃO BRASILEIRA DE NORMAS TÉCNICAS. NBR ISO/IEC 9126-1:


Engenharia de Software – Qualidade de produto Parte 1: Modelo de
qualidade. Rio de Janeiro, 2003.

BASTOS, A. et al. Base de conhecimento em teste de software. 3ª ed. São


Paulo: Martins Editora, 2007.

BOEHM, B. Software Engineering Economics. New Jersey: Prentice-Hall.


1981.

BRUNELLI, M. V. Q. A Utilização de uma Metodologia de Teste no Processo


de Melhoria da Qualidade do Software. Dissertação (Mestrado em Ciência
da Computação), Unicamp, Campinas, 2006.

BSTQB. Glossário Padrão de Termos Utilizados em Teste de Software,


2011. Disponível em: <http://www.bstqb.org.br>. Acesso em: 16 jul. 2012.

CAETANO, C. Automação e Gerenciamento de Testes: Aumentando a


Produtividade com as Principais Soluções Open Source e Gratuitas, 2007.
Disponível em:
<http://www.digitalworks.eti.br/DigitalWorks/Upload/Curso/automa_teste.pdf
Acesso em abril de 2013 .

CHATTERJEE, I. Testing Tesb alility, 2004. Disponível em:


<http://www.stickminds.com/sitewide.asp?
Function=edetail&ObjectType=ART&Objectid=8077>. Acesso em: 05 abr.
2013.

COPELAND, L. A Practitioner´s Guide to Software Test Design. London:


Artech House Publishers, 2004.

CRESPO, A. N. et al. Uma Metodologia para Testes de Software no Contexto


da Melhoria do Processo. São Paulo: [s.n.], 2003, 16p.
DELAMARO, M.E.; MALDONADO, J.C> e JINO, M. Introdução ao Teste de
Software. Rio de Janeiro: Campus, 2007.

DEUTSCH, M. Verification and Validation. In: PRESSMAN, Roger.


Engenharia de Software. São Paulo: Makron Books, 1995. p. 780-781.

DEMILLO, R. A. et al. Hints on Test Data Selection: Help for the Practicing
Programmer. IEEE Computer, vol. 11(4p. 34-41) Georgia Institute of
Technology, abr. 1978.

DUNN, R. Software Defect Removal. New York: McGraw-Hill, 1984.

ENGHOLM JR, Hélio. Engenharia de Software, na prática. 1ª ed. São Paulo:


Novatec, 2010.

FEWSTER, M.; GRAHAM, D. Software Test Automation. Massachussets:


Addison-Wesley Professional: 1st. Edition, 1999.

FILHO, T. R. M.; RIOS, E. Teste de Software. Rio de Janeiro: Alta Books,


2003.

FRASSI, D. Formas de integração entre os processos de desenvolvimento e


de teste. Disponível em:
<http://deborafrassi.blogspot.com.br/2010/09/introducao-ao-processo-de-
teste.html>. Acesso em: 27 abr. 2013.

GALITEZI, T. Regra 10 de Myers. Disponível em:


<http://www.galitezi.com.br/2012/02/teste-de-software-e-o-custo-da-
nao.html>. Acesso em: 04 mai. 2012.

GUERRA, A. C.; COLOMBO, R. M. T. Tecnologia da Informação: Qualidade


de Produto de Software. Brasília: PBQP Software, 2009.

HETZEL, William. Guia completo ao teste de software. Rio de Janeiro:


Campus, 1987. 206p.

HOWDEN, W. E. Functional Program Testing and Analysis, McGraw_Hill,


New York, 1987.

IBM Systems Sciences Institute. Implementing Software Inspections. New


York: IBM Corporation, 1981.

IEEE. Standard for Software and System Test Documentation 829-2008.


Disponível em: <http://ieeexplore.ieee.org/xpl/articleDetails.jsp?reload-
true&arnumber=5983353>. Acesso em: 15 mar. 2013.

JACOBSON, I. et al. Ob ject-Oriented Software Engineering: A use Case


Driven Approach. Massachussets: Addison Wesley Reading, 1992.

KOSCIANSKI, André; SOARES, Michel dos Santos. Qualidade de Software –


Aprenda as metodologias e técnicas mais modernas para o
desenvolvimento de software. 2ª ed. São Paulo: Novatec, 2007. Disponível
em:
<http://www.martinsfontespaulista.com.br/anexos/produtos/capitulos/241804.pdf
Acesso em: 27 abr. 2013.

KRUG, Margrit Reni. Teste de Software. 1ª ed. São Leopoldo: Universidade


do Vale do Rio dos Sinos, 2007.

LOPES, Mateus Bruno Teixeira; CARNEIRO, Allan Guerreiro. A Importância


do Processo de Teste de Software em TI. Universidade Federal de Viçosa,
2011. Disponível em: <http://www.univicosa.com.br/artigo/a-importancia-do-
processor-de-teste-de-software-em-ti>. Acesso em: 27 abr. 2013.

MACHADO, M. C. C. Estudo e definição de mecanismos para redução do


custo de aplicações do teste de programas concorrentes. 2011. 94 f.
Dissertação (Mestrado em Ciências de Computação e Matemática
Computacional), Universidade de São Paulo, São Carlos, 2011. Disponível
em: <http://www.teses.usp.br/teses/disponiveis/55/55134/tde-01092011-
084548/pt-br.php>. Acesso em: 27 abr. 2013.

MATTINGLY, L. R.; RAO, H. Writing Effective Use Cases and Introducing


Collab oration Cases. Journal of Object Oriented Programming 11. EUA,
1998.

MACIEL, A.C.F, et al. Análise da Qualidade de Software Utilizando Normas


12207, 15504, ISO 9000-3 e Modelos CMM/CMMI e MPS.BR. Revista
Científica do ITPAC, v.4, 2011. Disponível em:
<http://www.itpac.br/hotsite/revista/artigos/44/5.pdf>. Acesso em: 25 maio
2013.

MALDONADO, J. C. Critérios Potenciais Usos: Uma Contribuição ao Teste


Estrutural de Software. Tese (Doutorado em Ciência da Computação),
UNICAMP. Campinas, 1991. 260 p.

McCABE, T. J. A Complexity Measure. IEEE Transactions on Software


Engineering, New York, vol. 2(4), pp. 308-320, Dec. 1976.

MILLER, E. Automated Tools for Software Engineering. New York: IEEE


Computer Society Press, 1979.

MOLINARI, L. Testes Funcionais de Software. Florianópolis, Santa Catarina:


Visual Books, 2011.

MORAES, R.O.; LAURINDO, F.J. B. Teste de Software e Qualidade de


Software: Uma Visão Geral, 1999. Disponível em:
<http://www.adepro.org/biblioteca/ENEGEP1999_A0198.Pdf>. Acesso em:
21 set. 2013.

MOSLEY, D. J. The Handb ook of MIS Application Software Testing.


Englewood Cliffs, New Jersey: Prentice-Hall. 1993. 340 p.

MUNIZ, L. F. C. Automação de Testes Funcionais no Contexto da Melhoria


da Qualidade do Produto de Software (Monografia de Especialização em
Qualidade de Software). São Leopoldo: Unisinos, 2012.

MYERS, Glenford J. The Art of Software Testing. 2ª ed. Hoboken: John Wiley
& Sons, Inc., 2004.

NASCIMENTO, T. Alexandre. Avaliação da Qualidade de um Produto de


Software. Recife – PE, 2010. Disponível em: <www.cin.ufpe.br/~tg/2010-
1/tan2.docx>. Acesso em Abr de 2014.

NETO, Arilo Cláudio Dias. Introdução a Teste de Software. Engenharia de


Software Magazine, Curitiba, v. 1, n. 1, p. 54-59, 2007. Disponível em:
<http://www.devmedia.com.br/artigo-engenharia-de-software-introducao-a-
teste-de-software/8035>. Acesso em: 30 abr. 2013.

NITA, Erika de Freitas. Melhoria da Qualidade de Produto e de Processo de


Software a partir da Análise de Indicadores de Teste. In: I Simpósio
Brasileiro De Qualidade De Software, 2002, Gramado. Anais eletrônicos.
Gramado, 2002. Disponível em:
<http://www.lbd.dcc.ufmg.br/bdbcomp/servlet/Trabalho?id=5423>. Acesso
em: 06 maio 2013.

OLIVEIRA, P. L. Fatus – Ferramenta para Automatizar Testes de Unidade de


software. Porto Alegre: Uniritter, 2007.

PAULA FILHO, Wilson de Pádua. Alguns Fundamentos da Engenharia de


Software. Engenharia de Software Magazine, Curitiba, v. 1, n. 1, p. 54-59,
2007. Disponível em: <http://www.devmedia.com.br/artigo-engenharia-de-
software-alguns-fundamentos-da-engenharia-de-software/8029>. Acesso
em: 09 mai 2013.

PETERS, J. F. PEDRYCZ, W. Engenharia de Software, teoria e prática. 1ª ed.


Rio de Janeiro: Editora Campus, 2001.

PEZZÉ, M., YOUNG, M. Teste e Análise de Software: processos, princípios e


técnicas. Porto Alegre: Bookman, 2008. 512p.

PRESSMAN, Roger. Engenharia de Software. São Paulo: Makron Books,


2011.

RAPPS, S.; WEYUKER, E. Selecting Software Test Data Using Data Flow
Information. IEEE Transactions on Software Engineering, vol.11(4). Apr.
1985. Pp. 367-375.

RATZMANN, M.; YOUNG, C. Software Testing and Internationalization.


Publicado por: Lemonaide International, Inc. 2002. Disponível em:
http://ebookbrowse.com/galileo-computing-software-testing-pdf-
d87014917. Acesso em 11 set. 2012.

RIOS, E.; MOREIRA, T. Teste de software. 2ª ed. Rio de Janeiro: Alta Books,
2011.

RODRIGUES Fernando. Testes de Software – Níveis de testes. Disponível


em: <www.devmedia.com.br/testes-de-software-niveis-de-testes/22282>.
Acesso em: 20 dez. 2012.

SILVA, J. B. da. PROTESTE+: Ambiente de Validação Automática de


Qualidade de Software através de Técnicas de Teste e de Métricas de
Complexidade. Dissertação (Mestrado em Ciência da Computação),
CPGCC/UFRGS, Porto Alegre, 1995. 185 p.

SOFTEX. MPS.BR – Melhoria de Processo do Software Brasileiro, Guia


Geral. Sociedade Softex, 2011. Disponível em:
<http://www.softex.br/mpsbr/_guias/guias/MPS.BR_Guia_Geral_2011.pdf>.
Acesso em: 14 mai 2013

SOMMERVILLE, Ian. Engenharia de Software. 8ª ed. São Paulo: Addison


Wesley, 2009.
TANNOURI, P. A. O que é Testab ilidade? Disponível em
<http://www.linhadecodigo.com.br/artigo/923/0-que-e-testabilidade.aspx>.
Acesso em: 05 abr. 2013.

VICENTE, André Abel. Definição e gerenciamento de métricas de teste no


contexto de métodos ágeis. 2010. 136 f. Dissertação (Mestrado em
Ciências de Computação e Matemática Computacional), Universidade de
São Paulo, São Carlos, 2010. Disponível em
<http://www.teses.usp.br/teses/disponiveis/55/55134/tde-23062010-
083439/pt-br.php>. Acesso em: 13 maio 2013.

VINCENZI, A. M. R. et al. Critério Análise de Mutantes: Estado Atual e


Perspectivas. In: Workshop do Projeto Validação e Teste de Sistemas de
Operação. Águas de Lindóia, SP. Anais... Jan. 1997.

VINCENZI, A. M. R. et al. Componet-based Software: An Overview of Testing.


In. CECHICH, A. PIATTINI, M.; VALLECILLO, A., eds. Component-Based
Software Quality, Springer, 2003, pp 99-127 (Lecture Notes in Computer
Science, v. 2693).est Coverage and Adequacy. In: ACM Computing Surveys,
29(4) December, 366-427.
SOBRE A AUTORA

MARGRIT RENI KRUG


Doutora em Ciência da Computação com ênfase em Microeletrônica pela
UFRGS em 2007, onde teve com a tese Aumento da testab ilidade do
hardware com auxílio de técnicas de teste de software. Mestre em Ciência
da Computação, também pela UFRGS em 2000 e Bacharel em Informática
com ênfase em Análise de Sistemas pela UNISINOS em 1997. Atua como
consultora em teste de software em empresas de desenvolvimento de
software, em especial na elaboração do processo de teste e montagem de
equipes. Atualmente é professora e coordenadora de curso na UNISINOS
nas disciplinas de Processos de Teste de Software, Engenharia de Teste,
Processo de Software, entre outras.
UNIVERSIDADE DO VALE DO RIO DOS SINOS – UNISINOS

Reitor: Pe. Marcelo Fernandes de Aquino, SJ


Vice-reitor: Pe. José Ivo Follmann, SJ
Diretor da Editora Unisinos: Pe. Pedro Gilberto Gomes

Editora Unisinos
Avenida Unisinos, 950, 93022-000, São Leopoldo, Rio Grande do Sul,
Brasil
editora@unisinos.br
www.edunisinos.com.br

© dos autores, 2015


2015 Direitos de publicação da versão eletrônica (em e-book) deste livro
exclusivos da Editora Unisinos.

K94p Krug, Margrit Reni


Processos de teste de software [recurso eletrônico] /
Margrit Reni Krug – São Leopoldo : Ed. UNISINOS, 2015.
1 recurso online – (EaD)

ISBN 978-85-7431-705-2

1. Software - Testes. I. Título. II. Série.

CDD 005.30287
CDU 004.415.53
Dados Internacionais de Catalogação na Publicação (CIP)
(Bibliotecária Mariana Dornelles Vargas – CRB 10/2145)

Coleção EAD
Editor: Carlos Alberto Gianotti
Acompanhamento editorial: Jaqueline Fagundes Freitas
Revisão: Patrícia Coelho
Editoração: Guilherme Hockmüller

A reprodução, ainda que parcial, por qualquer meio, das páginas que
compõem este livro, para uso não individual, mesmo para fins didáticos,
sem autorização escrita do editor, é ilícita e constitui uma contrafação
danosa à cultura. Foi feito depósito legal.

Potrebbero piacerti anche