testes de sistema

18
UNIVERSIDADE LUTERANA DO BRASIL CENTRO DE CIÊNCIAS EXATAS E NATURAIS CURSO DE SISTEMAS DE INFORMAÇÃO TESTES DE SISTEMA MAURICIO VOLKWEIS ASTIAZARA IGOR CASA NOVA DOS SANTOS Engenharia de Software I

Upload: mauricio-volkweis-astiazara

Post on 11-Jun-2015

1.989 views

Category:

Technology


0 download

DESCRIPTION

Baixe mais arquivos em http://pastadomau.wikidot.com. Este trabalho tem como objetivo mostrar a importância dos testes no desenvolvimento estruturado de software, passando pelas fases desta etapa e os tipos de teste utilizados em cada fase. Aborda também os métodos para uma correta aplicação dos testes de forma eficiente, visando a produção de um sistema com qualidade.

TRANSCRIPT

Page 1: Testes de Sistema

UNIVERSIDADE LUTERANA DO BRASIL

CENTRO DE CIÊNCIAS EXATAS E NATURAIS

CURSO DE SISTEMAS DE INFORMAÇÃO

TESTES DE SISTEMA

MAURICIO VOLKWEIS ASTIAZARA

IGOR CASA NOVA DOS SANTOS

Engenharia de Software I

Torres, Junho de 2001

Page 2: Testes de Sistema

Introdução

Este trabalho tem como objetivo mostrar a importância dos testes no desenvolvimento

estruturado de software, passando pelas fases desta etapa e os tipos de teste utilizados em cada

fase. Aborda também os métodos para uma correta aplicação dos testes de forma eficiente,

visando a produção de um sistema com qualidade.

Page 3: Testes de Sistema

Testes

1 Objetivo

O propósito dos testes é evitar “surpresas desagradáveis” depois que o sistema entra em funcionamento. O propósito da análise estruturada é evitar surpresas desagradáveis nos testes. Os dois estão intimamente relacionados.

2 Tipos de Teste

Durante as quatro fases de teste de um projeto são aplicados testes que podem ser classificados em duas categorias: Testes Estruturais e Testes Funcionais. Antes de entrarmos nas fases do teste veremos como são caracterizados estes dois tipos de teste.

2.1 Testes Estruturais

São também chamados de testes de Caixa Branca. Preocupam-se em verificar como as funções são implementadas. Assim além de detectarem o erro, podem ajudar de modo significativo na sua correção. São constituídos de atividades de verificação que normalmente incluem a análise da especificação do projeto, do código do programa e do fluxo de dados. Esse tipo de análise é classificada como estática, pois o programa não ou módulo não necessita necessariamente estar em execução para que ela sejam efetuadas.

Os testes estruturais procuram analisar como as funções são implementadas

Os testes estruturais podem ajudar a descobrir funções ausentes no programa, erro nas expressões aritméticas, declaração de tipos necessária, diferenças entre áreas de dados compartilhadas, erro nas interfaces de módulos (parâmetros) e não cumprimento de padrões.

Exemplos de técnicas aplicadas no testes estruturados: Análise da estrutura de controle; Técnicas baseadas em lógica matemática; Inspeções; Testes de mesa; Programas verificadores de estrutura; Teste baseado na cobertura: é aquele em cada comando do módulo é executado ao menos

uma vez; Teste baseado na cobertura de desvios: testa cada decisão e segue todos os desvios da

decisão; Teste da cobertura dos caminhos DD: um caminho DD é a seqüência de comandos que se

inicia no resultado de uma decisão e termina na próxima decisão; Teste baseado na complexidade: procura orientar o esforço do teste para as partes mais

complexas do código, onde é mais provável a existência de erros. Para métrica da complexidade utiliza-se uma das diversas técnicas existentes como a métrica de Halstead,

Page 4: Testes de Sistema

número ciclomático de complexidade de McCabe e a complexidade da variável de controle de McClure.

2.2 Testes Funcionais

São também chamados de testes Caixa Preta. Preocupam-se em testar se as funções realizam as tarefas corretamente independente do modo como o façam (só interessa se as respostas estão corretas ou não). Estes testes são executados depois do teste de estrutura e tem como objetivo validar o que foi feito na etapa anterior, aprovando ou não. Os testes funcionais são realizados com o programa ou módulo em execução, por isso é chamado de análise dinâmica.

