Teste Estrutural Arndt von Staa Departamento de Informática PUC-Rio Outubro 2008
Especificação <ul><li>Objetivo desse módulo </li></ul><ul><ul><li>Apresentar os conceitos de teste estrutural visando o te...
Sumário <ul><li>Critérios de valoração </li></ul><ul><li>Princípios de teste estrutural </li></ul><ul><li>Teste de unidade...
Critérios de seleção <ul><li>Caixa fechada : dependem exclusivamente da especificação </li></ul><ul><li>Caixa aberta : dep...
Critérios de valoração <ul><li>Ao testar uma comparação  a <= b , escolha sempre os três casos: </li></ul><ul><ul><ul><li>...
Critérios de valoração <ul><li>Caso listas de  strings  sejam ordenadas precisa testar a  sensibilidade dos caracteres  na...
Critérios de valoração <ul><li>Qual a relação:  José ? JOSÉ ? JOSE ? jÓsÉ </li></ul><ul><ul><li>cada caractere tem um valo...
Critérios de valoração: tabela ISO / ASCII <ul><li>0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F </li></ul><ul><li>2  !  ...
Critérios de valoração: equalização de chars <ul><li>static const char ConversionTable[ ] =  // ISO ASCII Latin, idiom: po...
Critérios de valoração <ul><li>Cada elemento de uma  enumeração  deve ser testado </li></ul><ul><ul><li>caracteres são enu...
Critérios de valoração <ul><li>Ao testar  valores de tamanho variável </li></ul><ul><ul><ul><li>por exemplo: arquivos, vet...
Critérios de valoração <ul><li>Ao  acessar valores pertencentes a um conjunto   dinamicamente criado , considere sempre </...
Critérios de valoração <ul><li>Ao  procurar elementos pertencentes a conjuntos   </li></ul><ul><ul><li>o elemento inexiste...
Critérios de valoração <ul><li>Ao testar  nomes de arquivos </li></ul><ul><ul><li>nome ( string ) nulo </li></ul></ul><ul>...
Critérios de valoração <ul><li>Caso existam, as  relações inversas foram exploradas  nos testes? </li></ul><ul><ul><li>iss...
Critérios de valoração <ul><li>Os valores estão em conformidade com um  formato especificado  (ou sub-entendido)? </li></u...
Critérios de valoração <ul><li>Os valores estão ordenados (ou não) conforme especificado? </li></ul><ul><li>O domínio dos ...
Critérios de valoração <ul><li>Todos os atributos e referências dos objetos alterados devem ser verificados </li></ul><ul>...
Critérios de valoração <ul><li>Podem-se definir mais padrões de valoração </li></ul><ul><ul><li>crie e mantenha um “ manua...
Teste de unidade <ul><li>Objetivos </li></ul><ul><ul><li>verificar se cada função ou método  realiza o que se espera </li>...
Teste de unidade <ul><li>De maneira geral,  conhecida a interface da unidade  a testar, cria-se um  módulo de controle de ...
Teste de unidade :  exemplo de arcabouço de apoio ao teste
Critérios de teste estrutural <ul><li>Critérios  </li></ul><ul><ul><li>todas instruções  todos nós [Delamaro et al, 2007] ...
Grafo da estrutura do código <ul><li>Processo genérico para gerar massas de teste: </li></ul><ul><ul><li>criar o  grafo da...
Grafo da estrutura do código: exemplo <ul><li>01 STR_CString ::  </li></ul><ul><li>02 STR_CString( long idStringParm ) </l...
Grafo da estrutura do código: exemplo <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr ) ...
Grafo da estrutura do código: exemplo <ul><li>51 void STR_CString ::  </li></ul><ul><li>52 BuildString( const int  LengthP...
Grafo da estrutura do código: exemplo <ul><li>71 char * STR_CString ::  </li></ul><ul><li>72 GetStringAddress( long idStri...
Arrasto <ul><li>Como testar repetições? </li></ul><ul><li>O custo do teste cresce com o  número de iterações </li></ul><ul...
Arrasto <ul><li>Arrasto   </li></ul><ul><ul><li>é o  maior dos menores  números de iterações necessárias para que todas as...
Arrasto: exemplos <ul><li>for ( i = 0 ; i < 10 ; i++ ) ... </li></ul><ul><li>for ( pElem = pOrg ; pElem != NULL ; pElem = ...
Arrasto <ul><li>O arrasto é o  número mínimo de iterações  a realizar para que todos os valores que possam ser modificados...
Critério de cobertura de instruções <ul><li>Cobertura de  instruções  ( todos os nós ) </li></ul><ul><ul><li>Cada  instruç...
Critério de cobertura de instruções: exemplo <ul><li>71 char * STR_CString ::  </li></ul><ul><li>72 GetStringAddress( long...
Critério de cobertura de arestas <ul><li>Cobertura de  arestas </li></ul><ul><ul><li>Cada  aresta é percorrida pelo menos ...
Critério de cobertura de arestas: exemplo <ul><li>71 char * STR_CString ::  </li></ul><ul><li>72 GetStringAddress( long id...
Critério de cobertura de condições <ul><li>Cobertura de arestas mais: </li></ul><ul><ul><li>cada expressão é testada de ta...
Teste de funções encapsuladas <ul><li>Funções encapsuladas ( static  no módulo,  private ,  protected ) não são acessíveis...
Teste de funções encapsuladas: exemplo <ul><li>01 STR_CString ::  </li></ul><ul><li>02 STR_CString( long idStringParm ) </...
Teste de funções encapsuladas: exemplo <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr )...
Teste de funções encapsuladas: exemplo <ul><li>51 void STR_CString ::  </li></ul><ul><li>52 BuildString( const int  Length...
Teste de funções encapsuladas: exemplo <ul><li>71 char * STR_CString ::  </li></ul><ul><li>72 GetStringAddress( long idStr...
Critério cobertura de caminhos <ul><li>Um  caminho  (ou arco de execução) corresponde a uma seqüência de execução das inst...
Cobertura de caminhos <ul><li>A cobertura de caminhos tende a levar a uma  explosão combinatória </li></ul><ul><ul><li>o n...
Cobertura de caminhos <ul><li>O critério cobertura de caminhos seleciona um conjunto de caminhos </li></ul><ul><ul><li>cad...
Cobertura de caminhos: exemplo de seleção <ul><li>71 char * STR_CString ::  </li></ul><ul><li>72 GetStringAddress( long id...
Cobertura de caminhos <ul><li>Processo de geração da lista de caminhos a testar </li></ul><ul><ul><li>a partir de um  diag...
Cobertura de caminhos <ul><li>Cálculo da expressão algébrica dos caminhos  </li></ul><ul><ul><li>rotulam-se os blocos e in...
Cobertura de caminhos <ul><li>// (A) Intercalar arquivos </li></ul><ul><li>// (B) Abrir arquivos </li></ul><ul><li>// (E) ...
Cobertura de caminhos <ul><li>Com a expressão  A B C E [ 3 F ( G | H | I ) ] D c ria-se a  lista dos caminhos a testar , u...
Transformação em caso de teste úteis Os casos gerados foram casos de teste abstratos
Transformação em caso de teste úteis <ul><li>Casos de teste valorados determinam  os valores e coman-dos a serem utilizado...
Transformação em caso de teste úteis <ul><li>Casos de teste úteis estabelecem os  resultados esperados  em função dos dado...
Transformação em caso de teste úteis <ul><li>Dica para automação </li></ul><ul><ul><li>criar todos os arquivos requeridos ...
Exemplo de roteiro de teste <ul><li>Um  roteiro de teste  estabelece um  cenário de teste  e fornece uma série de  instruç...
Problema do teste caixa aberta <ul><li>O grande problema do teste caixa aberta é a  explosão de casos de teste </li></ul><...
Fluxo de dados <ul><li>Método de teste fluxo de dados tende a ser uma  forma de inspecionar  caminhos  a fim de identifica...
Fluxo de dados <ul><li>Dados são sujeitos às seguintes operações: </li></ul><ul><ul><li>D  - definição: declaração, constr...
Fluxo de dados <ul><ul><li>a  = expressão </li></ul></ul><ul><ul><ul><li>todas as variáveis da expressão são do gênero  uc...
Fluxo de dados <ul><ul><li>while ( exp ) </li></ul></ul><ul><ul><ul><li>todas as variáveis em exp são do gênero  Up </li><...
Fluxo de dados: conversão para caminhos <ul><li>Todas as definições </li></ul><ul><ul><li>exercitar cada uma das definiçõe...
Fluxo de dados: inspeção <ul><li>Seqüências envolvendo pares: </li></ul><ul><ul><li>DU - vale </li></ul></ul><ul><ul><li>U...
Fluxo de dados: inspeção <ul><li>Seqüências envolvendo estado indefinido: </li></ul><ul><ul><li>*L - erro, não definida e ...
Fluxo de dados: exemplo grafo de código
Fluxo de dados:  inspeção  envolvendo x *DcDU* *DcU*
Fluxo de dados: inspeção envolvendo z *LU UD * *LU D * *LL DUUD * *LL DUD *
Fluxo de dados: inspeção  <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr ) </li></ul><u...
Teste de exceções <ul><li>Quando usar exceções? </li></ul><ul><ul><li>abordagem ortodoxa : somente quando ocorre uma situa...
<ul><li>Projetar para  testabilidade </li></ul><ul><ul><li>estabeleça um padrão de implementação para exceções </li></ul><...
Teste de exceções
Teste de exceções <ul><li>Como testar exceções? </li></ul>
Teste de exceções: instrumentação Forçar ocorrência de erro
Teste de exceções: arcabouço teste C++ <ul><li>== Add numbers of different size, should generate loss of data </li></ul><u...
Teste de exceções <ul><li>Assegurar que  </li></ul><ul><ul><li>cada  throw  foi executado pelo menos uma vez no conjunto d...
Teste de exceções: análise estática <ul><li>Cria-se o grafo de estrutura do código completo: </li></ul><ul><ul><li>procure...
Recursos locais e exceções <ul><li>Recursos locais e exceções </li></ul><ul><ul><li>ao terminar um método através de uma e...
Recursos locais e exceções <ul><li>Solução Java:  </li></ul><ul><li>use a construção  try{ ... } finally{ ... }   </li></u...
Recursos locais e exceções <ul><li>Solução C++:  </li></ul><ul><ul><li>use  objetos locais  ao invés de referências para o...
Recursos locais e exceções <ul><li>#include <stdio.h> </li></ul><ul><li>class CRecurso { </li></ul><ul><li>public: int X ;...
Módulos dublê <ul><li>Módulo dublê  ( test double , analogia:  stunt double ) é um módulo que toma o lugar de outro durant...
Módulos dublê: exemplo de enchimento <ul><li>int F( int ParametroX ) { return 10 ; } </li></ul><ul><li>int G( int Parametr...
Módulos dublê: módulos de imitação <ul><li>Quando utilizar módulos (objetos) de imitação? </li></ul><ul><ul><li>o objeto r...
Módulos dublê: módulos de imitação <ul><li>Exemplo </li></ul><ul><li>public void testProcurarPedido( ) </li></ul><ul><li>{...
Módulos dublê: módulos de imitação void * CED_Malloc( size_t Tamanho , int Linha , char * NomeArquivo ) { tpElemListaEspac...
Módulos dublê: módulos de imitação <ul><li>public interface Ambiente { </li></ul><ul><li>public long getTime( ) ;  </li></...
Módulos dublê: módulos de imitação <ul><li>public class OrderEasyTester extends TestCase {  </li></ul><ul><li>private stat...
Módulos dublê: módulos de imitação <ul><li>Existem diversas bibliotecas MockObject disponíveis </li></ul><ul><ul><li>http:...
Referências bibliográficas <ul><li>Beck, K.;  Test-Driven Development by Example ; Reading, Massachusetts: Addison-Wesley;...
<ul><li>FIM </li></ul>
Upcoming SlideShare
Loading in...5
×

Teste Estrutural

2,311

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,311
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
74
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Teste Estrutural

  1. 1. Teste Estrutural Arndt von Staa Departamento de Informática PUC-Rio Outubro 2008
  2. 2. Especificação <ul><li>Objetivo desse módulo </li></ul><ul><ul><li>Apresentar os conceitos de teste estrutural visando o teste de unidades. </li></ul></ul><ul><li>Justificativa </li></ul><ul><ul><li>O teste estrutural é utilizado tipicamente para testar módulos e classes e, assim, verificar se os componentes elementares possuem o nível de qualidade necessário. </li></ul></ul>
  3. 3. Sumário <ul><li>Critérios de valoração </li></ul><ul><li>Princípios de teste estrutural </li></ul><ul><li>Teste de unidades </li></ul><ul><li>Grafo da estrutura do código </li></ul><ul><li>Arrasto </li></ul><ul><li>Critérios de cobertura </li></ul><ul><li>Teste de funções encapsuladas </li></ul><ul><li>Critério cobertura de caminhos </li></ul><ul><li>Critério fluxo de dados </li></ul><ul><li>Teste de exceções </li></ul><ul><li>Análise estática </li></ul><ul><li>Recursos locais </li></ul><ul><li>Módulos dublê </li></ul>
  4. 4. Critérios de seleção <ul><li>Caixa fechada : dependem exclusivamente da especificação </li></ul><ul><li>Caixa aberta : dependem da estrutura do código executável </li></ul><ul><li>Caixa entre-aberta : usualmente dependem da estrutura dos dados mas não do código executável </li></ul><ul><li>Geração : criação (manual ou não) sistemática da massa de testes </li></ul><ul><li>Geração automatizada : criação da massa de testes por intermédio de um programa </li></ul><ul><li>Teste : execução (manual ou não) da massa de testes </li></ul><ul><li>Teste automatizado : execução da massa de teste sem intervenção humana </li></ul>
  5. 5. Critérios de valoração <ul><li>Ao testar uma comparação a <= b , escolha sempre os três casos: </li></ul><ul><ul><ul><li>a = b –  </li></ul></ul></ul><ul><ul><ul><li>a = b </li></ul></ul></ul><ul><ul><ul><li>a = b +  </li></ul></ul></ul><ul><ul><li> é o menor valor possível que torne verdadeira a relação a +  >= b quando for verdadeira a relação a < b . </li></ul></ul><ul><ul><ul><li>para valores inteiros  é 1 . </li></ul></ul></ul><ul><ul><ul><li>para valores vírgula flutuante </li></ul></ul></ul><ul><ul><ul><ul><li>erro absoluto : </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>a –  <= b <= a +  </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>depende da magnitude de a e b </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><li>erro relativo : </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>1 –  <= b / a <= 1 +  </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>independe da magnitude </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li> pode ser o número de algarismos significativos desejado </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>procure usar sempre que possível erro relativo ao testar </li></ul></ul></ul></ul></ul>
  6. 6. Critérios de valoração <ul><li>Caso listas de strings sejam ordenadas precisa testar a sensibilidade dos caracteres nas diferentes posições: primeiro, segundo, meio, penúltimo, último </li></ul><ul><li>Para caracteres temos os problemas </li></ul><ul><ul><li>descontinuidade dos valores numéricos </li></ul></ul><ul><ul><ul><li>caracteres ASCII minúsculos, maiúsculos e diacríticos estão em regiões diferentes </li></ul></ul></ul><ul><ul><li>vários caracteres diferentes representarem o mesmo caractere de comparação </li></ul></ul><ul><ul><ul><li>a == A == á == à == â == ã == ä == ... </li></ul></ul></ul><ul><ul><li>ASCII e Unicode são diferentes </li></ul></ul>
  7. 7. Critérios de valoração <ul><li>Qual a relação: José ? JOSÉ ? JOSE ? jÓsÉ </li></ul><ul><ul><li>cada caractere tem um valor numérico e a comparação simples utiliza esse valor </li></ul></ul><ul><ul><ul><li>strcmp e memcmp </li></ul></ul></ul><ul><ul><ul><li>Jóse > Jose [ ó > o ] ; jóse > Jose [ j > J ] </li></ul></ul></ul><ul><li>Onde fica o caractere Euro: € na tabela Unicode? </li></ul><ul><ul><li>Em ASCII latin é 80 hexadecimal ou 128 decimal </li></ul></ul>
  8. 8. Critérios de valoração: tabela ISO / ASCII <ul><li>0 1 2 3 4 5 6 7 8 9 A B C D E F </li></ul><ul><li>2 ! &quot; # $ % & ' ( ) * + , - . / </li></ul><ul><li>3 0 1 2 3 4 5 6 7 8 9 : ; < = > ? </li></ul><ul><li>4 @ A B C D E F G H I J K L M N O </li></ul><ul><li>5 P Q R S T U V W X Y Z [ ] ^ _ </li></ul><ul><li>6 ` a b c d e f g h i j k l m n o </li></ul><ul><li>7 p q r s t u v w x y z { | } ~  </li></ul><ul><li>8 €  ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ  Ž  </li></ul><ul><li>9  ‘ ’ “ ” • – — ˜ ™ š › œ  ž Ÿ </li></ul><ul><li>A   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ </li></ul><ul><li>B ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ </li></ul><ul><li>C À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï </li></ul><ul><li>D Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß </li></ul><ul><li>E à á â ã ä å æ ç è é ê ë ì í î ï </li></ul><ul><li>F ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ </li></ul>parte ASCII parte ISO
  9. 9. Critérios de valoração: equalização de chars <ul><li>static const char ConversionTable[ ] = // ISO ASCII Latin, idiom: portuguese </li></ul><ul><li>{ </li></ul><ul><li>// 0 1 2 3 4 5 6 7 8 9 A B C D E F </li></ul><ul><li>/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', 0, 0, ' ', 0, 0, </li></ul><ul><li>/*1*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, </li></ul><ul><li>/*2*/ ' ', '!','&quot;', '#', '$', '%', '&',''', '(', '}', '*', '+', ',', '-', '.', '/', </li></ul><ul><li>/*3*/ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', </li></ul><ul><li>/*4*/ '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', </li></ul><ul><li>/*5*/ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[','apos;, ']', '^', '_', </li></ul><ul><li>/*6*/ ''', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', </li></ul><ul><li>/*7*/ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0, </li></ul><ul><li>/*8*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, </li></ul><ul><li>/*9*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, </li></ul><ul><li>/*A*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, </li></ul><ul><li>/*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, </li></ul><ul><li>/*C*/ 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 0, 0, </li></ul><ul><li>/*D*/ 0, 'n', 'o', 'o', 'o', 'o', 'o', 0, 0, 'u', 'u', 'u', 'u', 0, 0, 0, </li></ul><ul><li>/*E*/ 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 0, 0, </li></ul><ul><li>/*F*/ 0, 'n', 'o', 'o', 'o', 'o', 'o', 0, 0, 'u', 'u', 'u', 'u', 0, 0, 0 </li></ul><ul><li>} ; </li></ul><ul><li>for ( i == 0 ; i < len ; i++ ) // assumindo que o tamanho seja igual </li></ul><ul><li>{ </li></ul><ul><li>if ( ConversionTable[ strA[ i ]] < ConversionTable[ strB[ i ]] ) return IS_LESS ; </li></ul><ul><li>if ( ConversionTable[ strA[ i ]] > ConversionTable[ strB[ i ]] ) return IS_GREATER ; </li></ul><ul><li>} </li></ul><ul><li>return IS_EQUAL ; </li></ul>
  10. 10. Critérios de valoração <ul><li>Cada elemento de uma enumeração deve ser testado </li></ul><ul><ul><li>caracteres são enumerações </li></ul></ul><ul><ul><li>dependendo do caso pode-se simplificar </li></ul></ul><ul><ul><ul><li>testando intervalos 'a' <= ch <= 'z‘ </li></ul></ul></ul><ul><ul><ul><ul><li>mas... veja a tabela anterior </li></ul></ul></ul></ul><ul><ul><li>listas de estados da União são enumerações </li></ul></ul><ul><ul><ul><li>testar encontrar </li></ul></ul></ul><ul><ul><ul><li>testar não encontrar </li></ul></ul></ul>
  11. 11. Critérios de valoração <ul><li>Ao testar valores de tamanho variável </li></ul><ul><ul><ul><li>por exemplo: arquivos, vetores, strings </li></ul></ul></ul><ul><ul><li>gere casos de teste para </li></ul></ul><ul><ul><ul><li>tamanho zero </li></ul></ul></ul><ul><ul><ul><li>tamanho mínimo-1 , caso exista limite inferior </li></ul></ul></ul><ul><ul><ul><li>tamanho mínimo </li></ul></ul></ul><ul><ul><ul><li>tamanho médio </li></ul></ul></ul><ul><ul><ul><li>tamanho máximo </li></ul></ul></ul><ul><ul><ul><li>tamanho máximo+1 </li></ul></ul></ul>
  12. 12. Critérios de valoração <ul><li>Ao acessar valores pertencentes a um conjunto dinamicamente criado , considere sempre </li></ul><ul><ul><ul><li>conjunto vazio </li></ul></ul></ul><ul><ul><ul><li>conjunto contendo exatamente um elemento </li></ul></ul></ul><ul><ul><ul><li>e conjunto contendo três ou mais elementos </li></ul></ul></ul><ul><ul><li>acesse </li></ul></ul><ul><ul><ul><li>o primeiro elemento </li></ul></ul></ul><ul><ul><ul><li>um elemento mais ou menos no meio do conjunto </li></ul></ul></ul><ul><ul><ul><li>o último elemento </li></ul></ul></ul>
  13. 13. Critérios de valoração <ul><li>Ao procurar elementos pertencentes a conjuntos </li></ul><ul><ul><li>o elemento inexistente imediatamente anterior ao primeiro </li></ul></ul><ul><ul><ul><li>em um conjunto ordenado deve ser possível gerar um valor anterior ao primeiro elemento </li></ul></ul></ul><ul><ul><li>o primeiro elemento </li></ul></ul><ul><ul><li>o elemento inexistente entre o primeiro e o segundo </li></ul></ul><ul><ul><ul><li>segundo a ordem de procura do algoritmo empregado </li></ul></ul></ul><ul><ul><li>um elemento mais ou menos no meio do conjunto </li></ul></ul><ul><ul><li>um elemento inexistente mais ou menos no meio do conjunto </li></ul></ul><ul><ul><li>o elemento inexistente entre o penúltimo e o último </li></ul></ul><ul><ul><li>o último elemento </li></ul></ul><ul><ul><li>o elemento inexistente imediatamente após ao último </li></ul></ul>
  14. 14. Critérios de valoração <ul><li>Ao testar nomes de arquivos </li></ul><ul><ul><li>nome ( string ) nulo </li></ul></ul><ul><ul><li>nomes com caracteres ilegais, ex.: ? * / < > &quot; | </li></ul></ul><ul><ul><li>sempre para os casos existe e não existe </li></ul></ul><ul><ul><ul><li>nome sem extensão </li></ul></ul></ul><ul><ul><ul><li>nome com extensão igual ao default </li></ul></ul></ul><ul><ul><ul><li>nome com extensão diferente do default </li></ul></ul></ul><ul><ul><ul><li>nome com duas extensões (ex. xpto.x.y) </li></ul></ul></ul><ul><ul><ul><li>nome com diretório absoluto </li></ul></ul></ul><ul><ul><ul><li>nome com diretório relativo </li></ul></ul></ul>
  15. 15. Critérios de valoração <ul><li>Caso existam, as relações inversas foram exploradas nos testes? </li></ul><ul><ul><li>isso pode ser generalizado para redundâncias judiciosamente inseridas no código </li></ul></ul><ul><li>Caso existam, formas de calcular alternativas foram utilizadas como oráculos? </li></ul><ul><ul><li>trata-se aqui de redundância de forma de calcular </li></ul></ul><ul><li>Foram forçadas as ocorrências das condições de erro ? </li></ul><ul><ul><li>foram exercitados todos os throw , condições de retorno e mensagens de erro? </li></ul></ul><ul><li>As características de desempenho estão dentro dos limites estabelecidos? </li></ul>Adaptado de: [ Hunt & Thomas, 2004]
  16. 16. Critérios de valoração <ul><li>Os valores estão em conformidade com um formato especificado (ou sub-entendido)? </li></ul><ul><ul><li>o formato de armazenamento é respeitado sempre? </li></ul></ul><ul><ul><ul><li>ex. formato para armazenar data </li></ul></ul></ul><ul><ul><li>o formato de apresentação é respeitado sempre? </li></ul></ul><ul><ul><ul><li>ex. formato de exibir data </li></ul></ul></ul>Adaptado de: [ Hunt & Thomas, 2004]
  17. 17. Critérios de valoração <ul><li>Os valores estão ordenados (ou não) conforme especificado? </li></ul><ul><li>O domínio dos valores (mínimo e máximo) são respeitados? </li></ul><ul><ul><li>o domínio de valores plausíveis é controlado? </li></ul></ul><ul><li>O código depende de condições que estão fora do seu controle? </li></ul><ul><ul><li>objetos externos utilizados precisam estar em determinado estado? </li></ul></ul><ul><ul><li>o usuário precisa estar autorizado? </li></ul></ul><ul><li>A cardinalidade (número de objetos de um conjunto) ou a contagem estão corretas? </li></ul><ul><li>A temporização é respeitada? </li></ul><ul><ul><li>os eventos ocorrem na ordem correta? </li></ul></ul><ul><ul><li>De acordo com as restrições de tempo especificadas? </li></ul></ul>Adaptado de: [ Hunt & Thomas, 2004]
  18. 18. Critérios de valoração <ul><li>Todos os atributos e referências dos objetos alterados devem ser verificados </li></ul><ul><ul><li>pode tornar necessária a introdução de redundâncias </li></ul></ul><ul><ul><ul><li>ver teste baseado em assertivas </li></ul></ul></ul><ul><ul><ul><ul><li>== Test emptying empty list </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=emptylist Lista_1 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=getnumelem Lista_1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=movefirst Lista_1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=movelast Lista_1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=moveelem Lista_1 -1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=moveelem Lista_1 1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=getelem Lista_1 &quot;ø&quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=deleteelem Lista_1 false </li></ul></ul></ul></ul><ul><ul><ul><ul><li>== Insert an element into empty list </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=insertafter Lista_1 &quot;abcdefg&quot; </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=getnumelem Lista_1 1 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=moveelem Lista_1 -1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=moveelem Lista_1 1 0 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>=getelem Lista_1 &quot;abcdefg&quot; </li></ul></ul></ul></ul>O último parâmetro indica o número de elementos caminhados &quot; ø &quot; simboliza o string inexistente
  19. 19. Critérios de valoração <ul><li>Podem-se definir mais padrões de valoração </li></ul><ul><ul><li>crie e mantenha um “ manual de testes ” com os padrões de valoração </li></ul></ul><ul><ul><li>registre nele os problemas encontrados com alguma freqüência e como se deve realizar os testes para identificar a ocorrência desses problemas </li></ul></ul><ul><li>Este critério – valoração – é um exemplo de critério baseado em lista de controle </li></ul><ul><ul><li>à medida que se vai identificando mais condições potenciais causadoras de problemas, acrescenta-se ao “manual de teste” uma descrição de como realizar os correspondentes testes </li></ul></ul><ul><ul><li>se determinada condição se mostra inútil, ou sua solução inadequada, pode-se removê-la da lista </li></ul></ul>
  20. 20. Teste de unidade <ul><li>Objetivos </li></ul><ul><ul><li>verificar se cada função ou método realiza o que se espera </li></ul></ul><ul><ul><ul><li>em condições de uso normais </li></ul></ul></ul><ul><ul><ul><li>em condições de uso anormais </li></ul></ul></ul><ul><ul><ul><ul><li>exceções </li></ul></ul></ul></ul><ul><ul><ul><ul><li>violações das assertivas (contratos) </li></ul></ul></ul></ul><ul><ul><li>verificar se as classes (módulos) estão completas e corretas </li></ul></ul><ul><ul><li>verificar se a documentação técnica é coerente com o que se encontra implementado </li></ul></ul><ul><ul><li>verificar a coerência das interfaces com o que está implementado </li></ul></ul><ul><ul><li>permitir o reteste completo realizado com freqüência </li></ul></ul>
  21. 21. Teste de unidade <ul><li>De maneira geral, conhecida a interface da unidade a testar, cria-se um módulo de controle de teste que permite exercitar detalhadamente a unidade a testar </li></ul>
  22. 22. Teste de unidade : exemplo de arcabouço de apoio ao teste
  23. 23. Critérios de teste estrutural <ul><li>Critérios </li></ul><ul><ul><li>todas instruções todos nós [Delamaro et al, 2007] </li></ul></ul><ul><ul><li>todas arestas todas decisões </li></ul></ul><ul><ul><li>todas condições </li></ul></ul><ul><ul><li>todos caminhos </li></ul></ul><ul><ul><li>fluxo de dados </li></ul></ul>
  24. 24. Grafo da estrutura do código <ul><li>Processo genérico para gerar massas de teste: </li></ul><ul><ul><li>criar o grafo da estrutura do código a testar </li></ul></ul><ul><ul><ul><li>pode envolver chamadas a funções ou métodos </li></ul></ul></ul><ul><ul><li>com base no grafo e no critério de cobertura escolhidos gerar os casos de teste </li></ul></ul><ul><ul><li>qual a diferença com relação afluxogramas? </li></ul></ul><ul><li>Convenções utilizadas </li></ul>Início de função ou método, chamada de função ou método Seqüência de um ou mais comandos Término de função, return , throw
  25. 25. Grafo da estrutura do código: exemplo <ul><li>01 STR_CString :: </li></ul><ul><li>02 STR_CString( long idStringParm ) </li></ul><ul><li>03 { </li></ul><ul><li>04 #ifdef _DEBUG </li></ul><ul><li>05 EXC_ASSERT( idStringParm < 0 ) ; </li></ul><ul><li>06 #endif </li></ul><ul><li>07 unsigned long idStr = ( idStringParm & STR_ID ) ; </li></ul><ul><li>08 if ( ( idStringParm & STR_MEM ) == STR_MEM ) </li></ul><ul><li>09 { </li></ul><ul><li>10 BuildStr( idStr ) ; </li></ul><ul><li>11 } else </li></ul><ul><li>12 { </li></ul><ul><li>13 BuildStr( STR_MsgNotImplemented & STR_ID ) ; </li></ul><ul><li>14 } // if </li></ul><ul><li>15 } // End of function: STR !Construct a </li></ul><ul><li>string given an idString </li></ul>01 08 10 13 14 15 21 21
  26. 26. Grafo da estrutura do código: exemplo <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr ) </li></ul><ul><li>23 { </li></ul><ul><li>24 char * pStr = GetStringAddress( idStr ) ; </li></ul><ul><li>25 if ( pStr != NULL ) </li></ul><ul><li>26 { </li></ul><ul><li>27 BuildString( vtStrMem[ i ].tamStr , pStr ) ; </li></ul><ul><li>28 return ; </li></ul><ul><li>29 } // if </li></ul><ul><li>30 char Msg[ TAL_dimBuffer ] ; </li></ul><ul><li>31 pStr = GetStringAddress( STR_ErrorUndefinedId ) ; </li></ul><ul><li>32 if ( pStr != NULL ) </li></ul><ul><li>33 { </li></ul><ul><li>34 sprintf( Msg , pStr , idStr ) ; </li></ul><ul><li>35 } else { </li></ul><ul><li>36 sprintf( Msg , ILLEGAL_STR_TABLE , idStr ) ; </li></ul><ul><li>37 } /* if */ </li></ul><ul><li>38 BuildString( strlen( Msg ) , Msg ) ; </li></ul><ul><li>39 } // End of function: STR $Build string for </li></ul><ul><li>a given Id </li></ul>21 71 25 27 30 51 71 32 34 36 38 51 39
  27. 27. Grafo da estrutura do código: exemplo <ul><li>51 void STR_CString :: </li></ul><ul><li>52 BuildString( const int LengthParm , </li></ul><ul><li>53 const char * const pStringParm ) </li></ul><ul><li>54 { </li></ul><ul><li>55 delete pCharString ; </li></ul><ul><li>56 Length = LengthParm ; </li></ul><ul><li>57 pCharString = new char[ Length + 1 ] ; </li></ul><ul><li>58 if ( Length > 0 ) </li></ul><ul><li>59 { </li></ul><ul><li>60 if ( pStringParm != NULL ) </li></ul><ul><li>61 { </li></ul><ul><li>62 memcpy( pCharString , pStringParm , </li></ul><ul><li>Length ) ; </li></ul><ul><li>63 } else </li></ul><ul><li>64 { </li></ul><ul><li>65 memset( pCharString , STR_NULLChar , </li></ul><ul><li>Length ) ; </li></ul><ul><li>66 } /* if */ </li></ul><ul><li>67 } /* if */ </li></ul><ul><li>68 pCharString[ Length ] = 0 ; </li></ul><ul><li>69 } // End of function: STR $Build a string of </li></ul><ul><li>a given size </li></ul>51 58 60 62 65 66 67 69
  28. 28. Grafo da estrutura do código: exemplo <ul><li>71 char * STR_CString :: </li></ul><ul><li>72 GetStringAddress( long idString ) </li></ul><ul><li>73 { </li></ul><ul><li>74 unsigned long idStr = ( idString & STR_ID ) ; </li></ul><ul><li>75 for( int i = 0 ; i < NUM_STR_MEM ; i ++ ) </li></ul><ul><li>76 { </li></ul><ul><li>77 if ( vtStrMem[ i ].idStr == idStr ) </li></ul><ul><li>78 { </li></ul><ul><li>79 char * pStr = vtpStrTxt[ </li></ul><ul><li>vtStrMem[ i ].inxStrTxt ] ; </li></ul><ul><li>80 pStr += vtStrMem[ i ].inxStrTxtOrg ; </li></ul><ul><li>81 return pStr ; </li></ul><ul><li>82 } // if </li></ul><ul><li>83 } // for </li></ul><ul><li>84 return NULL ; </li></ul><ul><li>85 } // End function: STR &Get pointer to memory </li></ul><ul><li>resident string table </li></ul>71 75 77 83 79 84 85
  29. 29. Arrasto <ul><li>Como testar repetições? </li></ul><ul><li>O custo do teste cresce com o número de iterações </li></ul><ul><ul><li>portanto o número de iterações a testar deverá ser </li></ul></ul><ul><ul><ul><li>pequeno de modo a minimizar o custo </li></ul></ul></ul><ul><ul><ul><li>mas suficientemente grande para que o teste seja uma boa aproximação de um teste confiável </li></ul></ul></ul><ul><li>Recordação: um teste é confiável caso ele detecte todos os defeitos porventura existentes no código </li></ul>
  30. 30. Arrasto <ul><li>Arrasto </li></ul><ul><ul><li>é o maior dos menores números de iterações necessárias para que todas as variáveis ou estados inicializados antes e modificados durante a repetição passem a depender exclusivamente de valores computados em iterações anteriores de uma mesma instância de execução dessa repetição </li></ul></ul><ul><li>Exemplos: </li></ul><ul><ul><ul><li>A[0] = 0 ; A[1] = 0 ; A[2] = 0 ; A[3] = 0 ; </li></ul></ul></ul><ul><ul><ul><li>memset( A , 0 , sizeof( A )) ; </li></ul></ul></ul><ul><ul><ul><li>pElem = ProcurarSimbolo( pTabela , pSimbolo ) ; </li></ul></ul></ul><ul><ul><li>todos têm Arrasto == 0 </li></ul></ul><ul><li>Arrasto : força de resistência ao avanço de um objeto em um fluido, resultante da ação do meio </li></ul>
  31. 31. Arrasto: exemplos <ul><li>for ( i = 0 ; i < 10 ; i++ ) ... </li></ul><ul><li>for ( pElem = pOrg ; pElem != NULL ; pElem = pElem->pProx ) ... </li></ul><ul><li>fgets, fputs, fread, fwrite </li></ul><ul><li>tpEstado Corrente ; </li></ul><ul><li>Corrente = DefinirPrimeiro ( ValorProcurado ) ; </li></ul><ul><li>while ( ! Terminou ( Corrente )) </li></ul><ul><li>{ </li></ul><ul><li>if ( Comparar ( ObterValor ( Corrente ), ValorProcurado ) </li></ul><ul><li>== EH_IGUAL ) </li></ul><ul><li>{ return Corrente ; </li></ul><ul><li>} /* if */ </li></ul><ul><li>Corrente = DefinirProximo ( Corrente , ValorProcurado ) ; </li></ul><ul><li>} /* while */ </li></ul><ul><li>return ESTADO_NIL ; </li></ul><ul><li>Todos têm Arrasto == 1 </li></ul>
  32. 32. Arrasto <ul><li>O arrasto é o número mínimo de iterações a realizar para que todos os valores que possam ser modificados durante a repetição tenham sido de fato modificados </li></ul><ul><ul><li>corresponde ao número mínimo de iterações para atingir o estado “genérico” </li></ul></ul><ul><li>Os casos de teste a para as repetições são: </li></ul><ul><ul><li>caso 0 iteração (caso especial) </li></ul></ul><ul><ul><li>caso 1 iteração (base da indução) </li></ul></ul><ul><ul><li>caso n >= arrasto + 1 iterações ( simula o passo de indução) </li></ul></ul><ul><ul><li>devem sempre ser considerados os casos de término: </li></ul></ul><ul><ul><ul><li>break ou return no corpo da iteração </li></ul></ul></ul><ul><ul><ul><li>atingiu a condição de término </li></ul></ul></ul>
  33. 33. Critério de cobertura de instruções <ul><li>Cobertura de instruções ( todos os nós ) </li></ul><ul><ul><li>Cada instrução é executada pelo menos uma vez no conjunto de todos os casos de teste </li></ul></ul><ul><ul><li>dado o grafo </li></ul></ul><ul><ul><ul><li>cada caso percorre pelo menos um vértice (nó) ainda não percorrido </li></ul></ul></ul><ul><ul><ul><li>até que todos os vértices tenham sido percorridos </li></ul></ul></ul><ul><li>Escolher </li></ul><ul><ul><li>x e y : x && y => true </li></ul></ul><ul><ul><li>x e z : x || z => true </li></ul></ul><ul><ul><li>e após a execução de P2 uma ou mais vezes: x || y => false </li></ul></ul>
  34. 34. Critério de cobertura de instruções: exemplo <ul><li>71 char * STR_CString :: </li></ul><ul><li>72 GetStringAddress( long idString ) </li></ul><ul><li>73 { </li></ul><ul><li>74 unsigned long idStr = ( idString & STR_ID ) ; </li></ul><ul><li>75 for( int i = 0 ; i < NUM_STR_MEM ; i ++ ) </li></ul><ul><li>76 { </li></ul><ul><li>77 if ( vtStrMem[ i ].idStr == idStr ) </li></ul><ul><li>78 { </li></ul><ul><li>79 char * pStr = vtpStrTxt[ </li></ul><ul><li>vtStrMem[ i ].inxStrTxt ] ; </li></ul><ul><li>80 pStr += vtStrMem[ i ].inxStrTxtOrg ; </li></ul><ul><li>81 return pStr ; </li></ul><ul><li>82 } // if </li></ul><ul><li>83 } // for </li></ul><ul><li>84 return NULL ; </li></ul><ul><li>85 } // End function: STR &Get pointer to memory </li></ul><ul><li>resident string table </li></ul>71 75 77 83 79 84 85 Dois caminhos asseguram a cobertura 71 75 77 83 84 85 71 75 77 79 85
  35. 35. Critério de cobertura de arestas <ul><li>Cobertura de arestas </li></ul><ul><ul><li>Cada aresta é percorrida pelo menos uma vez no conjunto de todos os casos de teste </li></ul></ul><ul><ul><li>rotulam-se as arestas e criam-se os casos de teste </li></ul></ul><ul><ul><ul><li>cada caso percorre pelo menos uma aresta ainda não percorrida </li></ul></ul></ul><ul><ul><ul><li>até que todas as arestas tenham sido percorridas </li></ul></ul></ul><ul><ul><li>executar repetições para: </li></ul></ul><ul><ul><ul><li>n = 0 iterações </li></ul></ul></ul><ul><ul><ul><li>n = 1 iteração </li></ul></ul></ul><ul><ul><ul><li>n >= 2 iterações </li></ul></ul></ul><ul><li>Escolher </li></ul><ul><ul><li>x e y : x && y => false </li></ul></ul><ul><ul><li>x e y : x && y => true </li></ul></ul><ul><ul><li>x e z : x || z => false antes de executar P2 pela primeira vez (0 ciclos) </li></ul></ul><ul><ul><li>x e z : x || z => true , e false imediatamente após a primeira execução de P2 (1 ciclo) </li></ul></ul><ul><ul><li>x e z : x || z => true , e false após n > 1 execuções de P2 (n ciclos) </li></ul></ul>
  36. 36. Critério de cobertura de arestas: exemplo <ul><li>71 char * STR_CString :: </li></ul><ul><li>72 GetStringAddress( long idString ) </li></ul><ul><li>73 { </li></ul><ul><li>74 unsigned long idStr = ( idString & STR_ID ) ; </li></ul><ul><li>75 for( int i = 0 ; i < NUM_STR_MEM ; i ++ ) </li></ul><ul><li>76 { </li></ul><ul><li>77 if ( vtStrMem[ i ].idStr == idStr ) </li></ul><ul><li>78 { </li></ul><ul><li>79 char * pStr = vtpStrTxt[ </li></ul><ul><li>vtStrMem[ i ].inxStrTxt ] ; </li></ul><ul><li>80 pStr += vtStrMem[ i ].inxStrTxtOrg ; </li></ul><ul><li>81 return pStr ; </li></ul><ul><li>82 } // if </li></ul><ul><li>83 } // for </li></ul><ul><li>84 return NULL ; </li></ul><ul><li>85 } // End function: STR &Get pointer to memory </li></ul><ul><li>resident string table </li></ul>71 75 77 83 79 84 85 0 ciclos: 71 75 84 85 71 75 77 79 85 1 ciclo 71 75 77 83 75 84 85 71 75 77 83 75 77 79 85 2 ciclos 71 75 77 83 75 77 83 75 84 85 71 75 77 83 75 77 83 75 77 79 85
  37. 37. Critério de cobertura de condições <ul><li>Cobertura de arestas mais: </li></ul><ul><ul><li>cada expressão é testada de tantas maneiras quantas forem os elementos das tabelas de verdade </li></ul></ul><ul><li>x T T F F </li></ul><ul><li>y T F T F </li></ul><ul><li>x && y T F F F </li></ul><ul><li>x T T F F </li></ul><ul><li>z T F T F </li></ul><ul><li>x || z T T T F </li></ul>
  38. 38. Teste de funções encapsuladas <ul><li>Funções encapsuladas ( static no módulo, private , protected ) não são acessíveis a partir da interface </li></ul><ul><li>Como testá-las? </li></ul><ul><ul><li>A: criar um módulo para teste em que não são encapsuladas. Inconvenientes: </li></ul></ul><ul><ul><ul><li>dificulta retestar – teste de regressão – módulos já aprovados </li></ul></ul></ul><ul><ul><ul><li>a mudança de teste para produção pode introduzir defeitos </li></ul></ul></ul><ul><ul><li>B: considerar as funções encapsuladas como extensões de uma ou mais das funções externadas. Inconvenientes: </li></ul></ul><ul><ul><ul><li>as massas de teste podem tornar-se muito extensas devido à explosão combinatória (discutido mais adiante) </li></ul></ul></ul><ul><ul><ul><li>nem todas as condições são passíveis de teste </li></ul></ul></ul><ul><ul><li>C: criar funções de instrumentação disponíveis quando o módulo é compilado para fins de teste. Inconveniente: </li></ul></ul><ul><ul><ul><li>ex. uma espécie de “getter” para funções </li></ul></ul></ul><ul><ul><ul><li>a variedade de formas de compilação pode introduzir defeitos </li></ul></ul></ul>
  39. 39. Teste de funções encapsuladas: exemplo <ul><li>01 STR_CString :: </li></ul><ul><li>02 STR_CString( long idStringParm ) </li></ul><ul><li>03 { </li></ul><ul><li>04 #ifdef _DEBUG </li></ul><ul><li>05 EXC_ASSERT( idStringParm < 0 ) ; </li></ul><ul><li>06 #endif </li></ul><ul><li>07 unsigned long idStr = ( idStringParm & STR_ID ) ; </li></ul><ul><li>08 if ( ( idStringParm & STR_MEM ) == STR_MEM ) </li></ul><ul><li>09 { </li></ul><ul><li>10 BuildStr( idStr ) ; </li></ul><ul><li>11 } else </li></ul><ul><li>12 { </li></ul><ul><li>13 BuildStr( STR_MsgNotImplemented & STR_ID ) ; </li></ul><ul><li>14 } // if </li></ul><ul><li>15 } // End of function: STR !Construct a </li></ul><ul><li>string given an idString </li></ul>01 08 10 13 14 15 21 21 21 - Considerar idStringParm que (i) existem , (ii) não existem e (iii) a falta do string default para emitir a mensagem de não existência. Ver função BuildStr( long ) a seguir 51 - Considerar string de tamanho igual a 0, ver BuildString( int , char * ) a seguir 71 - Considerar repetições de procura 0, 1 e n iterações, ver GetStringAddress( long ) a seguir
  40. 40. Teste de funções encapsuladas: exemplo <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr ) </li></ul><ul><li>23 { </li></ul><ul><li>24 char * pStr = GetStringAddress( idStr ) ; </li></ul><ul><li>25 if ( pStr != NULL ) </li></ul><ul><li>26 { </li></ul><ul><li>27 BuildString( vtStrMem[ i ].tamStr , pStr ) ; </li></ul><ul><li>28 return ; </li></ul><ul><li>29 } // if </li></ul><ul><li>30 char Msg[ TAL_dimBuffer ] ; </li></ul><ul><li>31 pStr = GetStringAddress( STR_ErrorUndefinedId ) ; </li></ul><ul><li>32 if ( pStr != NULL ) </li></ul><ul><li>33 { </li></ul><ul><li>34 sprintf( Msg , pStr , idStr ) ; </li></ul><ul><li>35 } else { </li></ul><ul><li>36 sprintf( Msg , ILLEGAL_STR_TABLE , idStr ) ; </li></ul><ul><li>37 } /* if */ </li></ul><ul><li>38 BuildString( strlen( Msg ) , Msg ) ; </li></ul><ul><li>39 } // End of function: STR $Build string for </li></ul><ul><li>a given Id </li></ul>21 71 25 27 30 51 71 32 34 36 38 51 39
  41. 41. Teste de funções encapsuladas: exemplo <ul><li>51 void STR_CString :: </li></ul><ul><li>52 BuildString( const int LengthParm , </li></ul><ul><li>53 const char * const pStringParm ) </li></ul><ul><li>54 { </li></ul><ul><li>55 delete pCharString ; </li></ul><ul><li>56 Length = LengthParm ; </li></ul><ul><li>57 pCharString = new char[ Length + 1 ] ; </li></ul><ul><li>58 if ( Length > 0 ) </li></ul><ul><li>59 { </li></ul><ul><li>60 if ( pStringParm != NULL ) </li></ul><ul><li>61 { </li></ul><ul><li>62 memcpy( pCharString , pStringParm , </li></ul><ul><li>Length ) ; </li></ul><ul><li>63 } else </li></ul><ul><li>64 { </li></ul><ul><li>65 memset( pCharString , STR_NULLChar , </li></ul><ul><li>Length ) ; </li></ul><ul><li>66 } /* if */ </li></ul><ul><li>67 } /* if */ </li></ul><ul><li>68 pCharString[ Length ] = 0 ; </li></ul><ul><li>69 } // End of function: STR $Build a string of </li></ul><ul><li>a given size </li></ul>51 58 60 62 65 66 67 69 Como testar pStringParm == NULL sem adulterar os módulos cliente?
  42. 42. Teste de funções encapsuladas: exemplo <ul><li>71 char * STR_CString :: </li></ul><ul><li>72 GetStringAddress( long idString ) </li></ul><ul><li>73 { </li></ul><ul><li>74 unsigned long idStr = ( idString & STR_ID ) ; </li></ul><ul><li>75 for( int i = 0 ; i < NUM_STR_MEM ; i ++ ) </li></ul><ul><li>76 { </li></ul><ul><li>77 if ( vtStrMem[ i ].idStr == idStr ) </li></ul><ul><li>78 { </li></ul><ul><li>79 char * pStr = vtpStrTxt[ </li></ul><ul><li>vtStrMem[ i ].inxStrTxt ] ; </li></ul><ul><li>80 pStr += vtStrMem[ i ].inxStrTxtOrg ; </li></ul><ul><li>81 return pStr ; </li></ul><ul><li>82 } // if </li></ul><ul><li>83 } // for </li></ul><ul><li>84 return NULL ; </li></ul><ul><li>85 } // End function: STR &Get pointer to memory </li></ul><ul><li>resident string table </li></ul>71 75 77 83 79 84 85
  43. 43. Critério cobertura de caminhos <ul><li>Um caminho (ou arco de execução) corresponde a uma seqüência de execução das instruções dentro de um conjunto de grafos da estrutura de código </li></ul><ul><ul><li>em geral considera-se os caminhos que vão do início ao término da execução de uma função </li></ul></ul><ul><ul><ul><li>chamadas de função encapsuladas podem ser tratadas </li></ul></ul></ul><ul><ul><ul><ul><li>ou como pseudo-instruções </li></ul></ul></ul></ul><ul><ul><ul><ul><li>ou como referências a outro grafo a ser percorrido </li></ul></ul></ul></ul><ul><ul><ul><li>chamadas a funções externadas podem ser tratadas como pseudo-instruções uma vez que podem ser testadas detalhadamente através da interface </li></ul></ul></ul><ul><ul><li>em alguns casos pode ser interessante considerar somente um fragmento de um algoritmo complexo </li></ul></ul>
  44. 44. Cobertura de caminhos <ul><li>A cobertura de caminhos tende a levar a uma explosão combinatória </li></ul><ul><ul><li>o número de caminhos é proporcional ao produtório das alternativas aninhadas </li></ul></ul><ul><li>Uma solução é transformar fragmentos do código em funções </li></ul><ul><ul><li>dilema: como testar funções encapsuladas? </li></ul></ul>O da ordem de
  45. 45. Cobertura de caminhos <ul><li>O critério cobertura de caminhos seleciona um conjunto de caminhos </li></ul><ul><ul><li>cada caminho é um caso de teste abstrato </li></ul></ul><ul><ul><li>a valoração dos dados deve assegurar que se execute exatamente o caminho escolhido </li></ul></ul><ul><ul><li>o conjunto de caminhos selecionados forma a massa de testes </li></ul></ul><ul><li>Para manter pequeno o custo do teste deseja-se </li></ul><ul><ul><li>um conjunto pequeno de caminhos curtos </li></ul></ul><ul><ul><li>o conjunto de caminhos deve </li></ul></ul><ul><ul><ul><li>ser completo  exercitar todo o código </li></ul></ul></ul><ul><ul><ul><li>simular a argumentação da corretude </li></ul></ul></ul><ul><ul><ul><ul><li>auxiliar a argumentação da corretude </li></ul></ul></ul></ul><ul><ul><ul><li>utilizar a estrutura do código </li></ul></ul></ul>
  46. 46. Cobertura de caminhos: exemplo de seleção <ul><li>71 char * STR_CString :: </li></ul><ul><li>72 GetStringAddress( long idString ) </li></ul><ul><li>73 { </li></ul><ul><li>74 unsigned long idStr = ( idString & STR_ID ) ; </li></ul><ul><li>75 for( int i = 0 ; i < NUM_STR_MEM ; i ++ ) </li></ul><ul><li>76 { </li></ul><ul><li>77 if ( vtStrMem[ i ].idStr == idStr ) </li></ul><ul><li>78 { </li></ul><ul><li>79 char * pStr = vtpStrTxt[ </li></ul><ul><li>vtStrMem[ i ].inxStrTxt ] ; </li></ul><ul><li>80 pStr += vtStrMem[ i ].inxStrTxtOrg ; </li></ul><ul><li>81 return pStr ; </li></ul><ul><li>82 } // if </li></ul><ul><li>83 } // for </li></ul><ul><li>84 return NULL ; </li></ul><ul><li>85 } // End function: STR &Get pointer to memory </li></ul><ul><li>resident string table </li></ul>71 75 77 83 79 84 85 Caminhos 0 vezes: <71, 75 , 84, 85>; <71, 75 , 77 , 79, 85>; 1 vez: <71, 75 , 77, 83, 75 , 84, 85>; <71, 75 , 77, 83, 75 , 77, 79, 85>; 2 vezes: <71, 75 , 77, 83, 75 , 77, 83, 75 , 84, 85>; <71, 75 , 77, 83, 75 , 77, 83, 75 , 77, 79, 85>;
  47. 47. Cobertura de caminhos <ul><li>Processo de geração da lista de caminhos a testar </li></ul><ul><ul><li>a partir de um diagrama da estrutura do código ou do grafo da estrutura do código </li></ul></ul><ul><ul><ul><li>cria-se uma expressão algébrica que descreve o conjunto de todos os possíveis caminhos </li></ul></ul></ul><ul><ul><ul><ul><li>em um programa estruturado a expressão será sempre uma expressão regular </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Exemplo – cada elemento A, B, C é uma expressão regular </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>conjunto: A , B , C ; seqüência A B C ; seleção: ( A | B | C ) ; repetição: n 1 – n 2 [ A ] </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>não vale recursão que aninhe ex. a := ( b a c | b c ) </li></ul></ul></ul></ul></ul><ul><ul><ul><li>com base na expressão algébrica e no critério de valoração geram-se os caminhos a serem percorridos </li></ul></ul></ul>
  48. 48. Cobertura de caminhos <ul><li>Cálculo da expressão algébrica dos caminhos </li></ul><ul><ul><li>rotulam-se os blocos e instruções </li></ul></ul><ul><ul><li>percorre-se o código </li></ul></ul><ul><ul><ul><li>externa-se o rótulo da instrução ou do bloco visitado </li></ul></ul></ul><ul><ul><ul><li>se o bloco for início de controle de repetição externa-se ‘ [ ’ </li></ul></ul></ul><ul><ul><ul><ul><li>calcula-se o arrasto e externa-se o valor arrasto + 1 </li></ul></ul></ul></ul><ul><ul><ul><ul><li>ao terminar o controle de repetição externa-se ‘ ] ’ </li></ul></ul></ul></ul><ul><ul><ul><li>se for início de controle de seleção externa-se ‘ ( ’ </li></ul></ul></ul><ul><ul><ul><ul><li>ao atingir um else ou else if externa-se ‘ | ’ </li></ul></ul></ul></ul><ul><ul><ul><ul><li>ao terminar o controle de repetição externa-se ‘ ) ’ </li></ul></ul></ul></ul><ul><ul><ul><ul><li>caso o else final seja vazio, i.e. não existe, externa-se ‘ | ) ’ </li></ul></ul></ul></ul><ul><ul><ul><li>se for uma chamada de função encapsulada e </li></ul></ul></ul><ul><ul><ul><ul><li>se o modo de cobertura de chamada de funções é percorrimento das funções encapsuladas , passa-se a percorrer a função servidora chamada, ao retornar retoma-se o percorrimento da função cliente </li></ul></ul></ul></ul><ul><ul><ul><ul><li>se o modo de cobertura de chamadas de funções é pseudo-instrução , externa-se nada </li></ul></ul></ul></ul>
  49. 49. Cobertura de caminhos <ul><li>// (A) Intercalar arquivos </li></ul><ul><li>// (B) Abrir arquivos </li></ul><ul><li>// (E) Inicializar </li></ul><ul><li>// Ler primeiro registro de arquivo A </li></ul><ul><li>// Ler primeiro registro de arquivo B </li></ul><ul><li>// (C 2) Intercalar pares de registros </li></ul><ul><li>while ( tem registro a processar ) </li></ul><ul><li>// (G) Transferir registro de A para S </li></ul><ul><li>if ( chave buffer A < chave buffer B ) </li></ul><ul><li>transferir de buffer A para S </li></ul><ul><li>// (H) Transferir registro de A e B para D </li></ul><ul><li>else if ( chave buffer A == </li></ul><ul><li>chave buffer B ) </li></ul><ul><li>transferir registro de A para D </li></ul><ul><li>transferir registro de B para D </li></ul><ul><li>// (I) Transferir registro de B para S </li></ul><ul><li>else </li></ul><ul><li>transferir de buffer B para S </li></ul><ul><li>// (D) Fechar arquivos </li></ul><ul><li>Expressão de caminhos </li></ul><ul><li>A </li></ul><ul><li>ABE </li></ul><ul><li>ABEC[3 </li></ul><ul><li>ABEC[3(G </li></ul><ul><li>ABEC[3(G|H|I </li></ul><ul><li>ABEC[3(G|H|I)]D </li></ul>
  50. 50. Cobertura de caminhos <ul><li>Com a expressão A B C E [ 3 F ( G | H | I ) ] D c ria-se a lista dos caminhos a testar , usando a expressão como gerador  casos de teste abstratos </li></ul><ul><ul><li>0 ciclos (caminhos dos casos especiais) </li></ul></ul><ul><ul><ul><li>ABCED </li></ul></ul></ul><ul><ul><li>1 ciclo (caminhos da base da indução) </li></ul></ul><ul><ul><ul><li>ABCEFGD </li></ul></ul></ul><ul><ul><ul><li>ABCEFHD </li></ul></ul></ul><ul><ul><ul><li>ABCEFID </li></ul></ul></ul><ul><ul><li>3 (== arrasto + 1) ciclos (caminhos do passo de indução) </li></ul></ul><ul><ul><ul><li>ABCEFGFGFGD </li></ul></ul></ul><ul><ul><ul><li>ABCEFGFGFHD </li></ul></ul></ul><ul><ul><ul><li>ABCEFGFGFID </li></ul></ul></ul><ul><ul><ul><li>ABCEFGFHFGD </li></ul></ul></ul><ul><ul><ul><li>ABCEFGFHFHD </li></ul></ul></ul><ul><ul><ul><li>ABCEFGFHFID </li></ul></ul></ul><ul><ul><ul><li>. . . </li></ul></ul></ul>
  51. 51. Transformação em caso de teste úteis Os casos gerados foram casos de teste abstratos
  52. 52. Transformação em caso de teste úteis <ul><li>Casos de teste valorados determinam os valores e coman-dos a serem utilizados como dados dos casos de teste </li></ul><ul><ul><li>Crie os arquivos A0 = {}, B0 = {}, A1 = { c1 }, B11 = { c1 } , A3 = { c1 , c2 , c3 } , B12 = { c3 } , . . . </li></ul></ul><ul><ul><li>Arq A vazio, Arq B vazio  A0 , B0 </li></ul></ul><ul><ul><li>Arq A com 1, Arq B vazio  A1 , B0 </li></ul></ul><ul><ul><li>Arq A com 1, Arq B com 1 e chaves de ambos iguais  A1 , B11 </li></ul></ul><ul><ul><li>Arq A vazio, Arq B com 1  A0 , B11 </li></ul></ul><ul><ul><li>Arq A com 3, Arq B vazio  A3 , B0 </li></ul></ul><ul><ul><li>Arq A com 3, Arq B com 1, chave em B igual à chave do 3º. de A  A3 , B12 </li></ul></ul><ul><ul><li>. . . </li></ul></ul>
  53. 53. Transformação em caso de teste úteis <ul><li>Casos de teste úteis estabelecem os resultados esperados em função dos dados </li></ul><ul><ul><li>Criar arquivos S0 = {} , E0 = {} , S1 = { c1 } , E11 = { c1 , c1 } , S2 = { c1 , c2 } , S3 = { c1 , c2 , c3 } , E12 = { c3 , c3 } , . . . </li></ul></ul><ul><ul><li>A0 , B0  S0 , E0 </li></ul></ul><ul><ul><li>A1 , B0  S1 , E0 </li></ul></ul><ul><ul><li>A1 , B11  S0 , E11 </li></ul></ul><ul><ul><li>A0 , B11  S1 , E0 </li></ul></ul><ul><ul><li>A3 , B0  S3 , E0 </li></ul></ul><ul><ul><li>A3 , B12  S2 , E12 </li></ul></ul><ul><ul><li>. . . </li></ul></ul>
  54. 54. Transformação em caso de teste úteis <ul><li>Dica para automação </li></ul><ul><ul><li>criar todos os arquivos requeridos </li></ul></ul><ul><ul><li>criar um programa de teste específico que </li></ul></ul><ul><ul><ul><li>para cada caso de teste recebe linhas com os nomes dos 4 arquivos </li></ul></ul></ul><ul><ul><ul><li>executa a intercalação com os dois primeiros arquivos </li></ul></ul></ul><ul><ul><ul><li>compara os arquivos resultantes com os dois últimos </li></ul></ul></ul><ul><ul><li>o módulo de intercalação pode ser implementado contendo uma função que recebe quatro parâmetros </li></ul></ul><ul><ul><ul><li>neste caso pode-se utilizar o arcabouço de apoio ao teste </li></ul></ul></ul><ul><ul><li>o programa de intercalação pode ser implementado como um programa principal recebendo 4 parâmetros da linha de comando </li></ul></ul><ul><ul><ul><li>neste caso pode-se implementar um batch ( .bat ) ou um programa LUA que controla a execução </li></ul></ul></ul>
  55. 55. Exemplo de roteiro de teste <ul><li>Um roteiro de teste estabelece um cenário de teste e fornece uma série de instruções a serem utilizadas durante os testes manuais ou automatizados: </li></ul><ul><li>== Intercalar A e B vazios </li></ul><ul><li>=intercalar A0 B0 S0 E0 </li></ul><ul><li>== Intercalar A contendo 1 registro com B vazio </li></ul><ul><li>=intercalar A1 B0 S1 E0 </li></ul><ul><li>== Intercalar A e B contendo 1 registro, chaves iguais </li></ul><ul><li>=intercalar A1 B11 S0 E11 </li></ul><ul><li>== Intercalar A vazio com B contendo 1 registro </li></ul><ul><li>=intercalar B0 A1 S1 E0 </li></ul><ul><li>. . . </li></ul>
  56. 56. Problema do teste caixa aberta <ul><li>O grande problema do teste caixa aberta é a explosão de casos de teste </li></ul><ul><ul><li>quanto mais controles aninhados em uma função exponencialmente maior é o número de casos de teste </li></ul></ul><ul><li>Outro problema é o fato de falhas poderem depender do caminho usado até a chamada de uma função </li></ul><ul><ul><li>este é um problema de integração </li></ul></ul><ul><li>Uma proposta é utilizar instrumentação (contadores de passagem) para verificar a parcela de cobertura alcançada </li></ul><ul><ul><li>inserir um contador de passagem </li></ul></ul><ul><ul><ul><li>em cada início de arco de fluxo de controle </li></ul></ul></ul><ul><ul><ul><li>antes de cada comando de retorno ( return , throw ) </li></ul></ul></ul>
  57. 57. Fluxo de dados <ul><li>Método de teste fluxo de dados tende a ser uma forma de inspecionar caminhos a fim de identificar caminhos potencialmente defeituosos </li></ul><ul><li>Dado um caminho, examinam-se as operações de criação, uso, atribuição, e destruição que são realizadas sobre cada um dos dados </li></ul><ul><ul><li>CRUD – Create, Retrieve, Update, Destroy </li></ul></ul><ul><li>Considerando o código de funções (métodos) </li></ul><ul><ul><li>muitos compiladores modernos geram advertências para caminhos potencialmente incorretos </li></ul></ul><ul><ul><ul><li>limitações óbvias: o problema é não computável no caso geral </li></ul></ul></ul><ul><ul><ul><li>quando receberem uma advertência, corrijam o código </li></ul></ul></ul><ul><ul><ul><ul><li>usualmente é erro mesmo </li></ul></ul></ul></ul><ul><ul><ul><li>nem todas as advertências são geradas  </li></ul></ul></ul>
  58. 58. Fluxo de dados <ul><li>Dados são sujeitos às seguintes operações: </li></ul><ul><ul><li>D - definição: declaração, construção, inicialização, atribuição, parâmetro recebido, parâmetro retornado, ... </li></ul></ul><ul><ul><ul><li>Dc declaração ou construção com valores neutros, ou sem valor </li></ul></ul></ul><ul><ul><li>L - destruição: destruição, indefinição, liberação, tornar desnecessário, … </li></ul></ul><ul><ul><li>U - uso: </li></ul></ul><ul><ul><ul><li>Uc - computação: acesso, elemento de fórmula, argumento passando valor, … </li></ul></ul></ul><ul><ul><ul><li>Up - controle: uso em um predicado, variável de controle, … </li></ul></ul></ul><ul><ul><li>* estado irrelevante - não definido, não existe, … </li></ul></ul><ul><ul><ul><li>antes de declarar </li></ul></ul></ul><ul><ul><ul><li>após return ou throw </li></ul></ul></ul><ul><ul><ul><li>após destruição </li></ul></ul></ul><ul><ul><ul><li>quando não for mais necessário dispor do elemento ou da instância </li></ul></ul></ul>
  59. 59. Fluxo de dados <ul><ul><li>a = expressão </li></ul></ul><ul><ul><ul><li>todas as variáveis da expressão são do gênero uc </li></ul></ul></ul><ul><ul><ul><li>a variável a é do gênero D </li></ul></ul></ul><ul><ul><li>read( a, b, c, …) </li></ul></ul><ul><ul><ul><li>todas as variáveis são do gênero D </li></ul></ul></ul><ul><ul><li>write( a, b, c, …) </li></ul></ul><ul><ul><ul><li>todas as variáveis são do gênero Uc </li></ul></ul></ul><ul><ul><li>free( pX ) ou delete obj </li></ul></ul><ul><ul><ul><li>o espaço apontado por pX , ou o objeto obj são do gênero L </li></ul></ul></ul><ul><ul><li>f( int * parm ) - declaração </li></ul></ul><ul><ul><ul><li>o ponteiro parm e o respectivo espaço são do gênero D </li></ul></ul></ul><ul><ul><li>*parm </li></ul></ul><ul><ul><ul><li>o ponteiro parm é do gênero Uc e o respectivo espaço é D </li></ul></ul></ul><ul><ul><li>f( parg ) - chamada passando referência </li></ul></ul><ul><ul><ul><li>o ponteiro parg é Uc o espaço depende do contrato: * , D ou Uc </li></ul></ul></ul>
  60. 60. Fluxo de dados <ul><ul><li>while ( exp ) </li></ul></ul><ul><ul><ul><li>todas as variáveis em exp são do gênero Up </li></ul></ul></ul><ul><ul><li>for ( a = b ; a < l ; a++ ) </li></ul></ul><ul><ul><ul><li>a é do gênero D (a = b, a ++) e Uc (a < l ) </li></ul></ul></ul><ul><ul><ul><li>b é do gênero Uc </li></ul></ul></ul><ul><ul><li>if ( exp) </li></ul></ul><ul><ul><ul><li>todas as variáveis em exp são do gênero Up </li></ul></ul></ul><ul><ul><li>switch ( exp) </li></ul></ul><ul><ul><ul><li>todas as variáveis em exp são do gênero Up </li></ul></ul></ul><ul><ul><li>OBS: exp não deve conter efeitos colaterais!!! </li></ul></ul><ul><ul><ul><li>proibido: while ( --i ) ou while ( scanf( ... ) != 0 ) ... </li></ul></ul></ul>
  61. 61. Fluxo de dados: conversão para caminhos <ul><li>Todas as definições </li></ul><ul><ul><li>exercitar cada uma das definições existentes pelo menos uma vez </li></ul></ul><ul><li>Todos usos </li></ul><ul><ul><li>exercitar pelo menos uma vez cada um dos usos Uc e Up pelo menos uma vez </li></ul></ul><ul><li>Todos DU caminhos </li></ul><ul><ul><li>sempre relativos a um atributo (variável) específico </li></ul></ul><ul><ul><li>exercitar pelo menos uma vez cada um dos caminhos que iniciam em uma definição até a próxima definição ou liberação da variável de referência </li></ul></ul>
  62. 62. Fluxo de dados: inspeção <ul><li>Seqüências envolvendo pares: </li></ul><ul><ul><li>DU - vale </li></ul></ul><ul><ul><li>UU - vale </li></ul></ul><ul><ul><li>LD - vale </li></ul></ul><ul><ul><li>UpD - vale </li></ul></ul><ul><ul><li>UcD - provavelmente vale </li></ul></ul><ul><ul><li>DcD - vale </li></ul></ul><ul><ul><li>DD - advertência definição múltipla </li></ul></ul><ul><ul><li>DcL – advertência se não tiver caminho alternativo: para que definir e destruir sem utilizar? </li></ul></ul><ul><ul><li>DL - possivelmente vale </li></ul></ul><ul><ul><li>LU - erro: destrói depois usa </li></ul></ul><ul><ul><li>LL - erro: destrói duas vezes </li></ul></ul>
  63. 63. Fluxo de dados: inspeção <ul><li>Seqüências envolvendo estado indefinido: </li></ul><ul><ul><li>*L - erro, não definida e destruída </li></ul></ul><ul><ul><li>*D - vale, primeira definição no caminho </li></ul></ul><ul><ul><li>*U - erro, usado antes de definir </li></ul></ul><ul><ul><li>L* - vale, última coisa feita é destruição </li></ul></ul><ul><ul><li>D* - advertência, definido e nunca utilizado </li></ul></ul><ul><ul><li>U* - provavelmente é erro se a variável for um objeto ou recurso não ancorado </li></ul></ul><ul><ul><ul><li>objetos e recursos não ancorados precisam ser liberados sempre que se tornem irrelevantes </li></ul></ul></ul><ul><ul><li>* - provavelmente erro, variável declarada mas não definida (inicializada) </li></ul></ul>
  64. 64. Fluxo de dados: exemplo grafo de código
  65. 65. Fluxo de dados: inspeção envolvendo x *DcDU* *DcU*
  66. 66. Fluxo de dados: inspeção envolvendo z *LU UD * *LU D * *LL DUUD * *LL DUD *
  67. 67. Fluxo de dados: inspeção <ul><li>21 void STR_CString :: </li></ul><ul><li>22 BuildStr( unsigned long idStr ) </li></ul><ul><li>23 { </li></ul><ul><li>24 char * pStr = GetStringAddress( idStr ) ; </li></ul><ul><li>25 if ( pStr != NULL ) </li></ul><ul><li>26 { </li></ul><ul><li>27 BuildString( vtStrMem[ i ].tamStr , pStr ) ; </li></ul><ul><li>28 return ; </li></ul><ul><li>29 } // if </li></ul><ul><li>30 char Msg[ TAL_dimBuffer ] ; </li></ul><ul><li>31 pStr = GetStringAddress( STR_ErrorUndefinedId ) ; </li></ul><ul><li>32 if ( pStr != NULL ) </li></ul><ul><li>33 { </li></ul><ul><li>34 sprintf( Msg , pStr , idStr ) ; </li></ul><ul><li>35 } else { </li></ul><ul><li>36 sprintf( Msg , ILLEGAL_STR_TABLE , idStr ) ; </li></ul><ul><li>37 } /* if */ </li></ul><ul><li>38 BuildString( strlen( Msg ) , Msg ) ; </li></ul><ul><li>39 } // End of function: STR $Build string for </li></ul><ul><li>a given Id </li></ul>21 71 25 27 30 51 71 32 34 36 38 51 39 idStr  22 D 27 Uc L ; 22 D 34 Uc L ; 22 D 36 Uc L pStr  24 D 25 Up 27 Uc L ; 24 D 25 Up 31 D 32 Up 34 Uc L ; 24 D 25 Up 31 D 32 Up L Msg  30 D 34 D 38 Uc L ; 30 D 36 D 38 Uc L
  68. 68. Teste de exceções <ul><li>Quando usar exceções? </li></ul><ul><ul><li>abordagem ortodoxa : somente quando ocorre uma situação anômala  erro, exemplos </li></ul></ul><ul><ul><ul><li>assertiva não vale </li></ul></ul></ul><ul><ul><ul><li>dispositivo não existe, mas deveria existir </li></ul></ul></ul><ul><ul><ul><li>faltou memória </li></ul></ul></ul><ul><ul><ul><li>anomalia na seqüência de execução </li></ul></ul></ul><ul><ul><ul><li>componente interno, ex. base de dados, recebeu dados não válidos </li></ul></ul></ul><ul><ul><li>abordagem não ortodoxa : um instrumento de controle da execução </li></ul></ul><ul><ul><ul><li>retorno de uma função que fica “longe” de quem trataria a condição de retorno </li></ul></ul></ul><ul><ul><ul><li>argumento: condições de retorno são chatas e acabam sendo ignoradas </li></ul></ul></ul><ul><ul><ul><ul><li>mas try catch finally em tudo quanto é lugar não é igualmente chato? </li></ul></ul></ul></ul>
  69. 69. <ul><li>Projetar para testabilidade </li></ul><ul><ul><li>estabeleça um padrão de implementação para exceções </li></ul></ul><ul><ul><ul><li>idealmente deveria ser válido para todos os projetos da organização </li></ul></ul></ul><ul><ul><li>simplifique a captura ( catch ) </li></ul></ul><ul><ul><ul><li>evitar uma lista longa de catch es </li></ul></ul></ul><ul><ul><li>detalhe a causa para gerar a exceção </li></ul></ul><ul><ul><ul><li>expressão ou condição que provocou o throw </li></ul></ul></ul><ul><ul><li>determine onde foi e por que foi sinalizada a exceção </li></ul></ul><ul><ul><ul><li>módulo, linha de código onde se encontra o throw </li></ul></ul></ul><ul><ul><li>forneça informação de contexto do ponto da sinalização </li></ul></ul><ul><ul><ul><li>ex. pilha de execução, se der </li></ul></ul></ul>Teste de exceções
  70. 70. Teste de exceções
  71. 71. Teste de exceções <ul><li>Como testar exceções? </li></ul>
  72. 72. Teste de exceções: instrumentação Forçar ocorrência de erro
  73. 73. Teste de exceções: arcabouço teste C++ <ul><li>== Add numbers of different size, should generate loss of data </li></ul><ul><li>=ConvertIntToBCD 0 4 -3785328 </li></ul><ul><li>=ConvertIntToBCD 1 5 108303031 </li></ul><ul><li>=Add 0 1 </li></ul><ul><li>=ExceptionProgram 0 lossOfData 'c' </li></ul><ul><li>== Convert 10 siz 1 to BCD, should generate overflow exception </li></ul><ul><li>=ConvertIntToBCD 0 1 10 </li></ul><ul><li>=ExceptionProgram 0 overflow 'c' </li></ul><ul><li>----------------------- </li></ul><ul><li>46 == Add numbers of different size, should generate loss of data </li></ul><ul><li>>>> 1 Line 49 Tester caught a program exception >> </li></ul><ul><li>ERROR: Loss of data while assigning a BCD number . </li></ul><ul><li>Exception thrown in Line: 536 File: ..sourcescdarit.cpp </li></ul><ul><li><<< 0 Line 50 Expected exception has been ignored. </li></ul><ul><li>106 == Convert 10 siz 1 to BCD, should generate overflow </li></ul><ul><li>>>> 1 Line 107 Tester caught a program exception >> </li></ul><ul><li>ERROR: Overflow in BCD conversion </li></ul><ul><li>Exception thrown in Line: 161 File: ..sourcescdarit.cpp </li></ul><ul><li><<< 0 Line 108 Expected exception has been ignored. </li></ul>
  74. 74. Teste de exceções <ul><li>Assegurar que </li></ul><ul><ul><li>cada throw foi executado pelo menos uma vez no conjunto de todos os casos de teste </li></ul></ul><ul><ul><li>cada catch foi executado uma vez no conjunto de todos os casos de teste </li></ul></ul><ul><li>Problema </li></ul><ul><ul><li>provocar throws pode ser “fácil” ao testar módulos </li></ul></ul><ul><ul><li>mas testar o par throw => catch pode ser bastante difícil </li></ul></ul><ul><ul><li>o ponto em que se encontra o throw pode distar muito (caminho longo de chamadas) do ponto em que se encontra o correspondente catch </li></ul></ul><ul><ul><ul><li>envolve muitas classes ou módulos </li></ul></ul></ul><ul><ul><ul><li>torna-se difícil forçar a ocorrência da causa </li></ul></ul></ul><ul><ul><ul><li>é difícil também forçar causas que são detectadas pelo interpretador (Java, C#) ou pelo run-time (C++) </li></ul></ul></ul>
  75. 75. Teste de exceções: análise estática <ul><li>Cria-se o grafo de estrutura do código completo: </li></ul><ul><ul><li>procure envolver todos os módulos </li></ul></ul><ul><ul><ul><li>se der: todas as bibliotecas </li></ul></ul></ul><ul><ul><ul><li>se existe byte code (Java, .Net) pode-se criá-lo a partir do byte code </li></ul></ul></ul><ul><ul><ul><li>como tratar redefinições de funções (herança)? </li></ul></ul></ul><ul><ul><ul><ul><li>conservador: todas as possibilidades de herdar </li></ul></ul></ul></ul><ul><ul><li>para cada throw percorrer o grafo em ordem inversa da ativação até atingir o correspondente catch </li></ul></ul><ul><ul><ul><li>se não encontrar  defeito grave </li></ul></ul></ul><ul><ul><ul><li>se encontrar: examinar se o tratador está em conformidade com o throw </li></ul></ul></ul><ul><ul><ul><ul><li>catch all nem sempre é uma boa solução </li></ul></ul></ul></ul><ul><ul><ul><ul><li>pode existir um catch inserido incorretamente (aspectos) </li></ul></ul></ul></ul><ul><ul><ul><ul><li>pode existir um throw inserido incorretamente => não obedece ao padrão </li></ul></ul></ul></ul>
  76. 76. Recursos locais e exceções <ul><li>Recursos locais e exceções </li></ul><ul><ul><li>ao terminar um método através de uma exceção os recursos ancorados localmente não são liberados </li></ul></ul><ul><ul><li>recursos alocados localmente são uma potencial fonte de vazamento de recursos </li></ul></ul>
  77. 77. Recursos locais e exceções <ul><li>Solução Java: </li></ul><ul><li>use a construção try{ ... } finally{ ... } </li></ul><ul><ul><li>as referências para recursos são declaradas null </li></ul></ul><ul><ul><li>os recursos locais são alocados </li></ul></ul><ul><ul><li>o bloco try contém o código que potencialmente pode gerar exceções </li></ul></ul><ul><ul><ul><li>se um recurso é transferido para uma estrutura com âncora externa ao método, a referência deve passar a ser null </li></ul></ul></ul><ul><ul><li>os recursos locais são desalocados pelo bloco finally </li></ul></ul>
  78. 78. Recursos locais e exceções <ul><li>Solução C++: </li></ul><ul><ul><li>use objetos locais ao invés de referências para objetos </li></ul></ul><ul><ul><ul><li>CAlgo AlgumObjeto ; </li></ul></ul></ul><ul><ul><li>se necessário crie um struct encapsulado que contenha as referências e o respectivo destrutor e aloque uma instância (objeto) local deste struct . Esboço: </li></ul></ul><ul><ul><ul><li>struct SAncora { </li></ul></ul></ul><ul><ul><ul><li>CRecurso * pRecurso ; </li></ul></ul></ul><ul><ul><ul><li>SAncora( ){ pRecurso = NULL ; } </li></ul></ul></ul><ul><ul><ul><li>~SAncora( ){ delete pRecurso ; } </li></ul></ul></ul><ul><ul><ul><li>} ; // struct </li></ul></ul></ul><ul><ul><ul><li>SAncora Ancora ; </li></ul></ul></ul><ul><ul><ul><li>Ancora.pRecurso = new CRecurso( ) ; </li></ul></ul></ul><ul><li>Bjarne Stroustrup's C++ Style and Technique FAQ http://www.research.att.com/~bs/bs_faq2.html </li></ul>
  79. 79. Recursos locais e exceções <ul><li>#include <stdio.h> </li></ul><ul><li>class CRecurso { </li></ul><ul><li>public: int X ; </li></ul><ul><li>public: CRecurso( ) { X = 10 ; } </li></ul><ul><li>public: ~CRecurso( ) { printf( &quot; Destruiu CRecurso&quot; ) ; } </li></ul><ul><li>public: void Mata( ) { throw &quot;abcd&quot; ; } </li></ul><ul><li>} ; </li></ul><ul><li>int UmaFunc( ) { </li></ul><ul><li>struct SAncora { </li></ul><ul><li>CRecurso * pRecurso ; </li></ul><ul><li>SAncora( ){ pRecurso = NULL ; printf( &quot; Construiu ancora&quot; ) ; } </li></ul><ul><li>~SAncora( ){ delete pRecurso ; printf( &quot; Destruiu ancora&quot; ) ; } </li></ul><ul><li>} Ancora ; // struct </li></ul><ul><li>Ancora.pRecurso = new CRecurso( ) ; </li></ul><ul><li>Ancora.pRecurso->Mata( ) ; </li></ul><ul><li>return Ancora.pRecurso->X ; </li></ul><ul><li>} // UmaFunc </li></ul>void main( ) { try { printf( &quot; Recurso: %d&quot;, UmaFunc( )) ; } catch ( ... ) { printf( &quot; Cancelou com throw&quot; ) ; } }
  80. 80. Módulos dublê <ul><li>Módulo dublê ( test double , analogia: stunt double ) é um módulo que toma o lugar de outro durante os testes </li></ul><ul><ul><li>visa auxiliar o teste automatizado </li></ul></ul><ul><li>Tipos de módulos dublê </li></ul><ul><ul><li>controle ( driver ) – controla a realização do teste </li></ul></ul><ul><ul><ul><li>não é bem um dublê... </li></ul></ul></ul><ul><ul><ul><li>módulo de teste específico, arcabouço de apoio ao teste </li></ul></ul></ul><ul><ul><li>fictício ( dummy ) – são dados e objetos passados mas nunca usados, ex. enchimento de lista de parâmetros </li></ul></ul><ul><ul><li>simulado ( fake ) – implementam alguma funcionalidade mas de forma simplificada, ex. base de dados residente em memória </li></ul></ul><ul><ul><li>enchimento ( stub ) – geram respostas, em geral fixas </li></ul></ul><ul><ul><li>imitação ( mock object ) – implementam uma simulação da especificação </li></ul></ul>
  81. 81. Módulos dublê: exemplo de enchimento <ul><li>int F( int ParametroX ) { return 10 ; } </li></ul><ul><li>int G( int ParametroX ) { return ParametroX / 2 ; } </li></ul><ul><li>int H( int ParametroX ) </li></ul><ul><li>{ </li></ul><ul><li>tpElem * pElem = ProcurarTabela( ParametroX ) ; </li></ul><ul><li>if (pElem == NULL ) throw new CException( MsgErroParametro ) ; </li></ul><ul><li>return pElem->valRetorno </li></ul><ul><li>} </li></ul><ul><li>int L( int ParametroX ) </li></ul><ul><li>{ </li></ul><ul><li>int numLidos = RDR_ReadLine( &quot; ii &quot; , &Controle , &Valor ) ; </li></ul><ul><li>if ( ( Controle != ParametroX ) || ( numLidos != 2 )) </li></ul><ul><li>throw new CException( MsgErroSincronismo) ; </li></ul><ul><li>return Valor ; </li></ul><ul><li>} </li></ul>a ser tratada pelo arcabouço de teste
  82. 82. Módulos dublê: módulos de imitação <ul><li>Quando utilizar módulos (objetos) de imitação? </li></ul><ul><ul><li>o objeto real possui comportamento não determinístico </li></ul></ul><ul><ul><ul><li>permite seqüenciar os eventos </li></ul></ul></ul><ul><ul><li>o objeto real é trabalhoso para ser construído </li></ul></ul><ul><ul><li>o objeto real possui comportamento difícil de provocar </li></ul></ul><ul><ul><ul><li>exemplo: erros de comunicação </li></ul></ul></ul><ul><ul><li>o objeto real é lento </li></ul></ul><ul><ul><li>o objeto real é ou contém interface com o usuário </li></ul></ul><ul><ul><li>o teste precisa controlar a forma com que usa o objeto </li></ul></ul><ul><ul><ul><li>protocolo de interação </li></ul></ul></ul><ul><ul><ul><li>uso de uma função de call back </li></ul></ul></ul><ul><ul><li>o objeto real ainda não existe </li></ul></ul><ul><ul><ul><li>desenvolvimento de software embarcado </li></ul></ul></ul><ul><ul><ul><li>desenvolvimento com várias equipes </li></ul></ul></ul>
  83. 83. Módulos dublê: módulos de imitação <ul><li>Exemplo </li></ul><ul><li>public void testProcurarPedido( ) </li></ul><ul><li>{ </li></ul><ul><li>Database db = new MockDatabase( ) ; </li></ul><ul><li>db.expectQuery( &quot; select idPedido from Pedidos where </li></ul><ul><li>idCliente is 123 &quot; ) ; </li></ul><ul><li>db.returnResult( &quot; Pedido 2 &quot; , &quot; Pedido 3 &quot; ) ; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul>
  84. 84. Módulos dublê: módulos de imitação void * CED_Malloc( size_t Tamanho , int Linha , char * NomeArquivo ) { tpElemListaEspacos * pEspaco ; if ( LimiteMemoria > 0 ) { if ( LimiteMemoria < EspacoTotalAlocado + ( long ) Tamanho ) { return NULL ; ou throw exceção de falta de memória } /* if */ } /* if */ if ( LimiteNumEspacos > 0 ) { if ( numEspacosAlocados >= LimiteNumEspacos ) { return NULL ; } /* if */ } /* if */ pEspaco = ( tpElemListaEspacos * ) malloc( sizeof( tpElemListaEspacos ) + Tamanho ) ; if ( pEspaco == NULL ) { return NULL ; } /* if */ #define malloc CED_Malloc( Tam , __LINE__ , __FILE__ )
  85. 85. Módulos dublê: módulos de imitação <ul><li>public interface Ambiente { </li></ul><ul><li>public long getTime( ) ; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>--- Implementação de produção </li></ul><ul><li>public class Contexto implements Ambiente { </li></ul><ul><li>public long getTime( ) { </li></ul><ul><li>return System.currentTimeMillis( ) ; </li></ul><ul><li>} </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>--- Implementação de imitação </li></ul><ul><li>public class MockContexto implements Ambiente { </li></ul><ul><li>private long currentTime ; </li></ul><ul><li>public long getTime( ) { return currentTime ; } </li></ul><ul><li>public void setTime( long aTime ) { currentTime = aTime ; } </li></ul><ul><li>... </li></ul><ul><li>} </li></ul>
  86. 86. Módulos dublê: módulos de imitação <ul><li>public class OrderEasyTester extends TestCase { </li></ul><ul><li>private static String TALISKER = &quot;Talisker&quot;; </li></ul><ul><li>private MockControl warehouseControl; </li></ul><ul><li>private Warehouse warehouseMock; </li></ul><ul><li>public void setUp() { </li></ul><ul><li>warehouseControl = MockControl.createControl(Warehouse.class); </li></ul><ul><li>warehouseMock = (Warehouse) warehouseControl.getMock(); </li></ul><ul><li>} </li></ul><ul><li>public void testFillingRemovesInventoryIfInStock() { </li></ul><ul><li>//setup - data </li></ul><ul><li>Order order = new Order(TALISKER, 50); </li></ul><ul><li>//setup - expectations </li></ul><ul><li>warehouseMock.hasInventory(TALISKER, 50); </li></ul><ul><li>warehouseControl.setReturnValue(true); </li></ul><ul><li>warehouseMock.remove(TALISKER, 50); </li></ul><ul><li>warehouseControl.replay(); </li></ul><ul><li>//exercise </li></ul><ul><li>order.fill(warehouseMock); </li></ul><ul><li>//verify </li></ul><ul><li>warehouseControl.verify(); </li></ul><ul><li>assertTrue(order.isFilled()); } </li></ul>record / replay metaphor extraído de Fowler, M.; Mocks Aren’t Stubs
  87. 87. Módulos dublê: módulos de imitação <ul><li>Existem diversas bibliotecas MockObject disponíveis </li></ul><ul><ul><li>http://www.easymock.org </li></ul></ul><ul><ul><li>http://www.jMock.org </li></ul></ul><ul><ul><li>http://www.nMock.org </li></ul></ul><ul><ul><li>.NET EasyMock http://sourceforge.net/projects/easymocknet/ </li></ul></ul><ul><ul><li>... ? </li></ul></ul>
  88. 88. Referências bibliográficas <ul><li>Beck, K.; Test-Driven Development by Example ; Reading, Massachusetts: Addison-Wesley; 2003 </li></ul><ul><li>Delamaro, M.E.; Maldonado, J.C.; Jino, M.; Introdução ao Teste de Software ; Rio de Janeiro, RJ: Elsevier / Campus; 2007 </li></ul><ul><li>Fowler, M.; Mocks Aren’t Stubs ; Buscado em: 23/09/2008; URL: martinfowler.com/articles/mocksArentStubs.html </li></ul><ul><li>Hunt, A.; Thomas, D.; Pragmatic Unit Test: in Java with JUnit ; Raleigh, North Carolina: The Pragmatic Bookshelf; 2004 </li></ul><ul><li>Mackinnon, T.; Freeman, S.; Craig, P.; “ Endo-Testing: Unit Testing with Mock Objects ”; in: Succi, G.; Marchesi, M.; eds.; Extreme Programming Examined ; Reading, Massachusetts: Addison-Wesley; 2001; pags 287-302; Buscado em: 25/10/2005; URL: http://www.connextra.com/aboutUs/mockobjects.pdf </li></ul><ul><li>Myers, G.J.; The Art of Software Testing , 2nd edition; New York: John Wiley & Sons; 2004 </li></ul><ul><li>Staa, A.v.; Programação Modular ; Rio de Janeiro, RJ: Elsevier / Campus; 2000 </li></ul>
  89. 89. <ul><li>FIM </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×