10
votes

Méthode de test Junit avec nature randomisée

Je travaille sur un petit projet pour moi pour le moment et je l'utilise comme une occasion de se familiariser avec des tests unitaires et de maintenir une documentation appropriée.

J'ai un Deck code> La classe avec représente une pont de cartes (c'est très simple et, pour être honnête, je peux être sûr de fonctionner sans un test d'unité, mais comme je l'ai dit que je m'habituer à utiliser des tests d'unité) et qu'il a un shuffle () code> méthode qui modifie l'ordre des cartes dans le pont. p>

La mise en œuvre est très simple et fonctionnera certainement: P>

public void shuffle()
{
    Collections.shuffle(this.cards);
}


5 commentaires

D'une perspective logique, vos cartes seraient-elles considérées comme élevées si la commande est restée la même?


Pour votre dernière question, voici Stackoverflow.com/Questtions/122741/... . Je pense aussi que D. Knuth a un chapitre entier à ce sujet.


Je pense qu'il est logique que le pont soit considéré comme trop mélangé si les cartes restent dans le même ordre et que la réinscription s'est produite, bien qu'il est peu probable qu'il soit possible de mélanger un vrai jeu de cartes dans le même ordre qu'ils étaient à l'origine. dans.


Si votre code utilise un générateur de nombres aléatoires, définissez sa graine sur une valeur fixe dans vos tests d'unité. De cette façon, votre deck shuffle toujours de la même manière dans vos tests. Cela peut nécessiter une modification d'API pour permettre à votre code d'exposer publiquement une méthode pour définir la graine de rand, qui peut être définie dans des tests Junit.


Dupliqué possible de Stackoverflow .com / questions / 56411 / ...


9 Réponses :


0
votes

Je suppose que vous avez 52 cartes dans votre pont. La possibilité d'obtenir le même ordre dans deux appels ultérieurs est extrêmement faible, alors je ne la dérangerais pas trop. Mais si vous commencez à obtenir des ponts similaires plusieurs fois, je pense qu'il est prudent de dire que vous avez des problèmes avec votre générateur de nombres aléatoires.

Donc, la réponse: Vérifiez que la commande est différente pour tout le pont.

En outre, je pense que vous pouvez en faire une exigence en toute sécurité pour votre méthode de shuffle () de ne pas renvoyer les cartes dans le même ordre deux fois de suite. Et si vous voulez absolument vous assurer de suivre cette exigence, vous pouvez vérifier la similitude dans la mise en œuvre de la méthode.


1 commentaires

Vérifiez également que l'ensemble des cartes représentées par chaque pont est le même (c'est-à-dire le même nombre de cartes, mêmes membres une fois que la commande est ignorée).



3
votes

Premièrement, pensons aux probabilités impliquées:

  1. Vous ne pouvez pas garantir que le shuffle ne placera pas les cartes dans l'ordre exact. Cependant, la probabilité de faire cela avec un pont de 52 cartes est 1/52! (c'est-à-dire que c'est minimal et probablement ne mérite probablement pas la peine de vous inquiéter.)

  2. Vous devrez définitivement vérifier le pont entier, car la probabilité de la carte supérieure étant la même que avant que le shuffle est 1/52.

    Pour le cas général et en supposant que vous utilisez le générateur de numéros JAVA.UTIL.RANDOM , initiez-le avec la même graine. Ensuite, la sortie d'une entrée prédéterminée doit alors être répétable.

    Cependant, en particulier pour ce cas, en supposant que vous n'avez pas implémenté votre propre liste Je ne vois pas vraiment le point dans le test collections.shuffle (liste Liste) < / Code> ou Collections.shauffe (liste Liste, RND aléatoire) ( Lien API ) Comme ils ne font que partie de l'API Java. < / p>


0 commentaires

0
votes

question intéressante. À mon avis, le meilleur moyen serait de stocker chaque «shuffle» dans une collection, puis comparez après chaque shuffle si votre pont correspond à l'un des précédents «Decks» de la collection.

Selon le nombre de "aléateurs", vous avez besoin que vous augmentez le nombre de ponts mélangés que vous stockez dans ce test d'unité I.e. Après 50 miller, vous auriez une collection de 50 "Decks"


0 commentaires

5
votes

affirmant si votre méthode de shuffle mélange réellement les cartes est très difficile sinon impossible. Les générateurs de nombres aléatoires par défaut ne sont que aléatoires dans un certain degré. Il est impossible de tester si vous êtes satisfait de ce degré de hasard parce que cela prendrait trop de temps. Ce que vous testez réellement, c'est le générateur de nombres aléatoires lui-même qui n'a pas beaucoup de sens.

