Especificação de comandos Objectivo: O objectivo da especificação formal de comandos é a necessidade de assegurar a correcção dos comandos a desenvolver. Torna-se necessário desenvolver uma metodologia formal para a especificação. Comentário introdutório: A especificação de comandos utiliza uma notação em que os requisitos relativos aos comandos em questão se expressam formal e rigorosamente.
Especificação de comandos Definição: A especificação de um comando é uma asserção da forma: {CD} c {CO}, em que {CD} é a condição dada (ou pré-condição) e {CO} denota a condição objectivo (ou pós-condição).
Correcção parcial Definição: Se a execução de um comando c se iniciar num estado da máquina E 0, em que se verifica {CD} e se a sua execução terminar, atingir-se-á um estado E f, em que se verifica {CO} Comentário: A correcção assim definida é dita parcial, pois não é fornecida garantia de terminação.
Correcção total Definição: Correcção total = correcção parcial + garantia de terminação Garantia de terminação Definição: A garantia de terminação impõe que a execução do comando em causa deve terminar sempre que em E 0 se verifique {CD}
Especificação de comandos Exemplos de comandos a especificar Exemplo 1: Soma dos naturais de 0 a 100: U c 100 s = i=0 ou i { U} c s = i, i [ 0,100]
Especificação de comandos Exemplo 2: Factorial de um natural entre 100 e 200: { n 100, 200 } c { f = n!}
Prova de Correcção X Teste de Programas Dada a especificação de um comando c como os dos exemplos anteriores, provar a sua correcção é uma tarefa difícil e por isso, na prática, não se faz prova formal de correcção mas sim testes aos programas. Testar um programa corresponde a executá-lo com determinadas condições de entrada e analisar os resultados obtidos para verificar se estão correctos.
Teste de Programas Por mais cuidadoso que seja o processo de construção de programas é sempre possível que estes contenham falhas. Falhas são os defeitos ou incorrecções latentes nos programas Acidentes são situações que impedem o correcto funcionamento dos programas. Ex: falta de energia. Erros são consequência da existência de falhas ou acidentes Danos são os prejuízos provocados pelos erros
Teste de Programas É evidente que o controlo de falhas ou acidentes é tão mais importante quanto maiores forem os danos que podem ser causados. Assim devemos considerar uma postura defensiva ao programar procurando entre outras coisas: -prevenir os acidentes -simplificar o uso dos programas -reduzir o tempo de execução de operações críticas
Teste de Programas Testar um programa é uma das formas que devemos utilizar para verificar a sua qualidade. Mas esta depende também de outras características como a legibilidade do código, a existência de especificações adequadas, a eficiência dos algoritmos utilizados, etc... Realizando testes podemos mostrar a presença de erros mas não a sua ausência, por isso, caso não seja encontrado um erro quando realizamos um teste, isso não pode ser entendido como a não existência de falhas.
Teste de Programas Os testes devem ser projectados de forma a que tenhamos exercitado todo o código do nosso programa sem perder tempo com testes redundantes. Realizar testes é caro e demorado pelo que precisamos estabelecer um compromisso entre o custo de realizar os testes e o nível de qualidade que será necessário garantir. Necessitamos portanto de conhecer formas de projectar casos teste que nos assegurem a detecção do maior número de falhas -> Teste Sistemático
Teste de Programas Para descobrir as falhas de um programa é necessário realizar testes de forma sistemática e para isso devemos: 1- Criar instrumentação de teste 2- Projectar os casos teste utilizando um critério de selecção eficaz 3- Analisar rigorosamente os resultados obtidos 4- Identificar e eliminar cuidadosamente as falhas encontradas
Teste de Programas 1- Criar instrumentação de teste Os programas devem conter instruções especificas para auxiliar a fase de teste e depuração. Por exemplo, se quisermos testar uma função podemos criar um programa que invoque essa função com determinados valores dos seus parâmetros e, nele, incluir também instruções para imprimir, não só os valores obtidos, mas eventualmente valores intermédios que permitam avaliar o correcto funcionamento dessa função. Este código adicional é designado por instrumentação de teste
Teste de Programas 2- Projectar os casos teste utilizando um critério de selecção eficaz. Um conjunto de casos teste T diz-se completo relativamente a um determinado critério de selecção C e um dado programa P se T foi seleccionado segundo C e o conjunto exercita integralmente o programa P. Um teste bem sucedido é aquele que permite evidenciar a existência de falhas.
Teste de Programas Critério de selecção é o método utilizado para seleccionar um conjunto de casos teste. Deve ser válido e confiável. Válido: Um critério C é válido desde que, existindo alguma falha num programa P, exista pelo menos um caso teste t, em algum conjunto completo de casos teste T, seleccionado segundo C e P capaz de evidenciar o erro decorrente. Confiável: Um critério de selecção C é confiável se particionar os dados de entrada do programa P de modo que, se t pertence a uma determinada partição, qualquer caso teste t, pertencente a essa partição e seleccionado segundo C, acusará a ocorrência dos mesmos erros que o caso teste t.
Teste de Programas Teorema demonstrado por Goodenough em 77: Um conjunto completo de casos teste T, projectado para o programa P e obtido segundo um critério de selecção válido e confiável C, demonstra a correcção de P desde que T tenha fracassado. Infelizmente é muito difícil demonstrar que o critério de selecção é válido e confiável e que o conjunto de casos teste é completo.
Teste de Programas 3- Analisar rigorosamente os resultados obtidos A cada execução do programa com um dado teste t devemos examinar os resultados obtidos e verificar se eles correspondem ao esperado. Caso isso não aconteça então o caso teste teve sucesso e teremos de encontrar a falha existente.
Teste de Programas 4- Identificar e eliminar cuidadosamente as falhas encontradas Uma vez evidenciada a existência da falha é necessário olhar o código do programa e procurar perceber onde está a falha que levou ao erro. Nesta fase é muitas vezes necessário usar a instrumentação para conseguir acompanhar a execução do programa e assim identificar a origem do problema. É importante lembrar que por vezes existem várias falhas que concorrem para o erro.
Projecto de Casos Teste Os casos teste podem ser criados tendo por base o código do programa (caixa aberta) ou considerando as relações de entrada e saída (caixa preta). Nos casos teste caixa aberta procuramos assegurar que todo o código do programa seja executado no conjunto dos testes seleccionados. Os casos teste caixa preta são projectados considerando as condições de entrada e saída do programa ou módulo a testar e sem levar em conta a maneira como foi implementado.
Projecto de Casos Teste Nos casos teste caixa aberta existem várias estratégias: cobertura de instruções - todas as instruções devem ser executadas pelo menos uma vez. cobertura de arestas: neste caso, pelo menos uma vez, devem ser executadas todas as arestas de transferência de controle cobertura de decisões: neste caso, pelo menos uma vez, devem ser geradas todas as condições elementares e as suas combinações quando contidas em expressões lógicas complexas.
Projecto de Casos Teste Nos casos teste caixa aberta existem várias estratégias: cobertura de decisões em cascata: neste caso, não só temos de cobrir todas as decisões elementares e as suas combinações como todas as combinações possíveis entre expressões lógicas de todas as instruções do programa. Se existirem ciclos dentro do programa na cobertura de decisões temos também que testar cada ciclo de forma a que ele execute: 0 vezes; 1 vez; n>1 vezes e ainda todas as possíveis formas de saída do ciclo
Projecto de Casos Teste Nos casos teste caixa preta existem também várias estratégias como por exemplo: condições de contorno - procura um mínimo de casos teste tal que situações limite ou pouco frequentes sejam exercitadas (este critério é pouco sistemático pelo que deve ser usado como complemento de outros critérios) gráficos de causa efeito - neste caso é criado um gráfico onde todas as causas (dados ou condições de entrada) e efeitos (resultados produzidos) do programa aparecem representados e quais as suas relações. Depois cria-se uma tabela de decisão e sobre ela determinam-se os casos teste
Projecto de Casos Teste Caso seja necessário um elevado grau de qualidade para um programa, devemos testá-lo utilizando diversas estratégias por exemplo: 1- examinar cuidadosamente o código e argumentar sobre a sua correcção 2- aplicar testes segundo o critério de cobertura de decisões 3- acrescentar testes de condições de contorno
Conceitos a saber: Especificação de comandos Prova de correcção Teste sistemático Instrumentação de programas Projectar casos teste por cobertura de decisões e condições de contorno Depuração de programas