Aula 11: Análise Dinâmica - 2a. parte



Documentos relacionados
Processos de Desenvolvimento de Software

Como melhorar a Qualidade de Software através s de testes e nua. Cláudio Antônio de Araújo 22/11/2008

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

Como Processos Criam Valor?

Orientação a Objetos

a 1 x a n x n = b,

PROCESSO DE DESENVOLVIMENTO DE SOFTWARE. Modelos de Processo de Desenvolvimento de Software

Importância da normalização para as Micro e Pequenas Empresas 1. Normas só são importantes para as grandes empresas...

a) Teste das funções do sistema com outros sistemas b) Teste de componentes que em conjunto compõem a função do sistema

Podemos encontrar uma figura interessante no PMBOK (Capítulo 7) sobre a necessidade de organizarmos o fluxo de caixa em um projeto.

PONTIFÍCIA UNIVERSIDADE CATÓLICA DE GOIÁS Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br

GARANTIA DA QUALIDADE DE SOFTWARE

Aula 4 Estatística Conceitos básicos

Disciplina: Unidade III: Prof.: Período:

Guia de utilização da notação BPMN

Tecnologia em Gestão Pública Desenvolvimento de Projetos - Aula 9 Prof. Rafael Roesler

MÓDULO 6 INTRODUÇÃO À PROBABILIDADE

FATEC Cruzeiro José da Silva. Ferramenta CRM como estratégia de negócios

ENGENHARIA DE SOFTWARE I

Diagrama de transição de Estados (DTE)

1.6. Tratamento de Exceções

Batalha Naval Algoritmos de Busca. Correlações curriculares Matemática: Números: maior que, menor que, iguais a.

Exercícios Teóricos Resolvidos

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

Casos de teste semânticos. Casos de teste valorados. Determinar resultados esperados. Gerar script de teste automatizado.

3 Qualidade de Software

Módulo 4. Construindo uma solução OLAP

Feature-Driven Development

Prof. Antonio Fundamentos de Sistemas Operacionais UNIP/2015

Capítulo 2. Processos de Software Pearson Prentice Hall. Todos os direitos reservados. slide 1

Engenharia de Software e Gerência de Projetos Prof. Esp. André Luís Belini Bacharel em Sistemas de Informações MBA em Gestão Estratégica de Negócios

Governança de TI. ITIL v.2&3. parte 1

Módulo 15 Resumo. Módulo I Cultura da Informação

MEDIDA E ANÁLISE DE DESEMPENHO AULA 14 Arquitetura de Computadores Gil Eduardo de Andrade

Inventario de produtos

Visite o hotsite do livro:

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

BCC202 - Estrutura de Dados I

TÉCNICAS DE PROGRAMAÇÃO

Microsoft Access XP Módulo Um

Notas da Aula 17 - Fundamentos de Sistemas Operacionais

Unidade VI. Validação e Verificação de Software Teste de Software. Conteúdo. Técnicas de Teste. Estratégias de Teste

Conteúdo. Disciplina: INF Engenharia de Software. Monalessa Perini Barcellos

Introdução ao Aplicativo de Programação LEGO MINDSTORMS Education EV3

Cálculo utilizando variáveis do tipo DATA

Sistemas Operacionais

Um jogo de preencher casas

Estrutura de Dados Básica

Aula 05 Raciocínio Lógico p/ INSS - Técnico do Seguro Social - Com Videoaulas

ADM041 / EPR806 Sistemas de Informação

Engenharia de Software

Na medida em que se cria um produto, o sistema de software, que será usado e mantido, nos aproximamos da engenharia.

Coleções. Conceitos e Utilização Básica. c Professores de ALPRO I 05/2012. Faculdade de Informática PUCRS

Curso de Graduação em Administração. Administração da Produção e Operações I

Introdução a Java. Hélder Nunes

Capítulo 3. Avaliação de Desempenho. 3.1 Definição de Desempenho

Validando dados de páginas WEB

PROFESSOR: CRISTIANO MARIOTTI

Prof. Raul Sidnei Wazlawick UFSC-CTC-INE. Fonte: Análise e Projeto de Sistemas de Informação Orientados a Objetos, 2ª Edição, Elsevier, 2010.

Especificação do 3º Trabalho

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

O papel do CRM no sucesso comercial

Lógica de Programação

Q-Acadêmico. Módulo CIEE - Estágio. Revisão 01

Memórias Prof. Galvez Gonçalves

CENTRO DE CIÊNCIAS TECNOLÓGICAS CCT

