unit testing - Comment utiliser des combinaisons d'ensembles comme données de test

Translate

Je voudrais tester une fonction avec un tuple à partir d'un ensemble de cas marginaux et de valeurs normales. Par exemple, lors du test d'une fonction qui renvoietruechaque fois que trois longueurs forment un triangle valide, j'aurais des cas spécifiques, des nombres négatifs / petits / grands, des valeurs proches du débordement, etc. de plus, l'objectif principal est de générer des combinaisons de ces valeurs,avecousans pour autantrépétition, afin d'obtenir un ensemble de données de test.

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

En guise de note: je connais en fait la réponse à cela, mais cela pourrait être utile pour d'autres, et un défi pour les gens d'ici! - publiera ma réponse plus tard.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Absolument, en particulier avec beaucoup de ces permutations / combinaisons, je peux certainement voir que la première passe serait un problème.

Implémentation intéressante en python, même si j'en ai écrit une belle en C et Ocaml basée sur "Algorithm 515" (voir ci-dessous). Il a écrit le sien en Fortran comme c'était courant à l'époque pour tous les papiers "Algorithm XX", eh bien, cette assemblée ou c. J'ai dû le réécrire et faire quelques petites améliorations pour travailler avec des tableaux et non des plages de nombres. Celui-ci fait un accès aléatoire, je travaille toujours à obtenir de belles implémentations de celles mentionnées dans le fascicule 2 du quatrième volume de Knuth. Je vais expliquer comment cela fonctionne au lecteur. Mais si quelqu'un est curieux, je ne m'opposerais pas à l'écriture de quelque chose.

/** [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;
}

~ "Algorithme 515: Génération d'un vecteur à partir de l'index lexicographique"; Buckles, BP et Lybanon, M. ACM Transactions on Mathematical Software, Vol. 3, n ° 2, juin 1977.

La source
Translate

Avec le tout nouveau Python 2.6, vous avez une solution standard avec le module itertools qui renvoie le produit cartésien des itérables:

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)]

Vous pouvez fournir un argument "répétition" pour exécuter le produit avec un itérable et lui-même:

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)]

Vous pouvez également modifier quelque chose avec des combinaisons:

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

Et si l'ordre compte, il y a des permutations:

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)]

Bien sûr, tous ces trucs sympas ne font pas exactement la même chose, mais vous pouvez les utiliser d'une manière ou d'une autre pour résoudre votre problème.

Rappelez-vous simplement que vous pouvez convertir un tuple ou une liste en un ensemble et vice versa en utilisant list (), tuple () et set ().

La source
Translate

Question interessante!

Je ferais cela en choisissant des combinaisons, quelque chose comme ce qui suit en python. La partie la plus difficile est probablement la vérification du premier passage, c'est-à-direif f(1,2,3) returns true, est-ce un résultat correct? Une fois que vous avez vérifié cela, c'est une bonne base pour les tests de régression.

C'est probablement une bonne idée de créer un ensemble de cas de test dont vous savez qu'ils seront tous vrais (par exemple 3,4,5 pour ce cas de triangle), et un ensemble de cas de test dont vous savez qu'ils seront tous faux (par exemple 0,1 , inf). Ensuite, vous pouvez plus facilement vérifier que les tests sont corrects.

# 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);
...
La source
Translate

Je pense que vous pouvez le faire avec leAttribut de test de ligne(disponible dans MbUnit et les versions ultérieures de NUnit) où vous pouvez spécifier plusieurs ensembles pour remplir un test unitaire.

La source
Translate

Bien qu'il soit possible de créer de nombreuses données de test et de voir ce qui se passe, il est plus efficace d'essayer de minimiser les données utilisées.

Dans une perspective d'assurance qualité typique, vous voudriez identifier différentes classifications d'entrées. Produisez un ensemble de valeurs d'entrée pour chaque classification et déterminez les sorties appropriées.

Voici un exemple de classes de valeurs d'entrée

  • triangles valides avec de petits nombres tels que (1 milliard, 2, milliard, 2 milliards)
  • triangles valides avec de grands nombres tels que (0,000001, 0,00002, 0,00003)
  • triangles obtus valides qui sont `` presque '' plats tels que (10, 10, 19.9999)
  • triangles aigus valides qui sont `` presque '' plats tels que (10, 10, 0000001)
  • triangles non valides avec au moins une valeur négative
  • triangles invalides où la somme des deux côtés est égale au troisième
  • triangles invalides où la somme des deux côtés est supérieure au troisième
  • valeurs d'entrée non numériques

...

Une fois que vous êtes satisfait de la liste des classifications d'entrée pour cette fonction, vous pouvez créer les données de test réelles. Il serait probablement utile de tester toutes les permutations de chaque élément. (par exemple (2,3,4), (2,4,3), (3,2,4), (3,4,2), (4,2,3), (4,3,2)) En règle générale, vous constaterez que certaines classifications vous ont manqué (comme le concept d'inf en tant que paramètre d'entrée).

Des données aléatoires pour une certaine période de temps peuvent également être utiles, qui peuvent trouver des bogues étranges dans le code, mais ne sont généralement pas productives.

Plus probablement, cette fonction est utilisée dans un contexte spécifique où des règles supplémentaires sont appliquées (par exemple, seules les valeurs entières ou les valeurs doivent être par incréments de 0,01, etc.) Ces dernières s'ajoutent à la liste des classifications des paramètres d'entrée.

La source