testes de software - módulo 1

Post on 16-Jan-2015

835 Views

Category:

Education

6 Downloads

Preview:

Click to see full reader

DESCRIPTION

Aulas de teste de software.

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