MANUAL TISS Versão

ACOMPANHAMENTO GERENCIAL SANKHYA

1) MANUAL DO INTEGRADOR Este documento, destinado aos instaladores do sistema, com informações de configuração.

Teste de Software. Objetivos e Limites. Objetivos e Limites. Objetivos e Limites. Objetivos e Limites. Objetivos e Limites

Programação de Computadores - I. Profª Beatriz Profº Israel

OCOMON PRIMEIROS PASSOS

MINERAÇÃO DE DADOS APLICADA. Pedro Henrique Bragioni Las Casas

Capacidade = 512 x 300 x x 2 x 5 = ,72 GB

Esta dissertação apresentou duas abordagens para integração entre a linguagem Lua e o Common Language Runtime. O objetivo principal da integração foi

Seção 2/E Monitoramento, Avaliação e Aprendizagem

Implementando uma Classe e Criando Objetos a partir dela

Teste de Software. Ricardo Argenton Ramos Engenharia de Software I

Dadas a base e a altura de um triangulo, determinar sua área.

ANALISE COMBINATORIA Um pouco de probabilidade

Quais são as organizações envolvidas no SASSMAQ?

04/08/2012 MODELAGEM DE DADOS. PROF. RAFAEL DIAS RIBEIRO, MODELAGEM DE DADOS. Aula 2. Prof. Rafael Dias Ribeiro. M.Sc.

APOSTILA DE EXEMPLO. (Esta é só uma reprodução parcial do conteúdo)

A lógica de programação ajuda a facilitar o desenvolvimento dos futuros programas que você desenvolverá.

MRP II. Planejamento e Controle da Produção 3 professor Muris Lage Junior

Técnicas de Caixa Preta de Teste de Software

Algoritmos e Estrutura de Dados III. Árvores

Objetivos. Apresentar as superfícies regradas e superfícies de revolução. Analisar as propriedades que caracterizam as superfícies regradas e

Projeto da Disciplina Parte1: Estudo de Viabilidade. Um Estudo de Viabilidade

CAP. I ERROS EM CÁLCULO NUMÉRICO

Lição 1 - Criação de campos calculados em consultas

FACULDADE DE ENGENHARIA DE COMPUTAÇÃO. PROJETO FINAL I e II PLANO DE TRABALHO <NOME DO TRABALHO> <Nome do Aluno> <Nome do Orientador>

SERVIÇO DE ANÁLISE DE REDES DE TELECOMUNICAÇÕES APLICABILIDADE PARA CALL-CENTERS VISÃO DA EMPRESA

)HUUDPHQWDV &RPSXWDFLRQDLV SDUD 6LPXODomR

Memória Flash. PdP. Autor: Tiago Lone Nível: Básico Criação: 11/12/2005 Última versão: 18/12/2006. Pesquisa e Desenvolvimento de Produtos

Transcrição:

Aula 11: Análise Dinâmica - 2a. parte Nesta aula, continuaremos nossa discussão a respeito da análise dinâmica, focando na atividade de teste. Iremos dar uma breve olhada em algumas das noções básicas sobre as quais a atividade de teste está baseada, iremos analisar também as técnicas mais utilizadas na prática. No final, iremos reunir algumas diretrizes para lhe ajudar em seu próprio trabalho de testes. 11.1 Testando Os testes são muito mais efetivos, e menos dolorosos, se você utilizar uma abordagem sistemática. Antes de você começar, pense a respeito dos seguintes itens: quais propriedades você quer testar e para quê; quais módulos você quer testar, e em qual ordem você os irá testar; como você vai gerar casos de teste; como você irá checar os resultados; quando você vai saber que o trabalho está terminado. Para se decidir quais propriedades testar, e quais testes executar sobre estas propriedades, será necessário conhecimento a respeito do domínio do problema, visando compreender quais tipos de falhas serão consideradas as mais sérias, e será necessário também, conhecimento do programa, visando entender qual será a dificuldade em se detectar a variedade dos erros. A escolha dos módulos é direta. Você deve testar, especialmente, os módulos que são críticos, que são complexos, ou que foram escritos pelo pior dos seus programadores (ou por aquele que mais adora utilizar truquezinhos dentro do código). Ou, talvez, o módulo que foi escrito tarde da noite, ou em cima da data de lançamento... O diagrama de dependência modular ajuda a determinar a ordem. Se o seu módulo depende de um módulo que ainda não foi implementado, você precisará escrever um stub (o esqueleto de um módulo, que no máximo simula seu funcionamento) que irá fazer o papel do módulo que está faltando durante os testes. O stub fornece comportamento suficiente para os testes a serem realizados. Ele pode, por exemplo, procurar respostas em uma tabela ao invés de realizar a computação verdadeira. A checagem dos resultados pode ser difícil. Alguns programas - como o Foliotracker que você estará construindo nos exercícios 5 e 6 - nem mesmo possuem comportamento repetitivo. Para outros programas, os resultados são apenas a ponta do iceberg, e para se certificar que as coisas estão realmente funcionando, você terá que checar estruturas internas. Mais adiante, iremos discutir 118