O processo de um teste funcional envolve os seguintes passos:1 Selecionar um conjunto de dados de entrada com os quais se executará o programa;2 Determinar a saída que se espera ser produzida;3 Executar o programa;4 Comparar os resultados produzidos pelo programa com o que era esperado.

Passos para a realização de um teste funcional.

Diferentes aspectos da funcionalidade do programa devem ser testados nesta fase e para cada um deles existe uma metodologia para a produção de dados de teste (primeiro passo, acima). Por isso os testes funcionais se dividem nas seguintes etapas:1 Teste de Via Normal (ou Caminho Normal)2 Teste de Via de Erro (ou Caminho de Exceção)3 Teste de Estado Transiente4 Teste de Desempenho (ou Performance)5 Testes Especiais

2.2.1 Teste de Via Normal

Este teste é derivado do Dicionário de Dados. Consiste em gerar um grupo de entradas válidas para verificar se o sistema executa o que foi exigido na especificação estruturada.

Casos de teste devem ser derivados para cada item no dicionário de dados e para cada fluxo de dados composto seguindo o que foi especificado no dicionário de dados. Gerar todas as possibilidades de dados para cada item é impossível, ao invés disso devemos concentrar os testes nas chamadas situações limite, que pode ocasionar a maior parte dos erros. Pode-se ainda acrescentar um valor intermediário, com a objetivo de abranger todas as faixas de valores (inferior, médio e superior). Em geral as situações limite devem ser testadas nos seguintes aspectos:

Limites de Entrada: limites superiores, inferiores e outros associados com as entradas do sistema. A finalidade destes testes é verificar se o sistema aceitará entradas dentro dos limites da especificação. Por exemplo: se a especificação indica

Page 5: Testes de Sistema

que uma entrada do sistema deve ser uma string de 1 a 40 caracteres devemos testar se o sistema funcionará com strings de 1, 20, 39 e 40 caracteres.

Limites de Saída: limites superiores, inferiores e outros associados com as saídas do sistema. Por exemplo: se um sistema de folha de pagamento que supostamente deve ser capaz de produzir contracheques de seis dígitos, obviamente é uma boa idéia construir-se casos de teste que produzam este tipo de contracheque.

Limites Funcionais: para assegurar que as funções descritas na especificação do processo sejam executadas corretamente em situações limite. Por exemplo, um módulo OrdenaTab que ordena uma tabela de itens. Os limites funcionais seriam testados utilizando-se uma tabela vazia, uma tabela com somente um item, uma com itens já ordenados, uma com itens iguais e outra com o limite máximo de itens (se houver).

Uma vez definidos os conjuntos de valores válidos para cada item do dicionário de dados, eles devem ser combinados gerando uma gama de valores de entrada para o teste de via normal. Isso poderia ser feito utilizando-se um banco de dados com os conjuntos escolhidos e aplicando-se a operação de produto cartesiano sobre eles. Em alguns casos o tamanho deste banco de dados pode tornar-se um transtorno, não sendo viável realizar o teste com todos os valores obtidos ou até mesmo não sendo possível completar o banco de dados. Mesmo nesses casos a equipe deve estar ciente que o sistema deve ser capaz de manipular qualquer uma dessas entradas.

Tomemos agora um exemplo prático de teste de via normal para entrada a partir de um dicionário de dados simples, que segue a seguinte notação:

Símbolo Significado= É composto de + E<min>{ }<max> Iteração (mínimo, tipo de dado, máximo)<valor1> – <valor2> Intervalo de valores[<valor1>|<valor2>|<valorN>] Escolha Múltipla

Dicionário Exemplo:

Cod_quarto = 1 – 1000Status = [ “vago” | “ocupado” ]

A partir do que está especificado neste dicionário podemos derivar os seguintes conjuntos de dados válidos:

Cod_quarto =(1, 500, 1000)Status = (“vago”; “ocupado”)

Combinando-se os valores obtemos as seguintes entradas válidas:

Cod_quarto Status1 “vago”500 “vago”1000 “vago”1 “ocupado”

Page 6: Testes de Sistema

500 “ocupado”1000 “ocupado”

2.2.2 Testes de Via de Erro

Semelhante ao de via normal, porém entra com dados inválidos no sistema para avaliar seus tratamentos de erros, que deve ser recusá-los, evitando a produção de saídas inválidas ou até mesmo o travamento do sistema.

