fabianoseller / testecaixapreta

Aprendizado de testes - explicação Marco
MIT License
0 stars 0 forks source link

Teste caixa-preta: introdução #2

Open fabianoseller opened 6 years ago

fabianoseller commented 6 years ago

image image image image image image image image

fabianoseller commented 6 years ago

Desvantagens Linhas de código não coberta IF e WHILE

Coloca-se testes onde não há especificação (complexidade sintomática) https://qualidadebr.wordpress.com/2009/03/26/resolucao-de-questoes-ctfl-q13s1/ complexidade ciclomatica

qualidadebr.wordpress.pdf LER ACIMA... Agora vamos para a questão…

Dado o seguinte programa:

1 IF X < Y

2 THEN Statement 1;

3 ELSE IF Y >= Z

4 THEN Statement 2;

5 END

A complexidade ciclomática de McCabe é :

a) 2

b) 3

c) 4

d) 5

Análise do código

Temos dois IFs, sendo que o segundo é dependente do primeiro, ou seja, a sua execução depende do resultado do primeiro IF, pois o segundo IF está associado ao ELSE do primeiro IF.

Acredito que essa história de primeiro e segundo IF, pode ter te deixado confuso querido(a) leitor(a). Então, vamos facilitar as coisas, abaixo segue o fluxo do código da questão:

Fluxo

Resolução

Temos duas maneiras de resolver essa questão: fazendo o fluxo com os caminhos lógicos possíveis (parecido com a figura acima), ou usando a fórmula da complexidade ciclomática.

Vamos primeiro para a maneira mais difícil, usando a fórmula:

M = E − N + 2P M= complexidade ciclomática E= número de arestas (linhas/caminhos) N= número de nodos P= número de componentes conectados

M= 6 – 5 + 2X1

M= 1 + 2

M =3

Portanto já sabemos que a complexidade ciclomática é igual a 3.

Agora vamos resolver essa mesma questão, de uma maneira mais simples e fácil: fluxoq13s01

Fluxo

Sabendo que a complexidade ciclomática medi o número de caminhos de uma determinada função. Fica claro na figura acima, que o código apresentado tem 3 caminhos lógicos possíveis:

Verde: X é menor que Y > executar o Statement 1 > END

Azul: X é maior que Y > Y é menos que Z > END

Vermelho: X é maior que Y > Y é maior igual que Z > THEN Statement 2 > END

E o motivo por eu achar a segunda maneira mais fácil é simples: eu dificilmente foi lembrar da fórmula da complexidade ciclomática na hora da prova. E como tenho certeza que a pessoa que irá aplicar o exame não irá colocar a fórmula na lousa (como nos tempos de escola), prefiro fazer o fluxo do código, afinal não vou esquecer de como faz círculos e retas, durante a prova.

Logicamente essa é minha opinião, se você acha melhor resolver usando a fórmula, tudo bem.

Resposta

Alternativa: b) 3

Por hoje é só pessoal. No próximo post irei resolver a questão 5 do simulado 2, a que o Clauriston comentou no post anterior. Até lá!

Atualização 13 de Novembro de 2009 Estava hoje dando uma olhada no artigo publicado pelo próprio McCabe, e vi que ele mesmo diz que é possível calcular a complexidade ciclomática de uma forma bem mais simples (e a Cristina até citou nos comentários).

Fórmula mágica:

Quantidade de decisões + 1 = complexidade ciclomática 😀

OBS.: Considerando a análise de um programa que tenha apenas um ponto de entrada e um de saída.

Trecho retirado do artigo: “This proves that the cyclomatic complexity of a structured program equals the number of predicates plus one […]”

Fica aí a dica!

fabianoseller commented 6 years ago

Conceitos de Programação: Complexidade Ciclomática November 12th, 2008 § 5 comments http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/

Este é o quarto artigo em uma série sobre conceitos de programação. Os demais artigos podem ser encontrados na página de resumo sobre a série. Como nos demais artigos, um aviso: o tratamento dado aos assuntos aqui é informativo e podem existir erros nos mesmos. Como nos demais artigos neste blog, comentários e correções são sempre bem-vindos.

Complexidade Ciclomática Neste quarto artigo, vamos tratar um pouco de complexidade ciclomática. Apesar do nome esdrúxulo, complexidade ciclomática (também conhecida como complexidade condicional) é uma métrica simples para determinar, como o próprio nome sugere, a complexidade de um programa estruturado (cíclico).

Essa métrica foi desenvolvida em 1976 por Thomas J. McCabe e reflete diretamente o número de caminhos independentes que um programa pode tomar durante a sua execução.

Qualquer desenvolvedor que já tenha testado código em sua vida, sabe que a quantidade de testes necessária para exercitar um determinado trecho de código é diretamente proporcional à sua árvore decisória. Em outras palavras, quanto mais caminhos o código puder tomar (seja por meios de condicionais ou loops), maior a quantidade de testes necessários. E como veremos abaixo, há realmente uma relação direta entre a complexidade ciclomática e a cobertura de um código.