Ce que vous pouvez tester cependant, sont le invariants de cette méthode.

  • Si vous quittez la méthode, il devrait y avoir exactement le même nombre de cartes dans le pont que lorsque vous l'avez entré.
  • La méthode de shuffle ne devrait pas introduire des doublons.

    Vous pouvez bien sûr créer un test qui vérifie que, dans une séquence de N , il n'y a pas de ponts en double retournés. Mais une fois de temps en temps, ce test peut échouer (cependant improbable, comme déjà indiqué dans d'autres réponses).

    Quelque chose d'autre à prendre en compte est le générateur de nombres aléatoires lui-même. S'il s'agit d'un projet de jouet, java.util.random est suffisant. Si vous souhaitez créer un jeu de cartes en ligne, envisagez d'utiliser java.security.securerandom .


0 commentaires

2
votes

Une autre approche serait d'utiliser la liste shuffle (liste liste, aléatoire aléatoire) méthode et pour injecter un aléatoire instance ensemencée avec une constante.

De cette façon, votre test Junit peut exécuter une série d'appels et vérifier la sortie pour être la sortie attendue.

La mise en œuvre normale de votre classe créerait une instance aléatoire injusted.


0 commentaires

1
votes

Vous déléguez réellement tout le travail acharné au java.util.collections classe. Ceci est une classe centrale dans l'API de la collection de Java et vous devriez simplement supposer que cela fonctionne comme vous le faites probablement avec le java.lang.string classe.

Je préférerais que je recommanderais de coder contre des interfaces et de vous moquer de votre classe de mise en œuvre avec la méthode shuffle () . Ensuite, vous pouvez simplement affirmer que vos appels sur la méthode shuffle () sont réellement appelés à partir de votre test au lieu de tester exactement la même chose que les gars Sun / Oracle ont été testés en profondeur avant.

Cela vous permet de vous concentrer davantage sur le test de votre propre code sur lequel 99,9% de tous les bogues sont probablement situés. Et si vous remplacez par exemple java.util.collections.shuffle () méthode avec un dans un autre cadre ou votre propre implémentation, votre test d'intégration fonctionnera toujours!

Je comprends que vous faites cela parce que vous voulez apprendre et je crois que les connaissances sur la logique de tabac / moqueur d'autres cadres sont très utiles dans le cadre de vos connaissances de test.


0 commentaires

0
votes

La plupart des gens semblent être d'avis que vous devriez tester ce que vous testez. Par ce que je veux dire ce que vous construisez (ou vous intégrez, lorsque vous vous assurez qu'une bibliothèque tierce fait réellement ce qu'elle dit cela).

Mais vous ne devriez pas tester la langue java elle-même.

Il devrait y avoir un principe de test comme "Ne testez pas de plusquals".


0 commentaires

0
votes

J'ai travaillé sur des nombres aléatoires dans un cadre de modélisation et de simulation et je suis resté avant un problème similaire: comment puis-je réellement tester nos implémentations de PRNG. En fin de compte, je ne l'ai pas fait. Ce que j'ai fait plutôt, c'était d'effectuer quelques contrôles de santé mentale. Par exemple, nos PRNG annoncent tous combien de bits ils génèrent, alors j'ai vérifié si ces bits ont effectivement changé (avec des itérations de 10 000) et tous les autres bits étaient 0. J'ai vérifié le comportement approprié concernant les semences (initialisation du PRNA Les graines doivent produire la même séquence de nombres), etc. J'ai ensuite décidé de mettre les tests réels du hasard dans une interface utilisateur interactive afin de pouvoir être testés à tout moment, mais pour des tests unitaires, un résultat non déterministe n'est pas si agréable, je pensais.


0 commentaires

0
votes

Vous pouvez mélanger à plusieurs reprises, en gardant une trace de combien de fois l'as des piques (ou une autre carte, ou toutes les autres cartes) finit comme la première carte du pont. Théoriquement la carte doit se retrouver sur environ 1 sur 52 mélanges. Une fois que toutes les données ont été recueillies, comparez la fréquence réelle au nombre 1/52 et vérifiez si la différence (valeur absolue) est inférieure à celle de la valeur EPSILON choisie. Plus vous mélangez, plus votre valeur Epsilon peut être. Si votre méthode de shuffle () met la carte en haut dans votre seuil Epsilon, vous pouvez être sûr qu'il randomise les cartes comme vous le souhaitez.

Et vous n'avez pas à vous arrêter juste sur la carte supérieure. Vous pouvez tester si chaque emplacement dans le pont donne les mêmes résultats. Faites-le avec une seule carte, faites-le toutes les cartes, cela n'a probablement pas d'importance. Cela pourrait être surchargé, mais cela garantirait votre shuffle () fonctionne correctement.


0 commentaires