Esses dados inválidos são geralmente de dois tipos:1 Casos que infrinjam os limites de entrada (citados nos testes de via normal) como por

exemplo, para uma entrada de valor numérico que deve ser um valor de 1 a 10, um conjunto de dados inválidos para teste poderia ser –1,0,11,15.

2 Valores incompatíveis com o tipo de dado esperado, como por exemplo, para a mesma entrada numérica acima o conjunto de dados poderia ser 1A, w, #?, (vazio).

Cada conjunto de dados inválidos substituirá o seu respectivo conjunto de valores normais de cada vez, que foram usados no teste anterior (via normal). Efetua-se a combinação (produto cartesiano) nesse novo arranjo de conjuntos obtendo-se um conjunto de entradas inválidas, que contém um único erro (que está no item que teve seu conjunto normal substituído pelo inválido). Somente um conjunto de dados inválidos será combinado com o de vias normais de cada vez, produzindo um único erro por entrada. Não se deve produzir entradas com combinações de erros ou entradas com um dado com múltiplos erros.

Seguindo o mesmo dicionário do exemplo anterior, podemos estabelecer os seguintes conjuntos de dados inválidos:

Cod_quarto = (0, 1001, “M#”)Status = (“vag1”, 2)

Iniciamos a substituição pelo do primeiro item de dado (Cod_quarto) e efetuamos a combinação com os dados válidos. Assim se seguirá com o resto dos conjuntos.

Cod_quarto Status0 “vago”1001 “vago”“M#” “vago”0 “ocupado”1001 “ocupado”“M#” “ocupado”

2.2.3 Teste de Estado Transiente

Os testes derivados até agora seriam suficientes para testar um sistema que não tivesse nenhuma memória, que tratasse cada entrada de modo independente do que tivesse acontecido antes. Porém para sistemas com vários estados transientes será necessário agrupar os testes em seqüências. A seqüência de testes pode ser organizada para forçar o sistema em cada um dos estados possíveis e testar o seu desempenho nesse estado. Para derivar um conjunto completo de seqüências de teste deve-se listar os estados em memória para cada fluxo de dados de entrada e realizar uma seqüência de teste para cada estado.

Page 7: Testes de Sistema

2.2.4 Teste de Desempenho

Visa verificar se os requisitos de tempo e volume especificados na análise foram realmente atendidos. Este tipo de teste é essencial para grandes sistemas em-linha, mas pode ser desnecessário para pequenos sistemas em lote ou para qualquer tipo de sistema em que o hardware seja uma pequena parte do custo geral do sistema, e que seja facilmente expansível (por exemplo adicionando mais memória ou atualizando o processador).

Na maioria dos casos de teste de desempenho preocupa-se com o rendimento, tempo de resposta e capacidade de banco de dados. Pode não ser prático ou mesmo possível criar entradas reais suficientes e carga suficiente no novo sistema para verificar se o seu desempenho é satisfatório, porém pode-se utilizar uma série de técnicas de simulação.

Pode-se enganar o sistema em operação como se ele tivesse um pesado volume reduzindo o hardware disponível. Por exemplo rodar o sistema em máquina com somente 8MB de memória ao invés de 64MB.

Outra maneira é a partir de um pequeno volume de dados efetuar centenas de cópias ou até milhares para se obter o volume necessário.

Naturalmente essas simulações são subterfúgios não garantem a geração de resultados perfeitos.

2.2.5 Teste Especiais

Seria ingenuidade pensar que qualquer sistema, independente de sua complexidade, poderia ser completamente testado na sua funcionalidade pelos testes descritos anteriormente que são derivados da especificação estruturada. Alguns precisam claramente de testes adicionais para lidarem com suas naturezas particulares. Já que estes testes não podem ser derivados da especificação estruturada eles devem ser colocados explicitamente na especificação estruturada antes que ela seja considerada completa. Isto manterá o conceito de que todos os testes têm como base a especificação estruturada.

3 Fases do teste

A abordagem estruturada teve grande influência na etapa de teste, assim como nas outras fases de desenvolvimento de software. O teste tem sido formalizado como um procedimento de quatro fases como descrito abaixo.

3.1 Teste de Unidade

O teste de unidade consiste em se aplicar o teste estruturado e o teste funcional para cada função, sub-rotina ou módulo. O teste de unidade normalmente é realizado pelo programador como parte da etapa de codificação.

O teste de unidade sozinho não garante que ao unirmos os módulos testados teremos um sistema funcionando com sucesso, mas garante que módulo testado chegue a fase de integração cumprindo o seu objetivo lógico, a sua função.

Page 8: Testes de Sistema

No teste de Unidade cada módulo é testado individualmente quanto a estrutura e funcionalidade

3.2 Teste de Integração

O teste de integração consiste em se aplicar o teste estruturado e o teste funcional sobre uma hierarquia de módulos, como um subsistema ou o sistema completo. O objetivo do teste de integração é verificar se cada módulo funciona corretamente dentro da estrutura de controle e checar se as interfaces dos módulos (a comunicação entre eles) estão corretas.

Nos teste de integração é checada a comunicação (dados, controles) entre módulos.

O teste de integração tem diferentes abordagens: bottom-up, a top-down, e a middle-out são as básicas, mas existem outras variações. A seguir veremos mais detalhadamente cada uma delas.

3.2.1 Bottom-up

O nome desta estratégia significa do fundo para cima e segue este princípio na integração dos módulos, iniciando pelos módulos de nível mais baixo de forma ascendente até chegar aos níveis mais alto.

Direção da integração na abordagem Bottom-up

Esta estratégia de integração requer a construção de acionadores, que é um módulo temporário responsável pelo teste. O acionador chamará o módulo que esta sendo testado passando-lhe como parâmetro os dados do teste e recebendo o que o módulo retorna (se o módulo testado precisa de parâmetros ou retorna valores).

A estratégia Bottom-up tem apresentado vários problemas à fase de integração: acionadores podem exigir grande esforço pra serem desenvolvidos de modo a

simularem de modo fiel o sistema, além disso podem ser uma fonte adicional de erros; as funções de alto nível do programa são testados por último, retardando a descoberta

de erros que podem ser cruciais; erros de interface podem aparecer muito tarde, aumento de forma proporcional a

dificuldade de correção.

3.2.2 Top-down

Page 9: Testes de Sistema

Na estratégia top-down (do topo para baixo) os módulos de alto nível são integrados e testados em primeiro lugar. Desse modo o teste segue de modo descendente na estrutura hierárquica. O teste top-down requer a criação de módulos temporários chamados stubs. O módulo stub representa o módulo de nível logo abaixo do módulo que está sendo testado. A medida que o teste continua e se desce na estrutura, cada stub é substituído pelo módulo real e novos stubs para esse módulo são criados.

Direção da integração na abordagem Top-down

Os módulos stubs podem ser de diversos tipos, cada tipo pode auxiliar de modo diferente no teste do sistema: Não executar nada. Não é muito útil mas fácil de implementar; Exibir uma mensagem indicando que foi chamado. Útil para verificação do fluxo de

controle do sistema; Exibir um terminal, permitindo que o responsável pelo teste passe dados e tempo de

execução para o módulo superior; Retornar um valor constante, um número aleatório ou um número de uma tabela de teste. Ser uma versão simplificada do módulo real; Testar ou exibir os dados com os quais foi chamado; Aguardar certo tempo. Esse tipo de stub é útil em sistemas de tempo real ou sistemas

operacionais nos quais é preciso assegurar-se de que o sistema funcionará corretamente com um módulo que consumirá, por exemplo, 19 milésimos de segundo. Também pode ser utilizado para simular o acesso a um hardware que demorou tantos milésimos de segundo para estar pronto.

Substituição dos stubs pelos módulos a medida que segue o teste.

A estratégia top-down oferece importantes vantagens sobre a bottom-up: As funções de alto nível são testadas em primeiro lugar; O teste de integração pode começar mais cedo porque os módulos de alto nível podem ser

codificados em primeiro lugar e podem ser testados com stubs; Os stubs são mais fáceis de serem construídos que os acionadores.

Page 10: Testes de Sistema

Problemas com a abordagem top-down: Importantes funções de alto nível são testadas bem tarde no processo de desenvolvimento.

Problemas nessas funções podem forçar a um tardio reprojeto de funções de alto nível; Às vezes pode ser difícil construir os stubs simulando efetivamente o modo real.

3.2.3 Middle-out

Em pequenos programas, faz pouca diferença qual abordagem de integração é usada. Neste caso, teste de unidade e teste e integração são freqüentemente combinados em uma etapa. Em grandes projetos porém, prefere-se mais formalidade na separação das etapas de teste. Prefere-se, também uma abordagem que combine as técnicas top-down e middle-out a fim de minimizar seus problemas e aproveitar melhor suas vantagens. Middle-out significa do meio para fora, neste caso o meio não significa exatamente a metade da estrutura, mas sim a parte principal do projeto, que pode estar localizada em qualquer região.

Abordagem Middle-out: partindo do módulo principal.Inicia-se a integração a partir dessa parte crucial e pode-se seguir tanto para cima ou

para baixo, de acordo com a importância dos módulos. Dessa maneira têm-se a garantia de erros em partes importantes sejam descobertas tardiamente, forçando a uma reprojeção dos outros módulos.

Esta estratégia tem sido a que produz os melhores resultados, sendo a adotada pela maior parte dos desenvolvedores. Existem variações sobre esta estratégia sobre como percorrer a estrutura.

3.3 Teste de Sistema

É executado após o teste de integração e é basicamente um teste funcional aplicado sobre a estrutura já integrada na fase anterior. O objetivo é descobrir implementações incorretas ou falta de implementação das especificações dos requisitos e corrigi-las. As partes mais importantes do sistema e mais freqüentemente usadas devem ser testadas mais exaustivamente.

3.4 Teste de Aceitação

A fases anteriores de teste serviam para detectar erros afim de corrigi-los. Mas no teste de aceitação não é mais uma etapa de correção. O teste de aceitação é a mais pura forma de teste funcional, determinando se o projeto atingiu seu alvo ou não, pois o teste de aceitação é o que foi exigido na especificação (requisitos do usuário) estruturada produzida pela atividade de análise .

Análise Especificação Estruturada Geração do Teste de Aceitação

Page 11: Testes de Sistema

O teste de aceitação é efetuado elaborando-se um plano de teste e aplicando-se o teste funcional, visto em tipos de teste, no programa, como visto abaixo:

1 Elaborar Plano de Teste2 Aplicar Teste Funcional

2.1 Teste de Via Normal (ou Caminho Normal)2.2 Teste de Via de Erro (ou Caminho de Exceção)2.3 Teste de Estado Transiente2.4 Teste de Desempenho (ou Performance)2.4 Testes Especiais

3.4.1 Elaborar Plano de Teste

É o passo mais importante, pois uma vez desenvolvido é usado por todas as atividades subseqüentes. O plano de teste deve cobrir o estabelecimento do pessoal para testar o sistema, um esboço das normas de teste e um relatório de tempo estimado e recursos necessários a atividade de teste.

O objetivo inicial do plano deve ser a definição de uma pessoa ou grupo de pessoas responsável por testar o sistema. Esta pessoa (ou grupo) deve ser alguém diferente das pessoas que desenvolveram os sistema. Na verdade quanto mais afastada do projeto a pessoa responsável, mais objetivo e profundo será o procedimento do teste. Pode-se até mesmo contratar uma organização externa (como uma firma de consultoria de software) para realizar o teste. De qualquer forma, o teste deve ser feito por alguém que entenda que o processo possui a finalidade expressa de encontrar erros e revelar falhas do sistema.

Precisam ser desenvolvidos procedimentos e padrões para a construção de casos de teste, documentação de resultados, convenção de nomeação, armazenamento e recuperação para grupos (ou arquivos) de dados de teste.

3.4.2 Aplicar Teste Funcional

O teste funcional é aquele visto na parte de Tipos de Teste, que agora deve ser aplicado de modo global no programa de modo a validá-lo, resultando na sua aprovação ou reprovação.

Page 12: Testes de Sistema

Conclusão

Durante a realização deste trabalho concluímos que a análise estruturada possibilita o

desenvolvimento de software de qualidade, mas a etapa de teste é a que fornece maior retorno

ao desenvolvedor, tanto em relação ao atendimento dos requisitos do usuário quanto ao

progresso do projeto. Devendo portanto, receber a mesma dedicação e provimento de recursos

que as outras etapas da análise estruturada.

Page 13: Testes de Sistema

Bibliografia

1. YOURDON, Edward. Administrando o Ciclo de Vida do Sistema. Rio de Janeiro: Campus, 1989.

2. PAGE-JONES, Meilir. Projeto Estruturado de Sistemas. São Paulo: McGraw-Hill, 1988.

3. MARTIN, James; MC CLURE, Carma. Técnicas Estruturadas e Case. São Paulo: Makron, 1991.