testes de software - módulo 1
Post on 16-Jan-2015
835 Views
Preview:
DESCRIPTION
TRANSCRIPT
Testes de Software
Prof. Rodrigo de Barros Paes
rodrigo@ic.ufal.br
rodrigo@ic.ufal.br 2
Objetivos da disciplina COMP259 - TESTE DE SOFTWARE
oOs objetivos da disciplina envolvem o estudo e prática de conceitos chave acerca de testes de software, tais quais estão abaixo:
oFundamentos de Testes de Software
oPlanejamento de Testes
oTeste Caixa Preta
oTeste Caixa Branca
oFerramentas para apoio e automação de teste
rodrigo@ic.ufal.br 3
Ementa específica
oDomínio, intervalos, oráculos e tipos de teste
oCobertura do teste
o Testes aleatórios
o Teste aleatório na prática
o Teste em uma aplicação web
rodrigo@ic.ufal.br 4
Créditos
oMuitos slides, ideias e referências desse curso tiveram origem nos seguintes locais
oProf. Ardnt Von Staa, PUC-RIO, disciplina de Testes de Software, http://www.inf.puc-rio.br/~inf1413/
oMassachusetts Institute of Technology, Elements of Software Construction
oUdacity, Software Testing (curso on-line)
rodrigo@ic.ufal.br 5
Introdução Qualidade de Software
rodrigo@ic.ufal.br 6
Do ponto de vista do usuário
oUm sistema correto:
oResolve o meu problema;
oFunciona sempre que eu preciso dele;
oEu entendo como usar;
oEu posso justificavelmente depender dele.
Correct Systems: Building a Business Process Solution (Applied Computing) Paperbackby Mike Holcombe, Florentin Ipate, 1998
rodrigo@ic.ufal.br 7
Errare humanum est
o Errar é inerente ao ser humano
ocomo somos falíveis e o desenvolvimento de software é intensivo em esforço humano, é utópico esperar que software não contenha defeitos.
o Sed in errore perseverare dementis (mas perseverar no erro é próprio do louco)
oé frequente não aprendermos com os nossos erros de modo que possamos reduzir a frequência de defeitos em um novo software
rodrigo@ic.ufal.br 8
O que é um sistema?
defeito
erro
falha
vulnerabilida
de
sistema
observadorEngano do desenvolvedor ou falha da ferramenta
Engano do desenvolvedor ou falha da ferramenta
dano
rodrigo@ic.ufal.br 9
Definições
o Artefatos são resultados tangíveis resultantes do desenvolvimento ou da manutenção
o Defeito é um fragmento de um artefato que, se utilizado, pode levar a um erro
o Erro é um desvio entre o que é desejado ou intencionado e o que é gerado ou derivado
o pode existir sem que se saiba isso
o Falha é um erro observado
o Latência do erro é o tempo decorrido entre o momento em que o erro é gerado e o momento em que é observado
o quanto maior a latência significativamente maior é o custo da remoção da causa, i.e. o defeito
rodrigo@ic.ufal.br 10
BUG
o Indícios do uso da palavra BUG em engenharia
o“Defeitos inexplicáveis”It has been just so in all of my inventions. The first step is an intuition, and comes with a burst, then difficulties arise — this thing gives out and [it is] then that "Bugs" — as such little faults and difficulties are called — show themselves and months of intense watching, study and labor are requisite before commercial success or failure is certainly reached.
Thomas Edison, 1878
rodrigo@ic.ufal.br 11
BUG – na computação
oGrace Hoper trabalhava no computador Mark II (Harvard) em 1946, quando o Mark II começou a apresentar uma falha
oCausa: uma mariposa
Mark I (não achei foto do II)
rodrigo@ic.ufal.br 12
Software é “Bugento”
o Cerca de 40 a 50% dos programas postos em uso contêm defeitos não triviais
o defeito não trivial:
o demora para ser diagnosticado e removido
o e/ou produz danos elevados
o Como reduzir este percentual?
o procurar chegar perto do ideal corretude por construção
o realizar continuamente controle da qualidade: ao especificar,
o arquitetar, projetar, codificar: corretude por desenvolvimento
rodrigo@ic.ufal.br 13
Software é “Bugento””
oComo reduzir o tempo médio para recuperar?
oProjeto e programação orientada à recuperabilidade
oComo reduzir o tempo médio para corrigir?
oprojeto e programação orientada à corrigibilidadeBoehm, B.W.; Basili, V.R.; "Software Defect Reduction Top 10 List"; IEEE Computer 34(1); Los Alamitos, CA: IEEE Computer Society; 2001; pags 135-137
rodrigo@ic.ufal.br 14
Não existe software perfeito
o Mesmo sistemas perfeitos podem falhar. Erros provocados por causas exógenas:
o erros provocados por mau uso, deliberado ou não
o erros provocados por falhas de hardware
o erros provocados por falhas da plataforma de software usada
o Perfeição não existe, densidade de defeitos [Bao, 2007]:
o INTEL: no more than 80-90 defects in Pentium (em 2012: +- 3*10**9 transistores no chip; existem GPU’s com +- 7*10**9 transistores [Wikipedia])
o Standard Software: 25 defects / 1,000 lines of delivered code (kLOC)
o Good Software: 2 defects / 1,000 lines
o Space Shuttle Software: < 1 defect / 10,000 linesXinlong Bao; Software Engineering Failures: A Survey; School of EECS, Oregon State University, Corvallis, OR, U.S.A; apud Huckle, T.; Collection of Software Bugs; http://www5.in.tum.de/~huckle/bugse.html; last update October 5, 2007
rodrigo@ic.ufal.br 15
Crenças
oNão é possível prever todos os potenciais riscos (causas dos erros)
oNão se pode esperar que sistemas não contenham defeitos
oSe o sistema realmente não tiver defeitos, nós não temos como ter 100% de certeza. Ou seja, não saberemos.
rodrigo@ic.ufal.br 16
Fidedignidade
o Fidedignidade de software é definida como sendo a fidelidade de um sistema intensivo em software de modo que se possa justificavelmente depender dele assumindo riscos compatíveis com o serviço por ele prestado.
o fidedigno (Adjetivo) Digno de fé; merecedor de crédito (Aurélio)
o fidelidade (Substantivo feminino) Exatidão em cumprir suas obrigações, em executar suas promessas. (Aurélio)
RISCO = PROBABILIDADE X IMPACTO(CUSTO) X RELEVÂNCIA
rodrigo@ic.ufal.br 17
Características da fidedignidade (básicas)
o Adequação: prestar o serviço que interessa ao usuário usuário pode ser: pessoa; outro artefato; outro sistema; sensores e/ou atuadores; mantenedores; operadores; ...
o Usabilidade: habilidade de interagir com o usuário sem induzi-lo a erro, nem permitir que erros de uso (observáveis) fiquem despercebidos
o Durabilidade: habilidade do software operar fidedignamente por períodos de duração indefinida (longa duração, e.g. 24/7)
o Confiabilidade: prestar continuamente serviço fidedigno
o Disponibilidade: estar pronto para prestar serviço fidedigno sempre que solicitado
rodrigo@ic.ufal.br 18
Características da fidedignidade (básicas)
o Segurança: (safety) habilidade de evitar consequências catastróficas aos usuários, à organização, ou ao ambiente (risco baixo)
o Proteção: habilidade de evitar o sucesso de tentativas de agressão
o Privacidade: habilidade de proteger dados e código contra acesso (uso) indevido acidental ou deliberado
o Desempenho: habilidade de produzir resultados necessitando de poucos recursos (ex. tempo, memória) otimização ou: habilidade de atender à demanda consumindo recursos dentro do limite estipulado
o Escalabilidade: habilidade da capacidade de processamento do software crescer junto com o crescimento da demanda
o Interoperabilidade: habilidade de ser corretamente conectado com outro sistema
rodrigo@ic.ufal.br 19
Características da fidedignidade (tolerância)
o Robustez: habilidade de, em tempo de execução, detectar erros (reportar falhas) de modo que os possíveis danos ou lesões possam ser mantidos em um patamar aceitável
o um software robusto não provoca lesões (lesão: “prejuízo” não conhecido)
o pode gerar danos desde que controlados (dano: “prejuízo” conhecido)
o Resiliência: habilidade de amoldar-se a condições anormais de funcionamento sem comprometer a fidedignidade
o Recuperabilidade: habilidade de ser rapidamente reposto em operação fidedigna, preventivamente ou após a ocorrência de uma falha
o Corrigibilidade: habilidade de ser fácil e rapidamente corrigido quando da ocorrência de uma falha.
rodrigo@ic.ufal.br 20
Características da fidedignidade (evolução)
o Manutenibilidade: habilidade de poder ser modificado ou corrigido com facilidade e sem que novos defeitos sejam inseridos
o manutenção preventiva – refactoring
o correção – corrigibilidade
o melhorias, adaptação e evolução – evolutibilidade
o Longevidade: habilidade do software e dos dados persistentes por ele utilizados terem vida longa, evoluindo junto com as necessidades do usuário, com a plataforma, ou com a tecnologia utilizada para a sua implementação
o engenharia reversa
o reengenharia
o rejuvenescimento
o Co-evolutibilidade: facilidade de manter a coerência entre todos os artefatos que constituem o software.
o Disponibilizabilidade: facilidade de distribuir e por em uso correto as novas versões.
rodrigo@ic.ufal.br 21
Crenças (cont.)
o Adicionar características de fidedignidade a posteriori é usualmente muito caro
o as características necessárias precisam ser especificadas, arquitetadas, projetadas etc. junto com os requisitos funcionais
o é necessário identificar a priori que características são necessárias
o isso é sempre possível?
o para atingir bons níveis de fidedignidade deve-se:
o prevenir a injeção de defeitos
o controlar as potenciais falhas provocadas por causas exógenas
o Usuário
o Plataforma
o bibliotecas
rodrigo@ic.ufal.br 22
O que queremos?
Ter a certeza de que estamos desenvolvendo software, de forma econômica, possuindo qualidade de serviço assegurada e capaz de
operar em ambientes reais.
Qualidade de serviço = qualidade observada pelo usuário
rodrigo@ic.ufal.br 23
Qualidade de Software
Definições básicas
rodrigo@ic.ufal.br 24
Qualidade de um artefato
oA qualidade de um artefato é um conjunto de propriedades a serem satisfeitas em determinado grau, de modo que o artefato satisfaça as necessidades explícitas e implícitas de seus usuários e clientes.
o“Em determinado grau” necessidade de definir e medir
o“explícitas” é preciso especificar
o“implícitas” requer o uso de “bom sendo”, conhecimento do domínio, conhecimento do negócio, mas mesmo assim, como saber se não deixamos algo passar?
rodrigo@ic.ufal.br 25
Qualidade satisfatória
o Um artefato possui qualidade satisfatória caso satisfaça plenamente as necessidades e anseios de clientes e usuários, oferecendo riscos de uso justificavelmente aceitáveis
o fidedignidade
o a noção de “satisfatório” varia
o com a finalidade a que se destina o artefato
o com a natureza do artefato
o com o nível de treinamento / conhecimento do usuário
rodrigo@ic.ufal.br 26
Conceitos básicos
o Qualidade por construção
o Um artefato possui qualidade por construção caso possua qualidade satisfatória, considerando todas as propriedades relevantes, antes do primeiro teste
o Qualidade por desenvolvimento
o Um artefato possui qualidade por desenvolvimento caso possua qualidade satisfatória, considerando todas as propriedades relevantes, antes de ser posto em uso
o podem sobrar defeitos não conhecidos!
o Qualidade por manutenção
o Um artefato possui qualidade por manutenção caso possua qualidade satisfatória, considerando todas as propriedades relevantes, antes de ser reposto em uso
o podem ter sido adicionados defeitos não conhecidos!
rodrigo@ic.ufal.br 27
Modelo economia da qualidade
custo
qualidade assegurada pelo desenvolvimento
custo desenvolvimento
valor do serviço
custo total
custo do risco = f(probabilidade, impacto, relevância)
Perda por falta de qualidade
Perda por excesso de qualidade
rodrigo@ic.ufal.br 28
Por que desenvolver com qualidade?
oCusto do mau funcionamento, exemplos
oAborrecimento, pequenas perdas financeiras e/ou de material, grandes perdas financeiras e/ou de material, falência de empresas, acidentes graves, danos ecológicos consideráveis, perda de vidas
oCusto da correção
oRetrabalho inútil
rodrigo@ic.ufal.br 29
Por que desenvolver com qualidade?
oUma das principais causas do excessivo tempo gasto (custo) ao desenvolver software é o retrabalho inútil
oÉ responsável por algo em torno de 50% a 80% do custo de desenvolvimento.
oRetrabalho inútil – é trabalho que não precisaria ter sido realizado, se o trabalho anterior tivesse sido realizado visando fidedignidade, ou seja pelo menos de forma correta, completa, consistente, e adequada aos usuários
Fairley, R.E.; Willshire, M.J., "Iterative rework: the good, the bad, and the ugly," Computer , vol.38, no.9, pp.34,41, Sept. 2005
rodrigo@ic.ufal.br 30
Exemplos de retrabalho inútil
o desenvolver algo e descobrir que não era isso que se queria ou que se precisava
o causa: especificação inexistente ou mal formulada
o desenvolver algo e descobrir que está cheio de defeitos
o causa: falta de disciplina
o causa: falta de conhecimento de como raciocinar sobre programas, componentes, módulos e código
o trabalhar sem foco
o causa: falta de método de trabalho
o perfeccionismo patológico
o causa: melhorar, melhorar e melhorar mais ainda algo que já está satisfatório
rodrigo@ic.ufal.br 31
Introdução a testes
rodrigo@ic.ufal.br 32
Atividades típicas de um Software
Análise e especificação de
requisitosProtótipos
de tela
Projeto, provas de conceito
Codificação (sistema +
testes)
Release
Produção
rodrigo@ic.ufal.br 33
Atividades típicas de um Software
Análise e especificação de
requisitosProtótipos
de tela
Projeto, provas de conceito
Codificação (sistema +
testes)
Release
Produção
Técnicas da garantia de qualidade:
• Revisão de requisitos – busca por clareza, ausência de ambiguidades, etc.
• Métricas para os requisitos, ex: #falhas nos testes cuja causa foram requisitos mal especificados
• Especificação formal
• Inspeções de código
• Testes
rodrigo@ic.ufal.br 34
Foco
o Logo, esse curso se concentra em uma das atividades para se chegar a um software de maior qualidade
o Embora existam outras
rodrigo@ic.ufal.br 35
Introdução
o Se nós pudermos encontrar os defeitos do nosso software
o Se pudermos corrigir esses defeitos
o Então, um dia teremos o software livre de “bugs”. Um software em que poderemos confiar!!
o É só ter grana e investir em uma quantidade suficiente de testes
rodrigo@ic.ufal.br 36
Algumas empresas com “grana”
oMicrosoft
oGoogle
rodrigo@ic.ufal.br 37
Mais algumas
oApple
oUbuntu
rodrigo@ic.ufal.br 38
Hummm … beleza, e agora?
o Se essas empresas não conseguiram, como eu vou conseguir fazer isso no meu próprio software?
o Resposta curta: você também não vai conseguir!
o Resposta longa: mas você pode chegar a uma qualidade satisfatória com a ajuda das técnicas do restante desse curso
o Iremos quebrar esse problemão em vários pequenos problemas
o Veremos técnicas específicas para cada um dos pequenos problemas
o Quando você se tornar “bom” na resolução dos pequenos problemas, você fará software de forma mais confiável como um todo
rodrigo@ic.ufal.br 39
O que é teste?
o Como escolher boas entradas?
o Sempre é possível saber o resultado esperado?
o Sempre dá pra automatizar o teste?
rodrigo@ic.ufal.br 40
Algumas dicas
o Encontre defeitos o mais cedo possível
o É possível gastar muito tempo na atividade de teste e ainda assim testar mal. Portanto, testar direito é importante, mas requer técnica e alguma imaginação
oNem sempre mais teste é melhor
oA tarefa de teste pode ser facilitada se o software for projetado para ser testado
rodrigo@ic.ufal.br 41
Falhou, e agora?
o Quanto mais a gente “anda” para a direita nesse diagrama, mais a gente aprende sobre o software
o O teste é um pequeno experimento onde um teste que falha indica que alguma coisa está errada. Descobrir onde está o erro é um processo a parte e muitas vezes trabalhoso.
testoutput
rodrigo@ic.ufal.br 42
Exemplo
o Em 1998, foi lançado um foguete para analisar o clima de Marte
o A NASA subcontratou a empresa Lockheed Martin para ajudá-los com o software e com o foguete
o Em 1999, o foguete chegou à Marte
o Os cálculos da trajetória
o A NASA esperava o que o sistema utilizasse a unidade métrica (metros por segundo)
o A Lockheed Martin programou usando pés por segundo
rodrigo@ic.ufal.br 43
Exemplo
o Dano
oO foguete executou uma trajetória diferente e explodiu em Marte
o Embora tanto a NASA quanto a Lockheed tenha feito cálculos corretos, o software tenha sido programado corretamente, a falha aconteceu
rodrigo@ic.ufal.br 44
Pergunta
a)A causa foi um defeito no software sob teste?
b)A causa foi um defeito no teste de aceitação quando eles testaram o software anteriormente?
c)A causa foi um defeito na especificação do sistema?
d)A causa foi um defeito no hardware ou no sistema operacional do foguete?
Minha resposta é (c)
rodrigo@ic.ufal.br 45
Por que testar?
rodrigo@ic.ufal.br 46
Programadores “de verdade” não testam
o O importante é que funcione e que funcione rápido, se eu for fazer o teste vai me atrasar
o Eu comecei a programar aos 5 anos de idade, meu código é perfeito, não preciso de testes
o Teste é para os programadores incompetentes
o Nós somos programadores da UFAL, portanto nosso código funciona
o A maioria das funções do minha classe Grafo.java possui apenas uma ou duas linhas. Essas linhas simplesmente utilizam funções das classes HashMap ou HashSet. Estou assumindo que essas funções funcionam perfeitamente e, portanto, não preciso testá-las.
rodrigo@ic.ufal.br 47
Bugs famosos
o Ariane 5
o Se auto-destruiu 37 segundos após a decolagem
o http://youtu.be/gp_D8r-2hwk
o Reutilização do módulo de navegação do Ariane 4
o Mas não simularam como esse módulo se comportaria sob as mesmas condições de vôo do Ariane 5
o A maior aceleração do Ariane 5 fez com uma conversão de dados de um float de 64 bits para um inteiro de 16 bits não fosse verificada para um provável overflow
o O que de fato aconteceu
rodrigo@ic.ufal.br 48
Bugs famosos
oAriane 5L_M_BV_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BV) * G_M_INFO_DERIVE(T_ALG.E_BV)); if L_M_BV_32 > 32767 then P_M_DERIVE(T_ALG.E_BV) := 16#7FFF#;elsif L_M_BV_32 < -32768 then P_M_DERIVE(T_ALG.E_BV) := 16#8000#;else P_M_DERIVE(T_ALG.E_BV) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));end if; P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS (TDB.T_ENTIER_16S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH)));
Verificaram o overflowpara a variável E_BV (trajetória vertical)
Esqueceram de fazer a mesma coisa para a variável E_BH (trajetória horizontal)
rodrigo@ic.ufal.br 49
Bugs famosos
oAriane 5L_M_BV_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BV) * G_M_INFO_DERIVE(T_ALG.E_BV)); if L_M_BV_32 > 32767 then P_M_DERIVE(T_ALG.E_BV) := 16#7FFF#;elsif L_M_BV_32 < -32768 then P_M_DERIVE(T_ALG.E_BV) := 16#8000#;else P_M_DERIVE(T_ALG.E_BV) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));end if; L_M_BH_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH)); if L_M_BH_32 > 32767 then P_M_DERIVE(T_ALG.E_BH) := 16#7FFF#;elsif L_M_BH_32 < -32768 then P_M_DERIVE(T_ALG.E_BH) := 16#8000#;else P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BH_32));end if;
Código corrigido
rodrigo@ic.ufal.br 50
Bugs famosos
o Therac 25
omáquina de radioterapia, controlada por computador, muito moderna para sua época, por permitir a utilização do mesmo equipamento para a aplicação de diversas doses de radiação nos pacientes.
rodrigo@ic.ufal.br 51
Bugs famosos – Therac 25
o 2 modos de operação
oElétron (baixa intensidade radiação)
o Aplicada diretamente no paciente
oRaio-X (alta intensidade de radiação)
o Passava por um “filtro”, era convertida em raios X e tinha sua intensidade diminuída e “espalhada”
rodrigo@ic.ufal.br 52
Bugs famosos – Therac 25
o Problemas
oO software as vezes funcionava no modo de alta intensidade e não acionava o filtro, fazendo com que a radiação fosse aplicada diretamente sobre os pacientes
oO software não detectava quando essa situação ocorria (assertivas)
o Danos
o 6 acidentes e 5 mortes entre 1985 e 1987
rodrigo@ic.ufal.br 53
Bugs famosos – World of Warcraft
o Corrupted Blood Incident
o Masmorra de Zul'Gurub
o Um chefão: Hakkar (o deus do sangue)
o Quando atacado, lançava sobre os oponentes uma magia do “Corrupted Blood”
o A magia deveria
o Durar apenas alguns segundos
o Ficar restrita a uma determinada área de Zul'Gurub
rodrigo@ic.ufal.br 54
Bugs famosos – World of Warcraft
o BUG
o Pequenos animais e monstrinhos (minions) se contaminaram e levaram a magia para fora da área determinada
o Outros personagens se contaminaram
o Configurou-se uma pandemia
o Muita reclamação dos usuários
o Usuários evitaram áreas de grandes concentrações
rodrigo@ic.ufal.br 55
Um exemplo Fila Circular de Tamanho
Fixo
rodrigo@ic.ufal.br 56
Fila circular de tamanho fixo
• Operações básicas• enqueue• dequeue• full• empty
• Comportamento• First in First Out (FIFO)
• Exemplo• enqueue(7)
enqueue(8)dequeue() # deve retornar 7dequeue() # deve retornar 8dequeue() # deve retornar algum erro ou vazio
rodrigo@ic.ufal.br 57
Fila circular de tamanho fixo
o Atributos
o size : int
o max : int
o head : int
o tail : int
o data : int[ ]
o Passos:
o Criar uma classe Queue
o O método inicial “__init__” deve receber o tamanho máximo da fila
o O array deve ser estático (http://docs.python.org/3/library/array.html)
rodrigo@ic.ufal.br 58
Fila circular de tamanho fixo
o empty(): retorna True caso fila esteja vazia
o full(): retorna True caso a fila cheia
o enqueue(x): adiciona o elemento x na fila e returna True caso tenha conseguido adicionar. False caso não seja possível adicionar o elemento
o dequeue(): retorna o próximo elemento da fila, caso exista. None caso contrário.
rodrigo@ic.ufal.br 59
Todo mundo fez?
o Terminaram???
rodrigo@ic.ufal.br 60
__init__
def __init__(self,size_max):
self.max = size_max
self.head = 0
self.tail = 0
self.size = 0
self.data = array.array('i', range(size_max))
rodrigo@ic.ufal.br 61
empy, full
def empty(self):
return self.size == 0
def full(self):
return self.size == self.max
rodrigo@ic.ufal.br 62
Pergunta
o Suponha que a gente crie uma fila de 2 elementos. Definiremos uma variável temporária r1 como sendo o valor de retorno do enfileiramento do inteiro 6, r2 o valor retornado do enfileiramento do inteiro 7, r3 retorno do enfileiramento do inteiro 8, r4 o valor retornado pelo desenfileiramento de um elemento, r5 ser o valor devolvido pelo desenfileiramento de outro elemento, e, finalmente, r6 ser o valor devolvido pelo desenfileiramento de mais um elemento. Qual o valor dessas variáveis?
o a) 6, 7, 8, 6, 7, 8.
o b) True, True, True, 6, 7, None.
o c) True, True, False, 6, 7, 8.
o d) True, True, False, 6, 7, None.
o A resposta correta é d
rodrigo@ic.ufal.br 63
Pergunta
• Suponha o teste:def test_queue(self):
q = Queue(2)
q.enqueue(7)
self.assertEquals(7, q.dequeue())
• Caso o teste seja um sucesso, o que aprendemos?
a) Nosso código passou nesse caso de teste;
b) Nosso código passará em qualquer caso em que troquemos o 7 por outro inteiro;
c) Nosso código passará em muitos casos em que troquemos o 7 por outro inteiro;
• Resposta• Obviamente a (a) está correta;• Será que a (b) está correta?
• E se passarmos um inteiro tão grande que o tipo inteiro da sua linguagem não conseguir armazená-lo?
• A (c) também está correta
Verifica se o valor esperado é igual ao valor obtido.Nesse caso, verifica se 7 é igual ao retorno de q.dequeue()
Moral da história: ao fazer um caso de teste, pense o que você poderá inferir a partir dele. Com isso você evitará escrever muitos casos de teste que significam a mesma coisa
rodrigo@ic.ufal.br 64
Testes equivalentes
o Dado um caso de teste, é possível concluir que um outro caso de teste também irá funcionar? Mesmo sem de fato executar o caso de teste?
?Olhe novamente para o seu código. O fato de haver um sleep trará alguma consequência?Existe alguma dependência do tempo?
1 caso de teste como representante de uma classe de entradas e saídas
rodrigo@ic.ufal.br 65
Prática
• No exemplo anterior, mostramos como um teste pode ser um representante de uma classe
• Nesse exercício iremos fazer o contrário, ou seja, não vamos testar funcionalidades equivalentes
• Escreva mais uma ou duas funções de teste de forma a explorar situações que a função test_1 não explorou, por exemplo:
• Não testamos o caso onde a fila fica cheia no enqueue
• Não testamos a situação onde a fila está vazia e tentamos fazer um dequeue
• …
• Chame a sua primeira função de test_enqueue e procure explorar os testes da função enqueue
• Chame a segunda função de test_dequeue e explore os testes da função dequeue
rodrigo@ic.ufal.br 66
Code It !!
o Existem várias soluções corretas
oO importante é exercitar as situações do código
rodrigo@ic.ufal.br 67
“Minha” solução
rodrigo@ic.ufal.br 68
enqueue
def enqueue(self,x):
if self.size == self.max:
return False
self.data[self.tail] = x
self.size += 1
self.tail += 1
if self.tail == self.max:
self.tail = 0
return True
rodrigo@ic.ufal.br 69
dequeue
def dequeue(self):
if self.size == 0:
return None
x = self.data[self.head]
self.size -= 1
self.head += 1
if self.head == self.max:
self.head = 0
return x
rodrigo@ic.ufal.br 70
Assertivas de execução
rodrigo@ic.ufal.br 71
Definições
o É uma verificação executável de uma propriedade do seu código
o Podem ser desligadas (discutiremos sobre isso depois)
o Exemplo: cálculo da função de raiz quadrada
def sqrt(x): ## aqui ficaria o seu código para encontrar a raiz quadrada assert(result >= 0) return result
an assertion is a predicate (a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. If an assertion evaluates to false at run-time, an assertion failure results, which typically causes execution to abort.
wikipedia
rodrigo@ic.ufal.br 72
Regras para o uso de assertivas
o As assertivas não devem ser utilizadas para o tratamento de erros
o No caso da função anterior, poderíamos ter feito:
def sqrt(x): assert(x >= 0) ## aqui ficaria o seu código para encontrar a raiz quadrada assert(result >= 0) return result
o Só que:
o x foi gerado em alguma outra parte do código e, portanto, o local da assertiva deveria ser lá
o Se você quiser garantir a pré-condição que x é maior que zero, seria mais adequado realizar um tratamento de erros (http://docs.python.org/2/tutorial/errors.html)
rodrigo@ic.ufal.br 73
Regras para o uso de assertivas
oAs assertivas não devem provocar efeitos colaterais
oExemplo:
assert( funcao( ) == 0) ## só que funcao( ) muda o valor de alguma variável com escopo global (atributo de objeto, variável estática, …)
oO que aconteceria se desligassemos as assertivas?
o O código teria um comportamento diferente com assertivas e sem assertivas
rodrigo@ic.ufal.br 74
Regras para o uso de assertivas
oNão escreva assertivas inúteis
oassert(1+1 ==2)
oVocê deve buscar verificar propriedades não-triviais que poderia estar errada caso você tenha colocado algum defeito na sua lógica
rodrigo@ic.ufal.br 75
CheckRep
o Algumas propriedades devem ser sempre verdade durante a execução de um código
o Invariantes
o Exemplo com a nossa fila:
o 0 <=size <= max
o Uma ideia é criar uma função para verificar essas invariantes
o Você deve chamar essa função no final de cada método do seu objeto … assim você verifica se você não “quebrou” nenhuma dessas invariantes
rodrigo@ic.ufal.br 76
Código para verificar a invariante
Que outras invariantes poderíamos ter?
rodrigo@ic.ufal.br 77
Vamos fazer uma pequena simulação
o http://youtu.be/SmdYmxQYIB0
rodrigo@ic.ufal.br 78
Problemas
o Veja que no primeiro caso, a nossa invariante foi acionada e o programa parou
o Se ele não tivesse sido acionada, provavelmente o programa continuaria rodando, mas em um estado de erro
oOu seja, resultados provavelmente iriam acontecer .... e outras partes do programa
o O segundo caso ilustra a utilidade de mantermos testes automatizados
rodrigo@ic.ufal.br 79
Hora de melhorar as nossas invariantes
oQue outras invariantes seriam úteis para o nosso código da fila?
rodrigo@ic.ufal.br 80
Mais invariantes
rodrigo@ic.ufal.br 81
Introduza um defeito
o vamos voltar a fazer o tail receber 1 ao invés de 0
oVeja que agora o check_rep levantou dois erros, tanto no deste de enqueue quanto no de dequeue (que não havia sido detectado antes)
oAs assertivas verificaram o detalhe interno da estrutura de dados, muitas vezes inacessível a um teste devido ao encapsulamento
rodrigo@ic.ufal.br 82
Por que usar assertivas?
oO código se torna auto-verificável
oFalha proativa
oNa presença de um defeito, o código falha antes, e falha próximo da origem do defeito, reduzindo o tempo de debugging
o Funcionam como uma espécie de documentação executável deixando explícito as premissas que você usou para construir o código
rodrigo@ic.ufal.br 83
Devemos usar assertivas em produção?
oGCC: 9000 assertivas
o LLVM: 13.000 assertivas1.2 milhões de linhas de códigoaproximadamente 1 assertiva para cada 100
linhas de código
oCerto .... E daí? Devemos usar em produção?
rodrigo@ic.ufal.br 84
Desabilitar assertivas em produção?
• Vantagens• O código rodará mais rápido• Se o seu código atingir um
estado de erro, ele continua rodando, ou seja, não pára
• Desvantagens• A gente quer que o sistema
continue rodando, mesmo podendo gerar resultados errados?
• Ou seja, o que é menos ruim?
• Com as assertivas, o código irá parar perto do local do erro, facilitando o debugging
"This code is absolutely loaded with assertions, and these are permanently enabled. As Valgrind has become more widely used, they have shown they worth, pulling up various bugs which would otherwise have appeared as hard-to-find segmentation faults. I am of the view that it's acceptable to spend 5% of the total running time doing assertion checks."
Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail
rodrigo@ic.ufal.br 85
Por outro lado
• Um engenheiro da NASA disse que para a maior parte da missão da nave, as assertivas estavam ligadas
• Lançamento• Cruzeiro• Órbita em Marte
• Em caso de violação, o sistema era reiniciado
• Porém, pouco antes do pouso, as assertivas eram desligadas
• Não daria tempo de reiniciar o sistema• Era melhor tentar pousar de qualquer
jeito
rodrigo@ic.ufal.br 86
Em outras palavras
o Em relação ao seu sistema ...
oÉ melhor que ele continue rodando e produzindo resultados errados?
o Não use assertivas
oOu é melhor que ele pare logo a execução?
o Use assertivas
rodrigo@ic.ufal.br 87
Especificações
rodrigo@ic.ufal.br 88
Especificação
oO software que você irá testar pode ser gigante ou muito pequeno
oMas o fato é que você gostaria de poder encapsular a implementação das funcionalidades e testar as funcionalidades
rodrigo@ic.ufal.br 89
Espeficificação
o Suponha um software que calcula a raiz quadrada
oQual a resposta esperada?
o a)
o b)
o a) e b)
rodrigo@ic.ufal.br 90
Especificação
oQualquer uma poderia estar correta
oDepende da sua especificação
oO software sempre funciona com base em alguma especificação
oSeja ela implícita ou explícita
o Parte do seu trabalho como testador é refinar a especificação, garantir que o entendimento está correto.
rodrigo@ic.ufal.br 91
Exercício
o Escreva sua especificação para a função “sqrt”
o Imagine que outra pessoa irá implementar
rodrigo@ic.ufal.br 92
Se usarmos a sua especificação e...
o ... chamarmos : sqrt(-1)
oA) 1
oB) i
oC) NaN
oD) levanta uma exceção
oE) -1
Essa não dá
Se estivermos trabalhando com números complexos, essa seria uma resposta aceitável
Também é uma resposta aceitável
Também é uma resposta aceitável
Essa também não dá
rodrigo@ic.ufal.br 93
Domínios e contra-domínios
o Podemos pensar no software que iremos testar como uma espécie de função matemática
oDomínio: conjunto de todos os valores que o software foi projetado para gerenciar
oContra-domínio (range): conjunto de todos os valores de saída possíveis para o software
rodrigo@ic.ufal.br 94
Exemplo da raiz quadrada
o Poderíamos pensar na função da raiz como aceitando somente números positivos e mostrando como resposta apenas números positivos
oUma outra função poderia aceitar qualquer número como entrada e oferecer como saída qualquer número, inclusive complexos
rodrigo@ic.ufal.br 95
Na prática
oOs computadores representam reais como números de ponto flutuante
o Suponha que queremos que o nosso domínio aceite números negativos, mas que a resposta não seja de números complexos
rodrigo@ic.ufal.br 96
Voltando as questões sobre testes
o Suponha a última especificação:
oDevemos testar esse código com entradas negativas?
oSim
oNão
rodrigo@ic.ufal.br 97
SIM!!!
oAs entradas negativas fazem parte do domínio
oDevemos testar com amostras de valores retiradas do domínio da função
rodrigo@ic.ufal.br 98
Domínios claramente definidos
o Em muitos casos, é possível definir precisamente o domínio
oBibliotecas para uso interno, uma classe que só será usada por outras classes dentro de um mesmo projeto, etc.
o Porém, em outros códigos não é possível definir esse domínio, pois você não terá controle da entrada
oEntrada de usuários, APIs acessíveis via Internet, uma API de um sistema operacional, etc.
rodrigo@ic.ufal.br 99
Exemplo
oChamada de sistema: read
oDisponível em plataformas UNIX: mac, Linux ...
rodrigo@ic.ufal.br 100
Quais desses testes são úteis?
a) Ler de um descritor de arquivo número 1 – esse é sempre descritor válido --, assumindo que você passa um buffer válido e você irá ler 10 bytes;
b) Ler em um buffer, 10 bytes mas usar o descritor -99999
c) Usar o descritor 1, mas passar como buffer um ponteiro para uma posição de memória inválida e ler 10 bytes
d) Usar o descritor 1, usar um buffer válido, mas ler -33333 bytes
rodrigo@ic.ufal.br 101
Resposta
o Todos!
oNão temos como garantir o domínio bem definido! Logo, devemos pegar amostras, que somadas, possuam uma grande representatividade do domínio
o S.O.
oPara o SO, da API pra “baixo”, ele confia nos componentes. Da “API” pra cima, ele tem que assumir que os programas irão atacá-los, ou usá-lo de forma errada
oEle precisa ser defensivo
rodrigo@ic.ufal.br 102
Crashme
oAloca um bloco de memória
o Escreve lixo nesse bloco
o Executa esse lixo no S.O.
http://crashme.codeplex.com/
rodrigo@ic.ufal.br 103
Fronteira de confiança
o Se você possui uma interface que representa uma fronteira de confiança, você precisa testar com os valores que representam o máximo do seu domínio
rodrigo@ic.ufal.br 104
Fronteira de confiança
o Suponha que você possui algum tipo de interface para interagir com o código dos outros membros da equipe
o Eles podem confiar que você irá sempre gerar entradas válidas de acordo com o domínio dessas entradas?
o E ao contrário? Você pode confiar neles?
oGeralmente a resposta é não!!
rodrigo@ic.ufal.br 105
Testes, APIs e dependências
o Testar um software com base na sua API é relativamente simples, basta chamar a API e olhar os resultados
oO problema é que muitas vezes o software que disponibiliza uma API também usa uma API
rodrigo@ic.ufal.br 106
Exemplo: WEB Browser
oO que fazer?
oBrowser crash
o Ignorar e se manter em um estado de erro
oParar de usar cookies até existir espaço em disco
GUI
network file ...
process page
store cookie
save
disk is full !
rodrigo@ic.ufal.br 107
Teste, não espere!!
oNão espere que tudo que você depende funcione
oMas como testar uma falha em algo que não controlamos?
rodrigo@ic.ufal.br 108
Exemplo
o ssize_t read(int fd, void *buf, size_t count);
oOn success, the number of bytes read is returned
oOn error, -1 is returned, and errno is set appropriately
rodrigo@ic.ufal.br 109
Exemplo read() em Python
rodrigo@ic.ufal.br 110
Fault Injection
o Introduza uma falha no seu código “de propósito” de forma a testar como o seu sistema irá se comportar em situações difíceis de reproduzir
oPouca memória
oHD sem espaço
rodrigo@ic.ufal.br 111
Exemplo
class MyTestCase(unittest.TestCase): def test_read(self): fr = FileReader("file.txt",True) self.assertEquals("This is a test file!",fr.get_content())
This is a test file!
rodrigo@ic.ufal.br 112
Exemplo (cont.)
class FileReader:
def __init__(self, file_name): self.file = open(file_name,"r")
self.content = self.file.read()
def get_content(self): return self.content
rodrigo@ic.ufal.br 113
Injetando uma falta
oVamos simular um problema com a leitura do arquivo
rodrigo@ic.ufal.br 114
Fault Injection
class FileReader:
def __init__(self, file_name, fault_injection): self.file = open(file_name,"r") self.fault_injection = fault_injection if ( not self.fault_injection): self.content = self.file.read() else: self.content = self.my_read()
def my_read(self, size=None ): # lê com um caracter a menos, simulando um eventual problema de pouca memória return self.file.read(size)[:-1]
def get_content(self): return self.content
rodrigo@ic.ufal.br 115
Quando devemos injetar faltas (defeitos) ?
o Em todos os cenários de falha possíveis
o Em nenhum caso
oNos locais onde você espera que aconteça e que você espera que o seu software se comporte bem
rodrigo@ic.ufal.br 116
Tipos de Teste
rodrigo@ic.ufal.br 117
White box X Black box
oWhite
oUso de detalhes internos do sistema para construir casos de testes melhores
oBlack
oSem o uso de detalhes internos. Teste baseado na entrada e saída esperadas, sem saber como as funções foram de fato implementadas
rodrigo@ic.ufal.br 118
Teste unitário
o Testa uma unidade de forma isolada
oGeralmente a unidade é pequena
oGeralmente o teste é caixa branca
oGeralmente quem testa é a mesma pessoa que implementa
rodrigo@ic.ufal.br 119
Teste unitário
oMuito suporte de ferramentas, frameworks
o*units
oMock objects
oObjetos falsos que facilitam o teste de um componente isoladamente
rodrigo@ic.ufal.br 120
Teste de integração
oA partir de múltiplos módulos que já foram testados com testes unitários
o Testá-los em conjunto
oGeralmente se testa a integração dos módulos
rodrigo@ic.ufal.br 121
Teste de sistema
oO sistema como um todo atende ao comportamento esperado?
oGeralmente não estamos preocupados com o que se passa “por baixo dos panos”
oDesde que o sistema se comporte como esperado
oGeralmente o teste é caixa-preta
rodrigo@ic.ufal.br 122
Outros tipos de teste
o Existem vários outros tipos de teste, mas de alguma forma eles se “encaixam” em uma das três categorias, ou tipos, de teste anteriores
oMultiple version testing
o Mesma entrada múltiplas implementações da mesma funcionalidade comparar resultados
oTeste de stress
o Teste do sistema sob condições anormais
o Pouquíssima memória, número absurdo de usuários simultâneos...
rodrigo@ic.ufal.br 123
Outros tipos de testes
o Testes aleatórios
o As entradas do caso de teste são criadas aleatoriamente, usando algum gerador de números aleatórios
o Exemplo:
o Crashme
o Testes de regressão
o Usar uma entrada que já fez o software falhar, provavelmente em produção, e construir um caso de teste que reproduza a falha.
o Assim, se o defeito for corrigido, e por alguma razão for reintroduzido no futuro, a falha será detectada pelo teste
rodrigo@ic.ufal.br 124
Quiz
o Você desenvolveu alguns novos serviços para a sua aplicação web
o Mas esses serviços serão disponibilizados somente para um subconjunto pequeno de usuários
o Você quer avaliar se as novas funcionalidades terão uma boa aceitação
o Que tipo de teste você faria?
o Integração
o Diferencial
o Aleatório
o Sistema
rodrigo@ic.ufal.br 125
Resposta
o Veja que estamos querendo avaliar as funcionalidades com um todo
oNão seria aleatório, pois não tem nenhum elemento aleatório (mais ou menos)
oNão temos múltiplas implementações de uma mesma “coisa” crítica. Logo não é diferencial
oNão estamos focados na integração entre módulos
o Por outro lado, queremos saber se o sistema se comporta como esperado, como um todo
rodrigo@ic.ufal.br 126
Outra quiz
o Temos um software bem grande pra testar
o Ele usa uma biblioteca para cálculos numéricos
oMas biblioteca se comporta mal, gerando exceções de ponto flutuante de tempos em tempos
o O fornecedor da biblioteca lançou uma nova versão
o Mas o histórico indica que quando uma nova versão é lançada, muitos novos bugs são inseridos
o Você precisa avaliar se vale a pena instalar a nova versão
rodrigo@ic.ufal.br 127
Quiz (cont.)
oQue tipo de teste você faria? (escolha somente uma)
oUnitário
oCaixa branca
oCaixa preta
oStress
rodrigo@ic.ufal.br 128
Quiz - discussão
oQualquer resposta poderia ser aceitável
oMas provavelmente você fará um teste unitário, para testar a biblioteca em isolado
oVocê poderia também usar um teste diferencial em algumas funções
oComo não falei se o código fonte estava disponível, poderia ser caixa preta ou branca
rodrigo@ic.ufal.br 129
Atitudes de um bom testador
oDesenvolvedor
o“Eu quero que esse código funcione”
o Testador
o“Eu quero fazer esse código falhar”
o Seja criativo e reflexivo
oNunca ignore algum comportamento estranho da sua aplicação
top related