Modulo 2

273 visualizações

Publicada em

0 comentários
0 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Sem downloads
Visualizações
Visualizações totais
273
No SlideShare
0
A partir de incorporações
0
Número de incorporações
2
Ações
Compartilhamentos
0
Downloads
2
Comentários
0
Gostaram
0
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Modulo 2

  1. 1. Testes de Software Prof. Rodrigo de Barros Paes rodrigo@ic.ufal.br
  2. 2. Cobertura de testes rodrigo@ic.ufal.br 2
  3. 3. Ubuntu release o Ubuntu 12.04 LTS oA primeira release estável só começou no .04 o Logo depois do lançamento oBugs, bugs e mais bugs rodrigo@ic.ufal.br 3
  4. 4. Não é assim com quase todos os software o Por que que os desenvolvedores lançam uma release com bugs? oParece que o trabalho dos testadores falhou ao não encontrar os erros não é? oParece que algumas partes do código foram esquecidas pelos desenvolvedores e testadores rodrigo@ic.ufal.br 4
  5. 5. Cobertura o Iremos ver algumas técnicas que ajudam a identificar o quanto executamos do nosso código fonte sob teste o Cuidado “Our results suggest that coverage, while useful for identifying under-tested parts of a program, should not be used as a quality target because it is not a good indicator of test suite efectiveness.” Inozemtseva, Laura, and Reid Holmes. "Coverage Is Not Strongly Correlated With Test Suite Effectiveness.“, ICSE 2014 http://www.linozemtseva.com/research/2014/icse/coverage/coverage_paper.pdf rodrigo@ic.ufal.br 5
  6. 6. Quanto teste é suficiente? o A gente começa a testar, gasta um bom tempo e se sente confiante que fez um bom trabalho rodrigo@ic.ufal.br 6
  7. 7. Mas ... o De repente alguma coisa esquisita acontece e o nosso software falha! o Na prática, esquecemos de testar alguma parte do nosso domínio da entrada rodrigo@ic.ufal.br 7
  8. 8. Ideia o A ideia é termos algumas métricas que nos digam, por exemplo: oVocê está indo bem, seu score de cobertura é 14/100 oOu ainda: o Você não executou a linhas 35, 70 e 195 da sua classe Queue rodrigo@ic.ufal.br 8
  9. 9. Voltando um pouco para discutir a partição do domínio o Não é viável testar com todas as possíveis entradas Domínio da entrada Contra-domínio (saídas) rodrigo@ic.ufal.br 9
  10. 10. Suponha ainda o Mesmo que você abstraia e considere classes do seu domínio de entrada o Suponha também que você tem acesso ao: oCódigo do software que você irá testar oEspecificações oE tudo o mais que você precise para criar as melhores partições possíveis do seu domínio da entrada rodrigo@ic.ufal.br 10
  11. 11. Logo ... o Você pega um ponto da partição, testa, analisa o resultado obtido e se for igual ao esperado, ok! O sistema se comportou corretamente o Mas em alguns casos, o sistema irá falhar, mesmo para pontos diferentes dentro de uma mesma partição o Ou seja ... Descobrimos uma outra partição dentro da partição que a gente achava que era a melhor o ... E culpamos a escolha da partição o Só que esse processo vira um loop ... É difícil encontrar boas partições ... E pior ainda é difícil medir (cobertura do domínio ???) rodrigo@ic.ufal.br 11
  12. 12. Cobertura o Na prática, a gente faz um pouco diferente e acaba particionando também o domínio ... mas como consequência o Mais fácil com exemplo ... Próximo slide rodrigo@ic.ufal.br 12
  13. 13. Cobertura de funções o Você terá 100% de cobertura de funções se todas as funções do seu sistema forem executadas durante os testes o Por exemplo, você pode fazer um teste que executa, por exemplo, 181 das 250 funções do seu código o Essa métrica 181/250 é uma das métricas de cobertura rodrigo@ic.ufal.br 13
  14. 14. Ou seja, o Você teve que escolher elementos do seu domínio que exercitassem as funções do seu código o As funções geraram saídas (contra-domínio) o Ou seja, ao tentar cobrir as funções, você cobriu uma parte do domínio e do contra-domínio de valores oMas o foco foi na cobertura das funções oE não em tentar cobrir todo o domínio rodrigo@ic.ufal.br 14
  15. 15. Existem várias formas de medir a cobertura o Cobertura de função o Cobertura de comandos o Cobertura de linhas o Cobertura de ramos o Cobertura de loops o Cobertura Modified Condition/Decision Condition rodrigo@ic.ufal.br 15
  16. 16. Iremos explorar cada uma delas ... o ... mas primeiro ... o... Um exemplo o Uma árvore de busca binária rodrigo@ic.ufal.br 16
  17. 17. Operações o insert (key) rodrigo@ic.ufal.br 17
  18. 18. find (key) rodrigo@ic.ufal.br 18
  19. 19. delete (key) o 3 casos oRemovendo uma folha rodrigo@ic.ufal.br 19
  20. 20. delete (key) o 3 casos oNó com um filho rodrigo@ic.ufal.br 20
  21. 21. delete (key) o 3 casos oNó com 2 filhos rodrigo@ic.ufal.br 21
  22. 22. Lets code it o Não esqueçam de fazer os testes unitários enquanto codificam rodrigo@ic.ufal.br 22
  23. 23. Agora vamos incrementar um pouco o Uma splay tree (com algumas simplificações) oÁrvore de busca binária oAuto ajustável oElementos mais acessados são acessados mais rápidos o Eles sobem para o topo da árvore rodrigo@ic.ufal.br 23
  24. 24. Ideia o Combinar as operações normais (insert e find) com uma nova operação oSplay o Responsável por levar para o topo da árvore o elemento inserido ou buscado o Ela faz uso da rotação de árvores rodrigo@ic.ufal.br 24
  25. 25. Como rotacionar uma árvore? o Mudar a estrutura da árvore sem interferir na ordem dos elementos rodrigo@ic.ufal.br 25
  26. 26. Consequências da rotação o Você só poderá rotacionar p se ele tiver um pai o Se P já é filho esquerdo de Q, não dá pra rodar pra esquerda, por exemplo o Se Q tiver um pai, ele precisará ser atualizado para apontar para P e P para ser filho ele rodrigo@ic.ufal.br 26
  27. 27. Primeira tarefa o Implementar oright_rotate(self, node) oleft_rotate(self, node) rodrigo@ic.ufal.br 27
  28. 28. O splay (simplificado) o Iremos rotacionar o nó até ele chegar na raiz o Por exemplo: 28 8 4 9 3 6 5 7 right 8 left 5 4 9 3 5 7 6 8 5 9 4 7 6 3 4 8 3 7 6 right 9
  29. 29. Escreva os seus testes rodrigo@ic.ufal.br 29
  30. 30. Cobertura dos testes que você fez o Vamos dar uma olhada na cobertura dos testes que você fez o Para isso, iremos usar uma ferramenta do Python o O Python Coverage irá contar quantos comandos foram executados em relação ao total o Cobertura de comandos rodrigo@ic.ufal.br 30
  31. 31. Python coverage (http://nedbatchelder.com/code/coverage/) o pip install coverage o Verifique se a pasta Script dentro do python está no seu path, se não estiver coloque. Por exemplo, no meu computador essa pasta é: D:python3.3Scripts o Vá para o diretório que você fez o caso de teste o coverage run my_tests.py o Troque my_tests.py pelo nome do seu script de testes o coverage html o Ele vai gerar um diretório chamado htmlcov o Abra o arquivo index.html para ver os resultados o Apagar resultados anteriores: coverage erase o Resultado em outro formato: coverage report -m rodrigo@ic.ufal.br 31
  32. 32. Rodou os testes instrumentados com a ferramenta de cobertura? o Provavelmente a cobertura não deu 100% o Espere .... não codifique mais testes para obter os 100% ainda o Identifique por que os comandos não foram executados? o Era um código que você julgou que não precisava ser testado? o Você não conseguiu pensar nessa situação? o Ué ... ele deveria ter executado esse comando  rodrigo@ic.ufal.br 32
  33. 33. O que ele nos diz? o O teste de cobertura nos diz o que não testamos o Ele deve sempre gerar uma reflexão da causa do “esquecimento” oNão saia tentando obter 100% de cobertura sem fazer essa reflexão rodrigo@ic.ufal.br 33
  34. 34. Melhore os seus testes o Se você julgou que esqueceu de testar algumas situações importantes o Melhore os seus casos de teste rodrigo@ic.ufal.br 34
  35. 35. 100% o Você obteve 100% de cobertura de comandos o Logo seu código está livre de bugs, certo? oClaro que não oAinda podem existir muitos membros do seu domínio de teste que podem disparar um bug rodrigo@ic.ufal.br 35
  36. 36. Exemplo rodrigo@ic.ufal.br 36 import math def is_prime(number): if number <= 1 or (number % 2) == 0: return False for check in range(3, int(math.sqrt(number))): if number % check == 0: return False return True
  37. 37. Testes import unittest from prime import is_prime class MyTestCase(unittest.TestCase): def test_is_prime(self): self.assertFalse(is_prime(1)) self.assertFalse(is_prime(2)) self.assertTrue(is_prime(3)) self.assertFalse(is_prime(4)) self.assertTrue(is_prime(5)) self.assertFalse(is_prime(20)) self.assertFalse(is_prime(21)) self.assertFalse(is_prime(22)) self.assertTrue(is_prime(23)) self.assertFalse(is_prime(24)) rodrigo@ic.ufal.br 37
  38. 38. Rodando a cobertura o coverage run test_prime.py o coverage html rodrigo@ic.ufal.br 38
  39. 39. Porém ... o A nossa função possui uma falta o Tente identificá-la o Quando descobrir, modifique o caso de teste para que a falta seja exercitada e se transforme em uma falha, que será “pega” pelo seu caso de teste o Só depois, corrija a falta rodrigo@ic.ufal.br 39
  40. 40. O teste que irá exercitar a falta import unittest from prime import is_prime class MyTestCase(unittest.TestCase): def test_is_prime(self): self.assertFalse(is_prime(9)) self.assertFalse(is_prime(25)) rodrigo@ic.ufal.br 40
  41. 41. A falta o for check in range(3, int(math.sqrt(number))): o Deveria ser: o for check in range(3, int(math.sqrt(number))+1): o Na função range, o primeiro parâmetro é inclusivo e o segundo exclusivo. Ou seja, se vc a chamar range(1,4), ele irá gerar o range: 1,2,3 rodrigo@ic.ufal.br 41
  42. 42. Mas o que aconteceu? o Tínhamos 100% de cobertura de comandos e ainda assim encontramos uma falta ?! o A cobertura de comandos ainda deixa passar várias situações oO comando pode executar mas retorna um valor errado oO loop pode executar, mas executa um número errado de iterações o... rodrigo@ic.ufal.br 42
  43. 43. Possíveis conclusões sobre esse processo o O fato de ter 100% cobertura de comandos não significa que o software está livre de faltas oSignifica apenas que ele executou todos os comandos o Quando deixamos de cobrir algum comando, o que realmente isso significa? oQue temos que escrever um casos de teste para executar esse comando? rodrigo@ic.ufal.br 43
  44. 44. Possíveis conclusões o Uma conclusão melhor seria oSignifica que a gente não pensou no problema direito oÉ melhor que a gente investigue porque que você não pensou naquele caso do que simplesmente sair escrevendo o casos de teste para executar o comando que foi deixado de lado rodrigo@ic.ufal.br 44
  45. 45. Métricas de cobertura rodrigo@ic.ufal.br 45
  46. 46. Quantas são? o Em [1], foram descritas 101 maneiras diferentes de medir a cobertura  o Mas vamos simplificar e falar apenas de 6 delas, consideradas as principais [1] Kaner, Cem. "Software negligence and testing coverage." Proceedings of STAR 96 (1996): 313. rodrigo@ic.ufal.br 46
  47. 47. Cobertura de comandos o Já vimos essa métrica através da ferramenta Python Coverage o Vamos só detalhar um pouco mais o Suponha: rodrigo@ic.ufal.br 47 if x == 0: y += 1 if y == 0: x += 1 Se chamarmos com: (x= 0, y= -1) obteremos 100% dos comandos executados (x=20, y=20) 2/4 executados, ou seja, 50%
  48. 48. Cobertura de linhas o Muito parecido com a cobertura de comandos o Mas conta as linhas ao invés de comandos o Logo, se o seu código tiver um comando por linha, as métricas serão iguais rodrigo@ic.ufal.br 48
  49. 49. Cobertura de linhas o Código em C: int do_something(int a, int b) { int c; if (a>b) c=a;else c=b; printf("%dn",c); o Independentemente dos valores de a e b obteremos 100% de cobertura de linha, mesmo que nem todos os comandos tenham sido executados rodrigo@ic.ufal.br 49 }
  50. 50. Quiz 1. Baixe esse código: http://goo.gl/M07GMb 2. Escreva um teste unitário class MyTestCase(unittest.TestCase): def test_stats(self): l = [31] my_map = stats(l) self.assertEqual(31,my_map["min"]) self.assertEqual(31,my_map["max"]) self.assertEqual(31,my_map["median"]) self.assertEqual([31],my_map["modes"]) 3. Modifique o teste unitário para obter 100% de cobertura de comandos rodrigo@ic.ufal.br 50
  51. 51. Quiz (continuação) 4. Insira uma falta na função “stats” de forma que a falta passe desapercebida pelo teste que você tinha escrito 5. Escreva outro teste que capture a falta que você inseriu rodrigo@ic.ufal.br 51
  52. 52. Uma possível solução o Introdução da falta oColocar um valor absoluto, assim irá ignorar os valores negativos oEssa falta não será detectada pelo teste já feito oVeja a linha 6: https://gist.github.com/r0drigopaes/401b298741c2fa88f70a o Testes para pegar a falta oVeja a linha 32: https://gist.github.com/r0drigopaes/be13f8557dd604b57b01 rodrigo@ic.ufal.br 52
  53. 53. Cobertura de ramos o É a métrica que se preocupa com os ramos da execução do seu código o Por exemplo, para obter 100% no ramo ... if (x == 0): y = y +1 o ... ele precisaria ser executado em ambas as possibilidades oCom x igual a 0 e com x diferente de 0 rodrigo@ic.ufal.br 53
  54. 54. Cobertura de ramos def foo(x,y): if x == 0: y += 1 if y == 0: x += 1 54 X == 0 Y == 0 Y += 1 X+=1 ... 4 ramos no total
  55. 55. Cobertura de ramos (python) o coverage run –branch seuarquivo.py o coverage html def foo(x,y): if x == 0: y += 1 if y == 0: x +=1 foo(0,1) rodrigo@ic.ufal.br 55
  56. 56. Como o coverage calcula? o coverage=execuções reais(er)/oportunidades de execução(oe) o oe = statements + branches o er = oe – (missing + partial) o Exemplo: o oe = 7 + 4 = 11 :: er = 11 – (2 + 2) = 7 :: logo o Coverage = 7/11 = 64% def foo(x,y): if x == 0: y += 1 if y == 0: x +=1 foo(0,1) rodrigo@ic.ufal.br 56
  57. 57. Ainda sobre o cálculo o oe = 8 + 4 = 12 o er = 12 – (3+2) =7 o Coverage = 7/12 = 58% def foo(x,y): if x == 0: y += 1 x += 2 if y == 0: x +=1 foo(0,1) rodrigo@ic.ufal.br 57
  58. 58. Informações úteis o Número da linha que não foi executada no ramo oNesse caso, o primeiro if nunca foi verdadeiro, pois não “pulou” para a linha 5 o E o segundo também não, pois não pulou para a linha 8 rodrigo@ic.ufal.br 58
  59. 59. Cobertura de loops o Conta se o “corpo” de um loop foi executado pelo menos o0 vezes o1 vez oMais de uma vez o A forma específica de contagem pode variar oO coverage não conta essa métrica rodrigo@ic.ufal.br 59
  60. 60. Cobertura de loops for loop in open("file"): process(line) o Para obter cobertura complete de loop: oArquivo sem nenhuma linha oArquivo com uma linha oArquivo com pelo menos 2 linhas rodrigo@ic.ufal.br 60
  61. 61. Complexidade Ciclomática o Ideia: medir a quantidade de decisões no código-fonte oQuanto menos decisões, mais simples de manter oTambém traz a noção de caminhos básicos independentes Thomas J. Mccabe; A Complexity Measure. IEEE Transactions on Software Engineering, 1976 http://dx.doi.org/10.1109/TSE.1976.233837 rodrigo@ic.ufal.br 61
  62. 62. Complexidade Ciclomática o Ver o programa como um grafo o Onde oe : arestas on: nós op: componentes conectados rodrigo@ic.ufal.br 62
  63. 63. Complexidade ciclomática o Sequência oV = 1 – 2 + 2 oV = 1 rodrigo@ic.ufal.br 63 A = 5+3; B = A+1;
  64. 64. Complexidade ciclomática o Decisão oV = 4 – 4 + 2 oV = 2 rodrigo@ic.ufal.br 64 if (a>b) { printf(“x”); } else { printf(“y”); } b = a+b;
  65. 65. Complexidade ciclomática o Decisão oV = 12 – 10 +2 oV = 4 rodrigo@ic.ufal.br 65
  66. 66. Teste baseado na complexidade ciclomática o Basis Path o Mas vamos explicar com um exemplo ... rodrigo@ic.ufal.br 66
  67. 67. Euclides euclid(int m, int n) { int r; if(n>m){ r = m; m = n; n = r; } r = m % n; while (r!=0){ m = n; n = r; r = m % n; } return n; 6 7 8 9 10 11 12 2 3 } rodrigo@ic.ufal.br 67 0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 1 5 13 4 V = 15 – 14 + 2 V = 3
  68. 68. Euclides euclid(int m, int n) { int r; if(n>m){ r = m; m = n; n = r; } r = m % n; while (r!=0){ m = n; n = r; r = m % n; } return n; 6 7 8 9 10 11 12 2 3 } rodrigo@ic.ufal.br 68 0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 1 5 13 4
  69. 69. Euclides o Qualquer caminho pode ser expresso como uma combinação linear de um “basis path” o Exemplo: o0 1 2 3 4 5 6 7 8 9 10 7 8 9 10 11 12 13 o= B2 – 2*B1 + 2*B3 0 1 5 6 7 8 9 10 11 12 13 2 3 4 rodrigo@ic.ufal.br 69
  70. 70. o [Mostrar as operações algébricas com matrizes] rodrigo@ic.ufal.br 70
  71. 71. MC/DC o Modified Condition Decision Coverage o Essa é mais fácil mostrando um exemplo: oif a or (b and c): print(“It is true!!”) oOu seja, a gente vai imprimir se a for verdade ou então b ou c rodrigo@ic.ufal.br 71
  72. 72. MC/DC Passo 1: em cada condição usada na decisão, procurar por aquelas que afetam a saída de forma independente A B C A or (B and C) True True True True True True False True True False True True True False False True False True True True False True False False False False True False False False False False a) Nesse caso, “fixe B e C” e mude o valor de A. b) Ele altera a saída? Se sim, esses dois seriam 2 casos de testes a) T, T, T e F, T, T rodrigo@ic.ufal.br 72
  73. 73. MC/DC Passo 1: em cada condição usada na decisão, procurar por aquelas que afetam a saída de forma independente A B C A or (B and C) True True True True True True False True True False True True True False False True False True True True False True False False False False True False False False False False a) Agora vamos tentar com B. Fixe A (True) e C(True) e varie B. b) Afetou a saída? Não. Tente outra possibilidade a) A(False), B(True), C(False) c) Altere somente B, de novo a) A(False), B(False), C(False) d) Alterou? a) Sim b) F, T, F e F, F, F rodrigo@ic.ufal.br 73
  74. 74. MC/DC A B C A or (B and C) True True True True True True False True True False True True True False False True False True True True False True False False False False True False False False False False rodrigo@ic.ufal.br 74 A mesma coisa para C a) A(False), B(True), C(True) b) Altere para a) A(False), B(True), C(False) c) F, T,T e F, T, F
  75. 75. MC/DC o Teríamos os seguintes casos de teste: oT, T, T e F, T, T oF, T, F e F, F, F oF, T,T e F, T, F oT, T, T e F, T, T oF, F, F rodrigo@ic.ufal.br 75
  76. 76. MC/DC o Usado em partes específicas de sistemas críticos o Não conheço nenhuma ferramenta para python rodrigo@ic.ufal.br 76

×