questões sobre como gerar casos de teste e como saber quando o trabalho está completo. 11.2 Testes de Regressão É muito importante ser capaz de reexecutar seus testes quando você modificar seu código. Por esta razão, não é uma idéia muito boa realizar testes específicos que não podem ser repetidos. Pode parecer um trabalho árduo, mas em longo prazo, é muito menos trabalhoso construir um conjunto prático de testes, isto é, um suíte de testes que podem ser reexecutados a partir de um arquivo. Tais testes são conhecidos como testes de regressão. Uma abordagem de testes conhecida pelo nome de 'test first programming', e que é parte do novo tratado de desenvolvimento conhecido como 'extreme programming', encoraja a construção de testes de regressão antes mesmo de se escrever qualquer código da aplicação. JUnit, oframework de testes que você tem utilizado, foi projetado para a isto. A construção de testes de regressão para um sistema grande é um ótimo negócio. É possível que a execução dos scripts de testes leve até uma semana. Por conta disto, uma área de pesquisas de muito interesse atualmente é a que tenta descobrir quais testes de regressão podem ser omitidos. Se você souber quais casos de teste testam quais partes do código, você pode ser capaz de determinar que uma alteração local em uma parte do código não exige que todos os casos sejam reexecutados. 11.3 Normas Para se compreender como os testes são gerados e avaliados, podemos pensar de maneira abstrata a respeito do propósito e da natureza das atividades de teste. Suponha que temos um programa P que, espera-se, satisfaça a uma especificação S. Vamos assumir, por simplicidade, que P é uma função que transforma entradas de dados em saídas de dados, e S é uma função que recebe uma entrada de dados e uma saída de dados, retornando um tipo boolean. Nosso objetivo na realização dos testes é encontrar um caso de teste t tal que S (t, P(t)) é falso: ou seja, P produz um resultado para a entrada t quenãoépermitidopors. Iremos denominar t como um 'caso de teste falho', apesar de se tratar, na verdade, de um caso de teste de sucesso, pois nosso objetivo é encontrar erros! UmsuítedetestesT é um conjunto de casos de teste. Fazemos, então, a seguinte pergunta: quando um suíte pode ser considerado bom o suficiente? Ao invés de tentamos avaliar cada suíte de testes 119

de uma forma dependente da situação, podemos aplicar uma norma geral. Você pode pensar em uma norma como uma função: C: Suite, Program, Spec Boolean que recebe um suíte de testes, um programa, e uma especificação, retornando true ou false de acordo com o fato do suíte de testes ser bom o suficiente para avaliar o programa e a especificação fornecidos, o que deve ser feito de maneira sistemática. A maioria das normas não envolve, ambos, o programa e a especificação. Uma norma que envolve apenas o programa é denominada norma program-based (baseada em programa). Outros termos também são usados como 'whitebox', 'clearbox', 'glassbox', ou 'structural testing' para se descrever testes que utilizam as normas do tipo program-based. Uma norma que envolve apenas a especificação é denominada norma specification-based (baseada em especificação). O termo 'blackbox testing' é utilizado em associação com o termo specificationbased, para sugerir que os testes são julgados sem que se possa analisar a parte interna do programa. Você pode escutar também o termo 'functional testing'. 11.4 Subdomínios Normas práticas tendem a ter uma estrutura particular e propriedades. Por exemplo, elas podem aceitar um suíte de testes T, mas rejeitar um suíte de testes T' queéigualat, possuindo apenas alguns casos de teste extras. As normas práticas também tendem a não ser sensíveis a quais combinações de testes são escolhidas. Estas características não são, necessariamente, boas propriedades; elas apenas surgiram a partir da maneira simples a partir da qual as normas são definidas. O domínio de dados de entrada é dividido em regiões normalmente chamadas de subdomínios, cada um dos quais contendo um conjunto de entradas. Os subdomínios juntos englobam todo o domínio de dados de entrada - ou seja, toda entrada está em pelo menos um subdomínio. Uma divisão do domínio de dados de entrada em subdomínios define uma norma implícita: que define que deva existir pelo menos um caso de teste para cada subdomínio. Subdomínios, normalmente, não são disjuntos, portanto, um único caso de teste pode estar em vários subdomínios. A intuição por trás dos subdomínios pode ser compreendida em duas partes. Primeiro, é uma maneira fácil (pelo menos conceitualmente) de se determinar se um suíte de testes é bom o suficiente. Segundo, esperamos que, ao exigir um caso de teste de cada subdomínio, faremos com 120

