Exemplos de questões da prova 2 1ª. Questão ( 2 pontos ) Indique se cada afirmação abaixo é verdeira ou falsa. Justifique sua resposta. a) O CESPDIN é um exemplo de módulo de instrumentação, cujo propósito é instrumentar as funções de alocação e desalocação dinâmica de memória. Tal instrumentação permite melhorar o controle sobre os espaços de dados alocados dinamicamente em um programa. Porém, o CESPDIN não foi codificado seguindo o padrão de implementação wrapper (envelope), apresentando em sala de aula. b) O critério de seleção de casos de teste por caminhos requer a criação de uma expressão regular geradora de caminhos. Diferentemente de critérios para teste caixa preta, tal critério requer o conhecimento da implementação da função. Além disso, indepedentemente de qual seja a estrutura interna do código de uma função sendo testada, a satisfação do critério de cobertura por instrução sempre vai requerer a seleção de um conjunto mínimo de casos de teste menor do que o conjunto mínimo correspondente para o critério de seleção por caminhos. c) Assim como no caso de teste dos módulos de um programa, não é possível utilizar a técnica de argumentação para demonstrar a corretude de algoritmos que ainda não estejam implementados. 2a. questão ( 4.5 pontos ) a) Esboce o protótipo e implementação (não se preocupe com sintaxe!) de uma função ConcatenarString que realiza a concatenação de duas strings. Assuma que a estrutura de cada string no programa é definida no modelo físico abaixo. A função deve conter o código de instrumentação do controle da entrada (pré-condições, assertivas de entrada) e do resultado (pós-condições, assertivas de saída). (1.5 pontos) b) Considere agora que você está implementando um módulo de instrumentação para o módulo que contém a função ConcatenarString, seguindo o padrão de implementação wrapper (envelope), apresentando em sala de aula. Quais das assertivas, tanto aquelas mencionadas na sua resposta a questão a) como aquelas no modelo físico abaixo, deveriam ser movidas para a função correspondente ConcatenarString_Instr do módulo de instrumentação? Quais não poderiam? Justifique o por quê das suas respostas. (1 ponto) c) O objetivo do módulo de instrumentação (mencionado na questão b acima) é segregar código de instrumentação de forma a evitar o aumento da complexidade do módulo alvo sendo instrumentado. É viável realizar a instrumentação para controle de cobertura de testes por arestas da função ConcatenarString através da inclusão de marcadores de passagem no código da função ConcatenarString_Instr? Justifique sua resposta. (0.5 ponto) d) Produza o fluxograma para o código da função ConcatenarString que você apresentou na questão a). Qual é o conjunto e o número mínimo de casos de teste para satisfazer o critério de cobertura por instruções? (1 ponto) e) Tanto o conjunto quanto o número mínimo de casos de teste para satisfazer o critério de cobertura de arestas da função ConcatenarString é idêntico a resposta da questão d acima? Justifique. (0.5 ponto) pString Cabeça do string idTipo Tamanho pCorpo Corpo do string idTipo pCabeca valString Terminador Assertivas estruturais (invariante da estrutura) pString != NULL pString->idTipo == idTipoCabecaString pString->Tamanho >= 0 se pString->Tamanho == 0 => pString->pCorpo == NULL se pString->Tamanho > 0 => pString->pCorpo != NULL pString->pCorpo->idTipo == idTipoCorpoString pString->pCorpo ->pCabeca == pString (pString->pCorpo->valString)[ pString->Tamanho ] == 0 3ª. questão ( 1.5 pontos ) Examine o código a seguir. O código está sintaticamente correto. Quais seriam os casos de teste que você geraria ao utilizar um critério de geração de casos de teste baseado em cobertura de arestas. LER_tpCondRet LER_AbrirArquivoScript( char * NomeArqParm ) { strcpy( NomeArqScript , NomeArqParm ) ; if ( TST_ObterPtInicioExtensao( NomeArqScript ) == NULL ) { strcat( NomeArqScript , DEFAULT_EXT_SCRIPT ) ; } /* if */ pArqScript = fopen( NomeArqScript , "rb" ) ; if ( pArqScript != NULL ) { printf( "\n Arquivo de teste: %s\n" , NomeArqParm ) ; AcabouScript = 0 ; return LER_CondRetOK ; } /* if */ NomeArqScript[ 0 ] = 0 ; return LER_CondRetNaoAbriu ; } /* Fim função: LER &Abrir arquivo script de teste */ 4ª. Questão ( 2 pontos ) Assuma que você está tornando auto-verificável a estrutura do modelo apresentado na 2ª. Questão. Explique em linguagem natural quais seriam 7 possíveis exemplos de deturpações para testar tal estrutura auto-verificável. Dê pelo 4 exemplos de assertivas a serem implementadas em funções verificadoras que seriam úteis para detectar as faltas estruturais causadas por seus exemplos de deturpações. 1a. questão ( 3.5 pontos ) Examine o código a seguir. Assuma que ele está sintaticamente correto. Como o número de iterações do laço é finito, assuma que o testador decidiu gerar casos de teste que exercitem todos caminhos possíveis na execução da função abaixo. Responda as perguntas abaixo. void VERIFICAR_MAIOR(int x, int y) int vezes = 0; while (vezes < 3) { if( x > y ) { printf("%d eh maior que %d\n", x, y); if (x>(y+5)) printf("%d eh muito maior que %d\n", x, y); x = x - 2; A B C D E F G } else { printf("%d eh menor ou igual que %d\n", x, y); if (x<(y-5)) printf("%d eh muito menor que %d\n", x, y); y = y - 2; H I J L } if(x > y) { printf("%d ainda eh maior que %d\n", x, y); M N x = x – 2; } else { printf("%d ainda eh menor ou igual que %d\n", x, y); y = y – 2; O } vezes++; } printf("fim da comparacao – x = %d e y = %d\n", x, y); } P Q a) Apresente a expressão regular geradora de caminhos que permita identificar os casos de teste necessários para satisfação do critério de cobertura de todos caminhos. Use os rótulos (letras) associados acima a cada instrução (ou bloco de instruções) do código da função VERIFICAR_MAIOR(). (1 ponto) b) Assuma que, através do uso do módulo Conta, o programador adicionou contadores no código da função de forma a controlar exatamente a passagem por cada um dos blocos rotulados acima (isto é, as instruções/blocos representados por A, B, ..., O, P). Apresente um script de teste, utilizando os comandos de teste para análise de cobertura, que verifique a corretude da execução do caminho para o caso de teste com os valores de entrada x = 14 e y = 6. O caminho esperado para este caso de teste é ABCDEFGMNPBCDEGMNPBCHILMNPQ. (1,5 pontos) c) Revisão de código é uma técnica de controle de qualidade que visa identificar vioalações de regras e recomendações associadas com uso da linguagem, estruturação do código, políticas de nomes de elementos do programa, dentre outros. Cite e explique, pelo menos, três regras e/ou recomendações que estão sendo violadas pelo código acima. (1 ponto) 2a. questão ( 2 pontos ) Indique se cada afirmação abaixo é verdeira ou falsa. Justifique com argumentos sua resposta. a) Conforme discutido em aula, sempre que possível, conversão de tipos deve sempre ter prioridade sobre imposição de tipos em programação modular. No entanto, somente é possível usar imposição de tipos em módulos que usam os módulos genéricos Lista e Arvore implementados no arcabouço de testes da disciplina. b) O CESPDIN é um exemplo de módulo de instrumentação, cujo propósito é instrumentar as funções de alocação e desalocação dinâmica de memória. Tal instrumentação permite melhorar o controle sobre os espaços de dados alocados dinamicamente em um programa. O CESPDIN foi codificado seguindo o padrão de implementação wrapper (envelope), apresentado em sala de aula. Isso significa que as funções de cada módulo instrumentado (com uso do CESPDIN) não precisam ser alteradas para realização de controle de tipos dos espaços de dados alocados. c) O critério de seleção de casos de teste por caminhos requer a criação de uma expressão regular geradora de caminhos. Diferentemente de critérios para teste caixa preta, tal critério requer: (i) o conhecimento da implementação da função, e (ii) é um dos critérios de seleção mais rigorosos. Porém, nem sempre a satisfação do critério de cobertura por caminhos vai requerer a seleção de um conjunto mínimo de casos de teste maior do que o conjunto mínimo correspondente para o critério de seleção por arestas. d) Inspeção de código é uma técnica de controle de qualidade que pode (e deve) ser empregada antes e após os testes. 3a. questão ( 4.5 pontos ) a) Esboce o protótipo e implementação (não se preocupe com sintaxe!) de uma função ConcatenarString que realiza a concatenação de duas strings. Assuma que a estrutura de cada string no programa é definida no modelo físico abaixo. A função deve conter o código de instrumentação do controle da entrada (pré-condições, assertivas de entrada) e do resultado (pós-condições, assertivas de saída). (1.5 pontos) b) Considere agora que você está implementando um módulo de instrumentação para o módulo que contém a função ConcatenarString, seguindo o padrão de implementação wrapper (envelope), apresentando em sala de aula. Quais das assertivas, tanto aquelas mencionadas na sua resposta a questão a) como aquelas no modelo físico abaixo, deveriam ser movidas para a função correspondente ConcatenarString_Instr do módulo de instrumentação? Quais não poderiam? Justifique o por quê das suas respostas. (1 ponto) c) O objetivo do módulo de instrumentação (mencionado na questão b acima) é segregar código de instrumentação de forma a evitar o aumento da complexidade do módulo alvo sendo instrumentado. É viável realizar a instrumentação para controle de cobertura de testes por arestas da função ConcatenarString através da inclusão de marcadores de passagem no código da função ConcatenarString_Instr? Justifique sua resposta. (0.5 ponto) d) Assuma que você está tornando auto-verificável a estrutura do modelo abaixo. Explique em linguagem natural quais seriam 5 possíveis exemplos de deturpações para testar tal estrutura auto-verificável. Dê, pelo menos, 3 exemplos de assertivas a serem implementadas em funções verificadoras que seriam úteis para detectar as faltas estruturais causadas por seus exemplos de deturpações. (1.5 pontos) pString Cabeça do string idTipo Tamanho pCorpo Corpo do string idTipo pCabeca valString Terminador Assertivas estruturais (invariante da estrutura) pString != NULL pString->idTipo == idTipoCabecaString pString->Tamanho >= 0 se pString->Tamanho == 0 => pString->pCorpo == NULL se pString->Tamanho > 0 => pString->pCorpo != NULL pString->pCorpo->idTipo == idTipoCorpoString pString->pCorpo ->pCabeca == pString (pString->pCorpo->valString)[ pString->Tamanho ] == 0 Esboce a função de criação de um string CriarString segundo o modelo abaixo (não se preocupe com sintaxe!). A função deve conter o código de instrumentação do controle da entrada (pré-condições, assertivas de entrada) e do resultado (pós-condições, assertivas de saída). pString Cabeça do string idTipo Tamanho pCorpo Corpo do string idTipo pCabeca valString Terminador Assertivas estruturais (invariante da estrutura) pString != NULL pString->idTipo == idTipoCabecaString pString->Tamanho >= 0 se pString->Tamanho == 0 => pString->pCorpo == NULL se pString->Tamanho > 0 => pString->pCorpo != NULL pString->pCorpo->idTipo == idTipoCorpoString pString->pCorpo ->pCabeca == pString (pString->pCorpo->valString)[ pString->Tamanho ] == 0 Examine o código a seguir. O código está sintaticamente correto. Quais seriam os casos de teste que você geraria ao utilizar um critério de geração de casos de teste baseado em cobertura de arestas. LER_tpCondRet LER_AbrirArquivoScript( char * NomeArqParm ) { strcpy( NomeArqScript , NomeArqParm ) ; if ( TST_ObterPtInicioExtensao( NomeArqScript ) == NULL ) { strcat( NomeArqScript , DEFAULT_EXT_SCRIPT ) ; } /* if */ pArqScript = fopen( NomeArqScript , "rb" ) ; if ( pArqScript != NULL ) { printf( "\n Arquivo de teste: %s\n" , NomeArqParm ) ; AcabouScript = 0 ; return LER_CondRetOK ; } /* if */ NomeArqScript[ 0 ] = 0 ; return LER_CondRetNaoAbriu ; } /* Fim função: LER &Abrir arquivo script de teste */ Um verificador de estruturas de dados é um conjunto de uma ou mais funções especificamente desenvolvidas para verificar se as estruturas de dados satisfazem as suas assertivas estruturais. Responda: a) dê 5 exemplos de funções verificadoras para um módulo que implementa uma estrutura genérica de árvores (como a utilizada no trabalho 1). b) porquê é difícil testar a corretude de funções verificadoras? c) dê um exemplo de deturpações para testar cada uma das 5 funções verificadoras mencionadas na questão 3a. Questão a) Qual é a finalidade da instrumentação de programas? Como redigir a instrumentação de tal forma que ela seja facilmente retirada do módulo alvo? b) Como testar um validador de estruturas de dados? Não esqueça de dar um exemplo, de preferência usando elementos do quarto trabalho como ilustração. Sobre o padrão Adaptador ou Envelope (Adapter ou Wrapper): explique porque ele também é útil em programação modular baseada na linguagem C. Dê dois exemplos concretos de instâncias de uso deste padrão, se possível casos utilizados durante os trabalhos da disciplina. Existem diversas formas de implementar uma lista: • lista armazenada em um vetor, • lista encadeada residente em memória, • lista capaz de ser armazenada em algum arquivo (persistência) sendo que somente a parte dos nós precisa estar em memória física. Esboce a interface de um iterador capaz de percorrer os elementos de uma lista, encapsulando a organização interna das diversas implementações. Considere esta uma função de ordenação (fornecida abaixo) baseada no método da bolha (do inglês, bubble sort). Descreva as assertivas AE, AS, AINV. void bubble( int v[], int qtd ) { int i; int j; int aux; int k = qtd - 1; for (i= k; i >= 1; i--) { for(j = 0; j < k; j++) { if(v[j] > v[j+1]) { aux = v[j]; v[j] = v[j+1]; v[j+1]=aux; } } } } Mostre, passo a passo, como utilizar assertivas na construção do módulo implementando o tipo abstrato Lista. Uma lista genérica e paginada é uma lista em que cada nó pode conter um valor de um determinado tipo, mas nós sucessivos podem conter tipos diferentes. Os valores podem ser de tamanhos altamente variáveis. Além disso, a lista paginada armazena os nós em páginas de tamanho constante, procurando sempre maximizar o número de nós por página. Mostre, passo a passo, como utilizar assertivas na construção do módulo implementando o tipo abstrato Lista genérica paginada. É dado um arquivo de texto de entrada contendo 0 ou mais linhas, e 0 ou mais palavras por linha. Projete um algoritmo para gerar um arquivo de texto de saída, contendo 0 ou mais linhas, onde o número de palavras é o maior possível tal que o tamanho de cada linha não ultrapasses o valor TamLinha. As palavras no arquivo de saída devem estar na mesma ordem que as palavras do arquivo de entrada. Considere um único branco entre palavras consecutivas de uma mesma linha. Assuma que você dispõe de uma biblioteca contendo as operações: • ObterPrimeiraPalavra, ObterProximaPalavra, ExistePalavra • IniciarSaida, RegistrarPalavra • Especifique completamente as funções da função geradora parcialmente identificada acima (tem somente uma!) e complete com os elementos em falta. • Discuta os critérios de estruturação tendo por exemplo este algoritmo. Os exemplos devem ilustrar e justificar conjuntos de solução que satisfazem e que não satisfazem estes critérios. • Descreva e justifique o estado de cada uma das repetições contidos neste algoritmo. Descreva o processo de projeto e implementação de um módulo. Ilustre este processo mostrando, passo a passo, como você projetaria um módulo para operar com n listas. Não deixe dúvidas quanto ao conteúdo dos módulos de definição e de implementação. Justifique as escolhas, baseando-se em critérios de qualidade estrutural (coesão e estrutura de controle). Obs. concentre-se no projeto, não no código. O que interessa é saber se você entendeu o processo de projeto de um módulo! ----------------------------- Um documento é formado um ou mais parágrafos. Parágrafos podem ser usados tanto para textos como para títulos. Cada tipo de parágrafo define uma formatação específica para o texto que contém. Os atributos e operadores de formatação de cada tipo de parágrafo são sempre os mesmos e são definidos em um descritor (struct) de formato de parágrafo. O texto de um parágrafo é formado por um marcador de início, uma ou mais linhas, cada qual contendo um string de zero ou mais caracteres, e um marcador de fim de parágrafo. Por exemplo, um parágrafo tipo X inicia com o marcador <X>, segue-se o texto do parágrafo e termina com o marcador </X>. No interior do texto de um parágrafo podem aparecer notas de rodapé, identificados por <NRP>texto da nota</NRP>. 1a. questão (2 pontos) Produza um modelo de dados físico auto-verificável para a estrutura de um documento. Não esqueça as assertivas! 2a. questão (2 pontos) Quais são os critérios que você utilizaria para verificar se o modelo é de fato auto-verificável? 3ª. Questão (2 pontos) Descreva como você geraria a partir do modelo da primeira questão os casos de teste úteis, utilizando o critério Cobertura de Estrutura de Dados (teste de estruturas de dados). Mostre, através de um exemplo, como você geraria 3 casos de teste úteis, envolvendo parágrafos. 4ª. Questão (2 pontos) Como redigir e qual a finalidade da instrumentação de programas? Como testar um validador de estruturas de dados? Não esqueça de dar um exemplo. 5ª. Questão (2 pontos) Crie a estrutura de decomposição sucessiva da função inserir aresta desenvolvida no trabalho 4, apresentando os conceitos de componente concreto, componente abstrato, conjunto solução, ortogonalidade, necessidade e suficiência. Inclua os contadores nesta função segundo o padrão de completeza "cobertura de arestas". Escreva um ou mais scripts de teste capazes de verificar a cobertura dos testes. pString Cabeça do string idTipo Tamanho pCorpo Corpo do string idTipo pCabeca valString Terminador Assertivas estruturais (invariante da estrutura) pString != NULL pString->idTipo == idTipoCabecaString pString->Tamanho >= 0 se pString->Tamanho == 0 => pString->pCorpo == NULL se pString->Tamanho > 0 => pString->pCorpo != NULL pString->pCorpo->idTipo == idTipoCorpoString pString->pCorpo ->pCabeca == pString (pString->pCorpo->valString)[ pString->Tamanho ] == 0 1a. questão ( 2 pontos ) Esboce a função de criação de um string CriarString segundo o modelo acima (não se preocupe com sintaxe!). A função deve conter o código de instrumentação do controle da entrada (pré-condições, assertivas de entrada) e do resultado (pós-condições, assertivas de saída). 2a. questão ( 2 pontos ) Utilizando o arcabouço de teste, mostre como você mediria a completeza do teste da função CriarString utilizando o critério cobertura de arestas. 3a. questão ( 2 pontos ) Por que devemos utilizar critérios de verificação da decomposição ao projetarmos artefatos? Descreva três critérios que impactam diretamente a confiabilidade do artefato. 4a. questão ( 2 pontos ) Esboce o deturpador do corpo do string segundo o modelo acima. 5a. questão ( 2 pontos ) Que critério você utilizaria para escolher os casos de teste da função CriarString? Por que este critério? Liste 6 casos de teste segundo este critério.