Calculando a complexidade ciclomática Antes de mostrar exatamente como o cálculo pode ser feito, vamos observar algumas coisas em relação a um programa qualquer. Digamos que você esteja desenvolvendo um programa que lhe dê o maior divisor comum entre dois números. Uma fórmula simples é o algoritmo de Euclides que pode ser descrito da seguinte forma:

Dados dois números naturais a e b, verifique se b é zero. Se sim, a é o maior divisor comum entre os mesmos; caso contrário, repita o processo usando b e o resto da divisão de a por b.

Esse algoritmo pode ser expresso pelo seguinte programa em Ruby (note que ele não está em Ruby idiomático):

require "test/unit"

def euclid(m, n) if n > m r = m m = n n = r end r = m % n while r != 0 m = n n = r r = m % n end n end

class EuclidTest < Test::Unit::TestCase

SETS = [[5, 10, 5], [2, 6, 2], [11, 7, 1], [80, 64, 16], [2, 2, 2]]

def test_euclid SETS.each do |set| assert_equal set[2], euclid(set[0], set[1]) end end

end Se o programa acima for executado, ele rodará o caso de teste logo abaixo da função que verificará se a mesma está correta. Você pode adicionar mais casos ao conjunto SETS se desejar.

A função euclid pode ser descrita por um grafo simples que conecta os caminhos entre as várias declarações que a mesma contém. Esse grafo é o mostrado abaixo (clique para expandir):

Com base nesse grafo, podemos definir a complexidade ciclomática de um programa da seguinte forma:

CC = A - N + 2C Nessa fórmula:

CC é a complexidade ciclomática A é o número de arestas do grafo N é o número de nós do grafo C é o número de componentes conectados Como se trata de uma função simples com um único ponto de entrada e saída, o número de componentes é 1 e a fórmula pode ser reduzida para:

CC = A - N + 2 Se a função possuísse múltiplos pontos de saída, entretanto, a complexidade ciclomática seria definida como:

CC = A - N + C + R Nessa fórmula, R é o número de declarações de saída (em Ruby, o número de returns).

Voltando ao grafo mostra na figura, vemos que o mesmo possui 11 nós e 12 arestas, o que nós dá uma complexidade ciclomática de 12 - 11 + 2, ou seja, 3.

Uma outra maneira bem simples de descobrir a complexidade ciclomática é contar o número de loops fechados no grafo (que são formados por condicionais e loops) e somar ao número de pontos de saída. No grafo acima, temos 2 loops fechados (os if e while) e um ponto de saída, resultando no mesmo valor 3 para a complexidade da função.

Uma coisa interessante é que a complexidade permanece a mesma quando a sintaxe de uma linguagem é levada em questão sem alterar a semântica do programa. Tome por exemplo a versão idiomática do algoritmo em Ruby:

def euclid(m, n) m, n = n, m if n > m m, n = n, m % n while m % n != 0 n end O grafo gerado nesse caso é (clique para expandir):

Node que embora o número de nós e arestas tenha mudado, a relação entre eles não mudou e a complexidade permanece a mesma.

Testando De uma forma geral, o valor da complexidade ciclomática define um limite superior para a quantidade de testes necessários para cobrir todos os caminhos decisórios no código em questão. Esse é um limite superior já que nem todos os caminhos são necessariamente realizáveis.

Disso se infere que quanto menor a complexidade, menor a quantidade de testes necessários para o método em questão. Esse fato implica em outro curioso: quebra um método em vários reduz a complexidade dos métodos mas aumenta a complexidade geral do código e, de forma geral, mantém a testabilidade do programa completo no mesmo nível.

Referências Obviamente, já que a complexidade é um valor específico, é possível extrair da mesma uma referência. Baseado no trabalho de McCabe, esses valores de referência são:

1-10, métodos simples, sem muito risco 11-20, métodos medianamente complexos, com risco moderado 21-50, métodos complexos, com risco alto 51 ou mais, métodos instáveis de altíssimo risco Conclusão Essa foi uma pequena introdução ao assunto com o objetivo de abrir o caminho para artigos posteriores mostrando ferramentas de apoio ao cálculo e monitoramento da complexidade ciclomática. Como de usual, sugestões e correções são bem vindos.

Tagged Tecnologia

§ 5 Responses to Conceitos de Programação: Complexidade Ciclomática" Rafael Ferreira Silva November 24, 2008 at 10:19 am Muito bom o artigo. É interessante notar que a complexidade não está associada ao código que é uma espécie de contra-senso para muita gente.

Jeveaux’s Weblog » Arquivo » Complexidade Ciclomática em Java December 2, 2008 at 10:40 pm […] Ciclomática em Java December 2nd, 2008 por jeveaux Há alguns dias o Ronaldo postou sobre conceitos de complexidade ciclomática (ótima leitura) e como analisar a complexidade ciclomática do seu código Ruby com o Saikuro e […]

Resolução de questões CTFL: Q13S1 « QualidadeBR November 13, 2009 at 3:37 pm

[…] http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/ […]

http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/

Paulo

fabianoseller commented 6 years ago

http://basedetestedesoftware.blogspot.com/