que os testes sejam orientados às regiões mais propensas a revelar bugs. Intuitivamente, cada subdomínio representa um conjunto de casos de teste similares; desejamos maximizar o benefício de nossa atividade de teste escolhendo casos de teste que não sejam similares - ou seja, casos de teste de diferentes subdomínios. No melhor caso, um subdomínio pode ser considerado revelador. Isto significa que todo caso de teste pertencente a este subdomínio faz com que o programa ou falhe ou tenha sucesso. O subdomínio, portanto, agrupa casos de teste verdadeiramente equivalentes. Se todos os subdomínios são reveladores, um suíte de testes que satisfaz à norma implícita estará completo, pois teremos a certeza de que o suíte irá encontrar qualquer bug. Na prática, no entanto, é muito difícil conseguir subdomínios reveladores, mas através de uma escolha cuidadosa dos subdomínios é possível ter-se, no mínimo, alguns subdomínios cuja taxa de erros - a proporção de entradas de dados que levam a saídas de dados erradas - é bem maior que a média de erros do domínio de dados de entrada como um todo. 11.5 Norma de Subdomínio A norma padrão e mais amplamente utilizada para a atividade de teste do tipo program-based é denominada 'statement coverage', ou 'cobertura das sentenças': que define que toda a sentença de um programa deve ser executada pelo menos uma vez. Você pode perceber, através da definição da norma, por que ela é considerada uma norma de subdomínio: defina para cada sentença do programa um conjunto de entradas que fazem com que esta sentença seja executada, e escolha no mínimo um caso de teste para cada subdomínio. Obviamente, o subdomínio nunca é, explicitamente, construído; trata-se de uma noção conceitual. Ao invés disso, tipicamente, executase uma versão instrumentada do programa que registra cada sentença executada. Deve-se continuar acrescentando casos de teste até que todas as sentenças sejam executadas. Existem outras normas ainda mais trabalhosas do que o statement coverage. A norma denominada 'decision coverage', por exemplo, requer que todas as arestas do gráfico do fluxo de controle do programa sejam executadas - é como exigir que todos os ramos de um programa sejam executados. Não é tão óbvio o porquê desta abordagem ser considerada mais trabalhosa do que o statement coverage. Pois, então, considere aplicar esta norma a um procedimento que retorna o menor de dois números: static int minimum (int a, int b) { if (a b) return a; else return b; 121

Para este código, statement coverage, irá exigir entradas com a menor do que b evice-versa.no entanto, para o código static int minimum (int a, int b) { intresult=b; if (b a) result = b; return result; um único caso de teste com b menor do que a irá satisfazer a norma statement coverage, masnão poderíamos identificar o bug que está presente no código. Para satisfazer à norma decision coverage seria exigido um caso (um ramo) no qual o comando if não seja executado, expondo, desta forma, o bug. Existem muitas formas de 'condition coverage' que exigem, de diversas formas, que as expressões boolenas testadas como condição sejam avaliadas tanto para true como para false. Uma forma particular de condition coverage conhecida como MCDC, é exigida por um padrão denominado DoD específico para softwares de segurança crítica, como os da aviação. Este padrão, o DO-178B, classifica as falhas em três níveis, e requer um diferente nível de cobertura para cada nível: Nível C: a falha reduz a margem de segurança Exemplo: link de dados via rádio Requer: statement coverage Nível B: a falha reduz a capacidade da aeronave ou da tripulação Exemplo: GPS Requer: decision coverage Nível A: a falha causa a perda da aeronave Exemplo: sistema de gerenciamento de vôo Requer: MCDC coverage Uma outra forma de norma de subdomínio do tipo program-based é utilizada em testes denominados boundary testing, ou testes limite. Estes tipos de testes exigem que os casos extremos para toda sentença condicional sejam avaliados. Por exemplo, se o seu programa testa x<n, seriam necessários casos de teste que produzissem x=n, x=n-1, ex=n+1. 122

Normas do tipo specification-based são, também, muitas vezes moldadas em termos de subdomínios. Pelo fato de que as especificações são, normalmente, informais - ou seja, não são escritas em nenhuma notação muito precisa - as normas tendem a ser um tanto vagas. A abordagem mais comum é definir subdomínios de acordo com a estrutura da especificação e de acordo com os valores dos tipos de dados subjacentes. Por exemplo, os subdomínios de um método que insere um elemento em um conjunto podem ser: o conjunto é vazio o conjunto é não vazio e o elemento não está no conjunto oconjuntoénãovazioeoelementoestánoconjunto. Você pode, também, utilizar na especificação qualquer estrutura condicional para guiá-lo na divisão do domínio de dados de entrada em subdomínios. Além disso, na prática, as pessoas incumbidas de realizar os testes utilizam seu conhecimento a respeito dos tipos de erros que muitas vezes surgem no código. Por exemplo, se você estiver testando um procedimento que encontra um elemento em um array, você, provavelmente, irá colocar o elemento de teste no início, no meio e no fim, simplesmente porque estes casos são propensos a ser manipulados diferentemente no código. 11.6 Viabilidade Cobertura total é raramente possível. De fato, mesmo que se alcance 100% das sentenças do código, é normalmente impossível alcançar a cobertura total. No mínimo, esta impossibilidade ocorre em razão de código decorrente de programação defensiva, código que, em grande parte, nunca é executado. As operações de um tipo abstrato de dado, que não possuem nenhum cliente, também não serão testadas pelos casos de teste, independente do rigor aplicado; no entanto, estes testes podem ser executados por testes de unidade. Uma norma é considerada viável se for possível satisfazê-la. Na prática, as normas normalmente não são viáveis. Em termos de subdomínio, elas contêm subdomínios vazios. A questão prática é determinar se um subdomínio particular é vazio ou não; se for vazio, não há razão em se procurar um caso de teste que o satisfaça. Falando de forma geral, quanto mais elaborada a norma, mais difícil é a sua determinação. Por exemplo, a norma denominada path coverage exige que todos os caminhos do programa sejam executados. Suponha que o programa se pareça com isto: 123

if C1 then S1; if C2 then S2; então, para se determinar se o caminho S1;S2 é viável, precisamos determinar se as condições C1 e C2 podem, ambas, serem verdadeiras. Para um programa complexo, esta não é uma tarefa trivial e, no pior caso, não é mais fácil do que determinar seu programa está correto, ou não, através do raciocínio! A despeito destes problemas, a idéia de se cobrir as possibilidades do programa é muito importante na prática. Se existe um número significante de partes do seu programa que nunca foram executadas, não há como se ter muita certeza que este programa está correto! 11.7 Diretrizes Práticas Deve estar claro porque nem as normas program-based, nem as normas specification-based são, se utilizadas isoladamente, boas o suficiente. Se você apenas olhar o programa, você não identificará erros por ser omisso. Se você olhar apenas a especificação, você não irá identificar os erros que surgem em decorrência de problemas de implementação, como, por exemplo, quando os limites de um determinado recurso computacional são alcançados, ocasião quando um procedimento de compensação é necessário. Na implementação da classe ArrayList do Java, por exemplo, o array da representação é substituído quando fica cheio. Para se testar este comportamento, será necessário inserir uma quantidade suficiente de elementos para que o array fique cheio. A experiência sugere que a melhor forma de se desenvolver um suíte de testes é utilizando-se normas do tipo specification-based para guiar o desenvolvimento do suíte e, para testar o suíte, é melhor que se utilizem normas do tipo program-based. Assim, você será capaz de examinar a especificação, e capaz de definir subdomínios de entrada. Baseando-se nessas premissas, você pode escrever os casos de teste. Então, você executa os casos de teste, e mede a cobertura dos testes em relação ao código. Se a cobertura não for adequada, basta que se adicionem novos casos de teste. Nos padrões industriais, você utilizaria uma ferramenta especial para medir a cobertura dos testes em relação ao código. No curso 6170, não exigiremos que você aprenda a utilizar qualquer ferramenta. Ao invés disso, você deve apenas escolher casos de teste suficientemente elaborados para que possa argumentar que alcançou uma cobertura considerável do código. As certificações em tempo de execução, especialmente as que representam checagens de invariante, irão dramaticamente aumentar o poder dos seus testes. Você irá encontrar mais bugs e poderá solucioná-los mais facilmente. 124