Prévia do material em texto
AULA 4 ENGENHARIA DE SOFTWARE Prof. Emerson Antonio Klisiewicz 02 CONVERSA INICIAL Olá, aluno. Nesta aula, vamos estudar as métricas em projetos de testes para o desenvolvimento de sistemas que também fazem parte do processo de engenharia de software. Bons estudos! CONTEXTUALIZANDO “O teste consiste em executar o programa com a intenção de encontrar erros (bugs)”, Myers, 1979. Por que temos que testar os softwares? Será que alguém se sentiria confortável, tranquilo em ser o passageiro de um avião que nunca tivesse decolado antes? Itens como qualidade de software, corretitude, confiabilidade são vitais para um software, e todos eles são construídos a partir de um excelente programa de testes. TEMA 1 – TERMINOLOGIAS 1.1 Garantia de qualidade de software É um conjunto de atividades técnicas que devem ser aplicadas durante todo o processo de desenvolvimento de um software. O objetivo é garantir que tanto o processo de desenvolvimento do software quanto o produto que será entregue tenham os padrões de qualidade especificados. 1.2 Validação Garantirá que o produto final desenvolvido corresponda plenamente aos requisitos solicitados pelo usuário. 1.3 Verificação Visa assegurar a consistência, a completude e a corretude do software desenvolvido em cada fase do projeto e entre as fases consecutivas do ciclo de vida do software. 1.4 Teste Visa garantir o funcionamento do software pelo exame do comportamento do produto por meio da sua execução. 03 1.5 Defeito Deficiência mecânica ou algorítmica encontrada no software que, se ativada, pode levar o produto a ter uma falha. 1.6 Erro É um item da informação ou estado de execução do produto de software inconsistente. 1.7 Falha É a situação encontrada em que o sistema desenvolvido viola suas especificações. TEMA 2 – DETALHANDO ITENS DA TERMINOLOGIA 2.1 Defeitos A principal causa encontrada nas ocorrências de defeitos é a tradução incorreta das informações. No projeto de desenvolvimento, quanto menor o tempo para esse defeito for revelado, menor também será o custo de correção e probabilidade da correção ocorrer de forma correta. A solução é introduzirmos pontos de verificação, validação e testes ao longo de todo o ciclo de desenvolvimento. 2.2 Teste É o processo de execução de um programa com o objetivo de revelar a presença de erros. Contribui para aumentar a confiança de que o software desempenha as funções especificadas. Deve-se ter um conjunto de passos ao qual seja possível alocar técnicas de projeto de casos de teste e estratégias de teste específicos durante o desenvolvimento. 2.3 Depuração 04 É uma situação não previsível ocorrida no teste. Depois de revelada a presença do erro, ele deve ser corrigido. O processo de depuração é a parte mais imprevisível do processo de teste. 2.4 Falha Incapacidade do software desenvolvido de realizar a função requisitada. 2.5 Erro Trata-se do estado de instabilidade. Veja, abaixo, a relação entre as questões de falhas em sistemas. O processo de teste deve ser revisto continuamente, a fim de ampliar sua atuação para possibilitar aos profissionais uma maior visibilidade e organização dos seus trabalhos, resultando em uma maior agilidade e controle operacional dos projetos de testes. Conhecendo-se o funcionamento interno de um produto, testes podem ser realizados para garantir que “todas as engrenagens”, ou seja, que a operação interna de um produto tenha um desempenho de acordo com as especificações e que os componentes internos foram adequadamente postos à prova. TEMA 3 – TÉCNICA ESTRUTURAL: CAIXA BRANCA É um método de projeto de testes que usa a estrutura de controle do projeto procedimental para derivar casos de teste. Baseia-se no exame dos detalhes procedimentais em que os caminhos do software são testados, porém não é viável testar todos os caminhos lógicos de um programa. Na Técnica de Caixa Branca, o engenheiro de software, por meio dos casos de teste, vai: Garantir que todos os caminhos lógicos, independentes do módulo, tenham sido exercitados pelo menos uma vez; Executar todas as decisões lógicas em seus lados verdadeiro e falso; 05 Executar todos os ciclos nos seus limites e dentro de seus intervalos operacionais; Executar as estruturas de dados internas. Nessa ideia, temos o Teste do Caminho Básico. Trata-se de uma técnica que vai permitir a definição de um conjunto-base de caminhos de testes a serem executados. Ele é baseado no fluxo de controle e no conceito da complexidade ciclomática. Antes, porém, vamos ver uma notação para representar o fluxo de controle. 3.1 Grafos Grafos mostram o fluxo de controle. O Nós vai representar um ou mais processos; as Arestas, o fluxo de controle do programa ou estrutura do programa. Figura 1 – Fluxo de controle A definição de regiões do grafo são áreas limitadas pelas arestas e nós. Nelas, podemos ter a seguinte notação: 06 Figura 2 – Regiões de grafo Exemplo: 3.2 Teste do caminho básico 07 Para criarmos um teste do caminho básico, precisamos executar as seguintes situações: Construir um grafo para o módulo do programa em teste; Fazer o cálculo do valor da complexidade ciclomática; Optar por um conjunto de caminhos básicos; Fazer a criação de um caso de teste para cada caminho básico; Executar todos os casos de testes. 3.2.1 Complexidade ciclomática É fundamentada na teoria dos grafos, fornecendo uma métrica de cálculo para testes muito interessante. Ela nos dá um limite de número de casos de testes que deveriam ser executados para que se garanta que cada comando/caminho de execução de um programa tenha sido passado ao menos uma vez. Isso é realmente útil para quando temos módulos com tendências maiores a erros. Ela pode ser calculada usando-se a seguinte fórmula: V(G) = E – N + 2, onde: E: número de ramos do grafo; N: número de nós do grafo. Ex.: Usando a figura abaixo, teríamos: V(G) = 17 arestas – 13 nós + 2 = 6. Portanto, a complexidade para o exemplo acima seria 6. Esse será o número de caminhos a serem seguidos pela estrutura do programa, conforme descrito abaixo: 08 Caminho 1: 1-2-10-11-13 Caminho 2: 1-2-10-12-13 Caminho 3: 1-2-3-10-11-13 Caminho 4: 1-2-3-4-5-8-9-2-... Caminho 5: 1-2-3-4-5-6-8-9-2-... Caminho 6: 1-2-3-4-5-6-7-8-9-2-... Nos caminhos 4, 5 e 6, as reticências indicam que se pode tomar qualquer caminho no restante da estrutura que não comprometerá o resultado do teste. Com isso, os testes devem ser realizados para que façam esses caminhos ao menos 1 vez. TEMA 4 – TÉCNICA FUNCIONAL: CAIXA-PRETA Primeiramente, usamos o particionamento de equivalências, técnica que se adequa aos testes com valores típicos de uma entrada em um programa. Os casos de teste são elaborados sabendo-se quais serão as entradas, de forma sistemática e direta. Para acharmos essas equivalências, siga estes passos: a. Definir as chamadas condições de entrada, qualquer intervalo de entradas válidas em um programa. Ex.: Faixa de valores 1 < CODIGO<99, vetores com X número de elementos, etc.; b. Definir as classes de equivalência, que podem ser válidas ou inválidas. São definidas pela condição de entrada. Ex: 1< CODIGO < 99 Classe válida : 1 <CODIGO< 99. Classes inválidas: CODIGO <= 1 e CODIGO >= 99; c. Para cada classe que for inválida, será criado um caso de teste. As classes declaradas válidas, os casos de teste serãogerados para atender a maior quantidade possível de entradas válidas. Exemplo: 09 Nessa técnica, podemos ter alguma dificuldade em quantificar os testes e acontecer de deixarmos partes essenciais críticas do sistema sem os devidos testes. Também podemos citar como uma dificuldade nessa técnica a questão da automatização dos testes. TEMA 5 – TEST DRIVEN DEVELOPMENT (TDD) Sobre os testes, temos uma metodologia chamada de ágil, que está crescendo no mercado em que os testes são vitais para o desenvolvimento. A Test Driven Development, ou simplesmente TDD, é um desenvolvimento guiado por testes. O primeiro livro sobre esse assunto foi escrito por Kent Beck. Trata-se de um método de desenvolvimento fácil de explicar, porém difícil de aprender, mas de retorno garantido. Essa forma de desenvolvimento deixa o código mais claro, os testes são documentações executáveis que garantem funcionalidades do domínio do problema. Nesse tipo de desenvolvimento, se algum teste parou de rodar, sabemos que algo deu errado. Isso trará economia de tempo e dinheiro em manutenção, e a escrita de testes ajuda na melhoria do design do código. Outras vantagens são: Com a utilização do método ganhando experiência, já no início da implementação de um método, o desenvolvedor poderá refletir sobre como fará para testá-lo; Ao iniciar mais cedo, os testes são feitos, aumentam as chances de que erros sejam encontrados na sua fase inicial de desenvolvimento, evitando que se espalhem pela aplicação, tornando-os mais simples de serem resolvidos. A base do TDD é a seguinte: os testes serão escritos antes do código. Ele é uma técnica para desenvolvimento de software formado por pequenas iterações para o desenvolvimento de uma nova funcionalidade, sempre iniciando pela construção do caso de teste para depois construir o código para fazer o teste passar e, finalmente, pela realização da refatoração do código visando melhorá-lo, incluindo as mudanças realizadas. O TDD vem da ideia de “test-first programming” do XP (Extreme Programming). Os passos da construção com TDD são os seguintes: a. Crie o teste; b. Compile-o e execute-o (com certeza não irá – vermelho); 010 c. Então, codifique o requisito e faça-o passá-lo pelo o teste (verde); d. Realize a refatoração do código para melhorá-lo. A metodologia TDD é conduzida por “testes do programador” ou testes unitários. É de se destacar que não se tratam dos testes de sistema nem os de homologação (feitos pelo usuário final). Siga estes princípios: 1. Construa testes isolados uns dos outros: um caso de teste não deve depender do sucesso de outro para funcionar. Deve ser possível executar um caso de testes isoladamente, sem executar nenhum outro; 2. Comece definindo uma “Test List”: de modo geral, para uma mesma classe ou método que será testado, existirão diferentes casos de teste. Devem-se listar todos primeiro; 3. Primeiro o teste: é chance de refletir sobre o projeto das classes do sistema e controlar o escopo. A codificação deve atender somente o necessário para o teste corrente; 4. Primeiro a assertiva: é necessário refletir sobre o que significará se o teste executar com sucesso antes de seguirmos adiante. 5. Dados para teste: para realizar o teste, procure não escolher números complexos caso eles não tenham algum significado para o teste. Seja simples. Não passe os mesmos valores para diferentes parâmetros. Ex.: Ao fazer o teste de um método Operacao (int x, int y), não o faça utilizando valores iguais Operacao (2,2). O método “Operacao” poderá inverter o “x” e o “y” fazendo o teste passar assim mesmo, dificultando sua análise. Procure usar informações do mundo real em seu sistema. 6. Dados com significado evidente: procurar codificar de forma explicativa (comentar), pois vale lembrar que estamos escrevendo testes para outras pessoas lerem, e não apenas para ser executados pelo computador. FINALIZANDO Qualquer conjunto de testes tem a missão de encontrar em um programa ou sistema o máximo de bugs possíveis utilizando o mínimo de esforço. Nessa aula, vimos como os testes são importantes e a existência de métodos e técnicas para que seja possível implementar um plano de testes que garanta a qualidade daquilo que se está entregando ao usuário. Os testes nunca finalizam. Mesmo após a implantação e, por consequente, seu uso pelo usuário, o sistema será 011 constantemente testado; nesse caso, pelo cliente. E ninguém deseja que ele encontre algum tipo de erro. 012 REFERÊNCIA PRESSMAN, R.; MAXIM, B. Engenharia de software: uma abordagem profissional. 8. ed. Porto Alegre: AMGH, 2016.