dans un test JUNIT 4, j'ai une méthode getvalues () code> qui renvoie une liste
list
org.hamcrest.collection.isarray.hasitems code> et
org.hamcrest.matchers.closeto code> comme ceci:
List<Matcher<Double>> doubleMatcherList = new ArrayList<Matcher<Double>>();
doubleMatcherList.add(closeTo(0.2, EPSILON));
doubleMatcherList.add(closeTo(0.3, EPSILON));
assertThat(getValues(), (Matcher) hasItems(doubleMatcherList));
7 Réponses :
Si les deux listes ont des longueurs différentes, disent qu'ils sont différents. S'ils ont les mêmes longueurs, triez les listes. Après avoir tri leurs éléments comparer des éléments au même index. P>
Ceci peut être discuté plus de détails, que vous compariez chaque élément de la liste A à des éléments correspondants de la liste B, par exemple. Comparez A [I] avec B [I-D], ... B [I], ..., B [I + D]. P>
Mais pour commencer, cela pourrait vous aider à avoir une meilleure idée. P>
Mise à jour: Si vous ne pouvez pas modifier les listes, vous pouvez toujours les copier et les trier. P>
Trier les listes? Quoi? Et si la commande compte? Et si vous attendez est [3.0, 1.0, 2.0] code> mais il renvoie
[2.0, 1.0, 3.0] code>? Votre test va passer même si cela ne devrait pas.
Eh bien, si la commande compte, vous ne triez pas les listes.
J'ai manqué évidemment la question. Désolé, trop fatigué. En outre, comment le commanderait-il si le nom de la méthode est des hasitems? Que par défaut signifie que l'ordre n'a pas d'importance, donc je ne comprends pas bien votre commentaire à ce sujet. Le vrai problème serait que ma réponse indique comment comparer deux listes non si l'une contient des éléments d'un autre. Mais toujours, en utilisant la même approche, elle peut être résolue dans O (n journal n). Je ne sais pas comment travaille hamcrest, mais je comprends que le problème est la complexité?
Je pense que la bonne solution ici serait une personnalisée correspondant . Fondamentalement, quelque chose comme ISITERABLeconAninginorder qui ne fonctionne que sur des doubles et prend en charge une marge d'erreur. p>
Je ne crois pas que personne ne l'a mentionné. Si vous avez la liste attendue et p>
veut que la liste réelle soit dans le même ordre que la liste attendue puis utilisez p>
veux que les listes soient égales, quelle que soit la commande puis faire
Assertequals (attendu, réel); code> p> li>
AsssertionTtrue (attendu.Contentatsall (réelle) && réel.conatsall (attendu)); code> p> li>
ul>
Les gens en ont mentionné, ont été révélés et ont supprimé leurs réponses parce qu'elles n'étaient nulle partout près de la résolution du problème de l'OP.
@Jaroslawpawlak mais pourquoi?
Pour la même raison pour laquelle 4.35d * 100! = 435.0d code>
Désolé, je suis juste en train d'essayer de comprendre le concept, donc si j'appelle égale dans les listes suivantes Arrays.Aslist ((double) 430, (Double) 2) Code> et
Arrays.Aslist (4.3 * 100 , (double) 2) code> devrait-il être faux?
@RAHULSHARMA Le problème est que les deux listes sont différentes mais numériquement égales. Dans les messages qui ont été supprimés, j'ai mentionné qu'une liste avec 0,2 et 0,3 n'est pas égale à une liste avec 0,2 et 0.300000004. Le seul moyen de faire ces deux listes égales (c'est-à-dire ce que cet article est à propos de) est d'introduire une tolérance numérique dans la comparaison. Votre solution ne résout pas mon problème.
@RAHULSHARMA Cependant, votre solution fonctionnerait parfaitement pour toute autre liste.
@Francois mais quel type de test écrivez-vous lorsque vous ne pouvez même pas produire le résultat attendu?
@RAHULSHARMA Ce sont des tests d'algorithmes numériques. Il pourrait s'agir d'interpolation, d'opérations matricielles, de résolution du système d'équations ou de trouver des racines d'équations non linéaires, juste pour vous donner quelques exemples. Dans l'exemple que j'ai donné dans mon poste initial, je sait b> que le résultat attendu sera proche de 0,2 et de 0,3 et il suffit que le test réussisse. Je ne peux pas m'attendre à ce qu'une méthode numérique donne une solution exacte, sinon il n'y aurait pas besoin de méthodes numériques du tout. Je ne modifierai pas mon code pour utiliser des entiers au lieu des doubles simplement parce qu'il serait plus facile de contrôler la sortie.
Il n'y a pas de Convertissez d'abord votre liste de matchers en une matrice p> et appelez-la comme ceci p> Méthode HASITEMS CODE> qui prend une liste des correspondants comme argument. Mais vous pouvez utiliser Celui avec Varargs .
assertThat(getValues(), hasItems(toDoubleMatcherArray(doubleMatcherList)));
Si vous êtes prêt à convertir de Liste
double [] code>, Assertarrayequals permet de spécifier une tolérance à l'erreur:
assertArrayEquals(toArray(refList), toArray(getValues()), 1E-9);
Cela ne gère pas les nuls, qui sont possibles dans une liste de doubles.
Vous devez utiliser Casting du retour de ceci est parce que Cela fait ce que vous voulez, sans passer le tracas d'un correspondeur contient () code> plutôt que
hasitems () code>.
hasitems () code> à
Correspondant code> cache une erreur de type. Votre code vérifie en fait si le résultat de
getvalues () code> est une liste code> code> qui dispose du match de 2
code> S que vous avez créé, il n'évalue pas ces
correspondeur code> S par rapport au résultat de
getvalues () code>. p>
hasitems () code> n'a pas de Surcharge prenant une liste
contient () code> fait. P>
personnalisé code> : P>
List<Matcher<? super Double>> doubleMatcherList = new ArrayList<>();
doubleMatcherList.add(closeTo(0.2, EPSILON));
doubleMatcherList.add(closeTo(0.3, EPSILON));
assertThat(getValues(), contains(doubleMatcherList));
Si vous êtes prêt à changer de HamCrest en Assertion Assertions, voici une solution en Java 8.
import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.junit.Test; // import java.util.function.Function; public class DoubleComparatorTest { // private static final Double DELTA = 1E-4; // private static final Function<Double, Comparator<Double>> DOUBLE_COMPARATOR_WITH_DELTA = // (delta) -> (o1, o2) -> (o1 - o2 < delta) ? 0 : o1.compareTo(o2); private Comparator<Double> COMPARATOR = (o1, o2) -> (o1 - o2 < 0.0001) ? 0 : o1.compareTo(o2); @Test public void testScaleCalculationMaxFirstPositive() { List<Double> expected = Arrays.asList(1.1D, 2.2D, 3.3D); List<Double> actual = Arrays.asList(1.10001D, 2.2D, 3.30001D); assertThat(actual) // .usingElementComparator(DOUBLE_COMPARATOR_WITH_DELTA.apply(DELTA)) .usingElementComparator(COMPARATOR) .isEqualTo(expected); } }
Il y a une solution qui fonctionne toujours: i Itérale sur les valeurs de GetValues () b> et faites une comparaison individuelle avec mes valeurs de référence. Je me demandais s'il y a une solution plus simple en utilisant Matchers B>.
Développement axé sur le test - La mise en œuvre est entraînée par vos tests. Si quelque chose est difficile à tester, vous ne le faites probablement pas correctement. Vous ne pouvez pas écrire un test pour la liste des doubles - n'utilisez pas de double. Pourquoi n'utilisez-vous pas les entiers / Longs ou
BigDecimals CODE>?
@Jaroslav Ce test se produit dans une application qui effectue des calculs numériques intenses. Donc, ne pas travailler avec des listes de doubles est hors de question.
@Francois vous essayez de résoudre le problème plutôt que sa cause. Que représentent ces doubles? Pourquoi la précision compte-t-elle? Pourquoi votre epsilon est 0.0001 et non 0.000001 ou 0,1?
@Jaroslav dans l'exemple que j'ai donné, les valeurs résultent d'une interpolation linéaire comprise entre 0,1 et 0,4, avec une augmentation de 0,1. Je m'attends à ce que le test renvoie une liste avec 0,2 et 0,3 comme des valeurs manquantes. C'est l'un des cas le plus simple que je dois tester. Ce test échoue car la liste contient 0,2 et 0.300000004, sauf si j'utilise un correspondant approprié.
Faites ce calcul sur les entiers alors (ou longs). Au lieu de faire une interpolation linéaire comprise entre 0,1 et 0,4 avec une augmentation de 0,1, faites-le entre 1 et 4 avec une augmentation de 1. De même, comme au lieu de représenter la quantité de dollars en double, vous utiliseriez longtemps qui représenterait des cents.
@Jaroslawpawakak Les BigDecimaux sont autant une douleur à tester que des doubles. : / La balance a à la même manière que le nombre.
@mlk vous avez raison. Je pense que la meilleure solution est de faire ce calcul dans des nombres entiers. Si Epsilon est 0,001, nous donnons simplement des numéros d'entrée multipliés par 1000 et attendez-vous au dos Int / Long / BigInteger.
Je ne suis pas d'accord avec vous les gars. Si le résultat d'un test est dans une tolérance numérique de la valeur attendue, ce test est un succès. Vous croyez que je ne contrôle pas la sortie et je suis en désaccord avec vous. Ceci est calcul numérique. Avec une entrée donnée, je m'attends à ce que la sortie soit proche de B> une sortie donnée. Le calcul numérique sera jamais b> converger vers une solution exacte. Pourquoi un tel test serait-il mauvais? Devrais-je numériquement résoudre un ensemble d'équations ou trouver les racines d'une fonction utilisant uniquement des entiers? Je ne le pense pas.