Pergunta

Gostaria de testar uma função com uma tupla de um conjunto de casos extremos e valores normais.Por exemplo, ao testar uma função que retorna true sempre que fossem dados três comprimentos que formassem um triângulo válido, eu teria casos específicos, números negativos/pequenos/grandes, valores próximos de serem estourados, etc.;além disso, o objectivo principal é gerar combinações destes valores, com ou sem repetição, a fim de obter um conjunto de dados de teste.

(inf,0,-1), (5,10,1000), (10,5,5), (0,-1,5), (1000,inf,inf),
...

Como nota:Na verdade, eu sei a resposta para isso, mas pode ser útil para outras pessoas e um desafio para as pessoas aqui!--irá postar minha resposta mais tarde.

Foi útil?

Solução

Com certeza, especialmente lidando com muitas dessas permutações/combinações, posso definitivamente ver que a primeira passagem seria um problema.

Implementação interessante em python, embora eu tenha escrito uma boa em C e Ocaml baseada no "Algoritmo 515" (veja abaixo).Ele escreveu o seu em Fortran, como era comum naquela época para todos os artigos do "Algoritmo XX", bem, aquele assembly ou c.Tive que reescrevê-lo e fazer algumas pequenas melhorias para trabalhar com matrizes e não com intervalos de números.Este faz acesso aleatório, ainda estou trabalhando para obter algumas boas implementações daquelas mencionadas no fascículo 2 do quarto volume de Knuth.Vou explicar ao leitor como isso funciona.Embora se alguém estiver curioso, eu não me oporia a escrever algo.

/** [combination c n p x]
 * get the [x]th lexicographically ordered set of [p] elements in [n]
 * output is in [c], and should be sizeof(int)*[p] */
void combination(int* c,int n,int p, int x){
    int i,r,k = 0;
    for(i=0;i<p-1;i++){
        c[i] = (i != 0) ? c[i-1] : 0;
        do {
            c[i]++;
            r = choose(n-c[i],p-(i+1));
            k = k + r;
        } while(k < x);
        k = k - r;
    }
    c[p-1] = c[p-2] + x - k;
}

~"Algoritmo 515:Geração de um Vetor a partir do Índice Lexicográfico”;Fivelas, B.P. e Lybanon, M.Transações ACM em Software Matemático, Vol.3, não.2, junho de 1977.

Outras dicas

Com o novo Python 2.6, você tem uma solução padrão com o módulo itertools que retorna o produto cartesiano de iteráveis:

import itertools

print list(itertools.product([1,2,3], [4,5,6]))
   [(1, 4), (1, 5), (1, 6),
   (2, 4), (2, 5), (2, 6),
   (3, 4), (3, 5), (3, 6)]

Você pode fornecer um argumento de "repetição" para executar o produto com um iterável e ele mesmo:

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]

Você também pode ajustar algo com combinações:

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

E se a ordem importa, existem permutações:

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
   (2, 1), (2, 3), (2, 4),
   (3, 1), (3, 2), (3, 4),
   (4, 1), (4, 2), (4, 3)]

É claro que todas essas coisas legais não fazem exatamente a mesma coisa, mas você pode usá-las de uma forma ou de outra para resolver seu problema.

Lembre-se de que você pode converter uma tupla ou lista em um conjunto e vice-versa usando list(), tuple() e set().

Pergunta interessante!

Eu faria isso escolhendo combinações, algo como o seguinte em python.A parte mais difícil é provavelmente a primeira verificação, ou seja, if f(1,2,3) returns true, esse é um resultado correto?Depois de verificar isso, esta é uma boa base para testes de regressão.

Provavelmente é uma boa ideia criar um conjunto de casos de teste que você sabe que serão todos verdadeiros (por exemplo,3,4,5 para este caso triangular) e um conjunto de casos de teste que você sabe que serão todos falsos (por exemplo0,1,inf).Então você poderá verificar mais facilmente se os testes estão corretos.

# xpermutations from http://code.activestate.com/recipes/190465
from xpermutations import *

lengths=[-1,0,1,5,10,0,1000,'inf']
for c in xselections(lengths,3):        # or xuniqueselections
    print c
(-1,-1,-1);
(-1,-1,0);
(-1,-1,1);
(-1,-1,5);
(-1,-1,10);
(-1,-1,0);
(-1,-1,1000);
(-1,-1,inf);
(-1,0,-1);
(-1,0,0);
...

Eu acho que você pode fazer isso com o Atributo de teste de linha (disponível em MbUnit e versões posteriores do NUnit) onde você pode especificar vários conjuntos para preencher um teste de unidade.

Embora seja possível criar muitos dados de teste e ver o que acontece, é mais eficiente tentar minimizar os dados usados.

De uma perspectiva típica de controle de qualidade, você gostaria de identificar diferentes classificações de entradas.Produza um conjunto de valores de entrada para cada classificação e determine as saídas apropriadas.

Aqui está um exemplo de classes de valores de entrada

  • triângulos válidos com números pequenos como (1 bilhão, 2, bilhão, 2 bilhões)
  • triângulos válidos com números grandes, como (0,000001, 0,00002, 0,00003)
  • triângulos obtusos válidos que são 'quase' planos, como (10, 10, 19,9999)
  • triângulos agudos válidos que são 'quase' planos, como (10, 10, 0000001)
  • triângulos inválidos com pelo menos um valor negativo
  • triângulos inválidos onde a soma de dois lados é igual ao terceiro
  • triângulos inválidos onde a soma de dois lados é maior que o terceiro
  • valores de entrada que não são numéricos

...

Quando estiver satisfeito com a lista de classificações de entrada para esta função, você poderá criar os dados de teste reais.Provavelmente seria útil testar todas as permutações de cada item.(por exemplo.(2,3,4), (2,4,3), (3,2,4), (3,4,2), (4,2,3), (4,3,2)) Normalmente, você descobrirá que há algumas classificações que você perdeu (como o conceito de inf como parâmetro de entrada).

Dados aleatórios por algum período de tempo também podem ser úteis, pois podem encontrar bugs estranhos no código, mas geralmente não são produtivos.

Mais provavelmente, esta função está sendo usada em algum contexto específico onde regras adicionais são aplicadas.(por exemplo,apenas valores inteiros ou valores devem estar em incrementos de 0,01, etc.) Eles são adicionados à lista de classificações de parâmetros de entrada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top