Junit4: Mejora: compatibilidad con BigDecimal para assertEquals ()

Creado en 25 mar. 2010  ·  27Comentarios  ·  Fuente: junit-team/junit4

Usar JUnit para probar los valores de BigDecimal es siempre un punto delicado. Es porque BigDecimal considera la precisión usando equals () pero lo ignora en compareTo (). La mejor manera de manejar esto sería un nuevo método assertEquals que permite evaluar opcionalmente la precisión. También puede agregar un método alternativo que acepte un mensaje:

public static void assertEquals (BigDecimal esperado, BigDecimal real, boolean precisionMatters) {
if (precisionMatters) {
Assert.assertEquals (esperado, real);
} demás {
Assert.assertEquals (0, esperado.compareTo (actual));
}
}

feature

Comentario más útil

¿Ha intentado usar comparesEqualTo ?

Todos 27 comentarios

Sería algo fácil de armar como un tenedor o un parche; Estaría dispuesto a hacerlo si fuera apropiado.

Prefiero tener una aserción assertNumericallyEqualTo que una bandera booleana pasada a assertEquals.

Ese es un buen nombre. Lo acortaría a assertNumericallyEquals ().

Si bien estoy de acuerdo con el sentimiento, no estoy seguro de que tener otro método de aserción con un nombre diferente realmente ayude a aclarar la confusión, especialmente entre las personas que desconocen por completo la diferencia o que realmente no se han encontrado con el problema. Quiero decir, si no hubiera leído este número, hubiera seguido adelante y hubiera usado assertEquals() por BigDecimal . En el caso general, de hecho, funcionaría como se anuncia; funcionaría exactamente como funciona BigDecimal#equals() . Incluso diría que esto es algo bueno: obliga a alguien a darse cuenta de que BigDecimal#equals() compara tanto el valor como la escala, entonces tal vez eso no era lo que estaban tratando de lograr, aunque, en otros casos, lo postulo _es_. Quiero decir, en algunos casos queremos verificar que el valor real devuelto por un método sea _exactamente_ 'igual' al valor esperado (no solo lógica / numéricamente igual). Dicho de otra manera: ¿qué proporciona assertNumericallyEquals() (aparte de la brevedad) que assertEquals(0, actual.compareTo(expected)) no proporciona? Personalmente, probablemente crearía un comparador Hamcrest e iría assertThat(actual, isNumericallyEqualTo(expected)) si lo necesitara con suficiente frecuencia; además, se puede usar en cualquier lugar donde se puedan usar comparadores Hamcrest (validación de datos, entre otros).

Perdón por el pesaje tardío, pero mi opinión personal es cercana a la de Alistair.

Dicho de otra manera: ¿qué proporciona assertNumericallyEquals() (aparte de la brevedad) que assertEquals(0, actual.compareTo(expected)) no proporciona?

¿Comunica la intención con mayor claridad? El enfoque de Hamcrest Matcher está bien para mí.

Geoffrey,

¿Está diciendo que está bien escribiendo ese matcher para su propio proyecto o que desea que se envíe con Hamcrest? ¿O JUnit, pero no Hamcrest?

Cualquiera o todo lo anterior: la mayoría de los proyectos que escribo terminan teniendo algunos comparadores de hamcrest personalizados. Tener casos comunes cubiertos por Hamcrest y / o JUnit ahorra un poco de tiempo, pero este tampoco ha sido un caso muy común para mí.

Un pequeño punto sobre los mensajes de error menos útiles ... Acabo de convertir mis llamadas Assert.assertEquals a Assert.assertTrue habiendo fallado al comparar BigDecimals con Assert.assertEquals. Por supuesto, ahora mis pruebas fallan con una especie de error de "prueba booleana fallida", sin decirme cuáles eran los valores. De la misma manera, assertEquals (0, actual.compareTo (esperado)) registraría, por ejemplo, "esperado 0 pero obtenido: 1" cuando un mensaje de error mucho más útil sería de assertNumericallyEquals (actual, esperado) sería "esperado 12.45 pero obtenido : 123 "(los valores reales de los argumentos 'real' y 'esperado').

http://www.bssd.eu/blog/?p=113 también es una lectura interesante.

assertEquivalent de https://github.com/KentBeck/junit/pull/228 debería resolver esto.

Gracias dsaff. Ese trabajo luce genial. No he hecho esto antes, ¿significa esto que tengo que buscar la fuente junit, fusionar esta solicitud de extracción yo mismo y hacer una compilación personalizada?

De la ayuda en http://help.github.com/send-pull-requests/ parece que debería:

clon de git https://github.com/KentBeck/junit.git
cd junit

y luego agregue un control remoto para la solicitud de extracción, luego busque, combine o haga ambas cosas.

Dado que esto parece ser una solicitud de extracción, es decir, no es un junit oficial, ¿es aconsejable usarlo en una aplicación? ¿Existe la posibilidad de que esto se convierta fuera del junit principal y tenga problemas para enviar mi código a otros, para quienes no se compilará?

Neekfenwick,

Sí, estás en el camino correcto sobre cómo hacerlo ahora. Tengo la intención de fusionar ese tirón en la rama 4.10, pero el autor original ha tenido problemas para fusionar el estado de git. Si tiene tiempo para hacerle un favor al mundo, puede bifurcar el repositorio de KentBeck, fusionar todo y emitir una solicitud de extracción contra la rama 4.10, para que sea más fácil para todos (si suena popular, incluso podría girar en algún momento un tarro de vista previa 4.10).

Realmente nunca había hecho esto antes :) Así que bifurqué el repositorio y

git remote add upstream https://github.com/KentBeck/junit.git

Solo por si acaso, me ramifiqué para poder fusionar la solicitud de extracción en otro lugar que no sea HEAD:

git branch merge_pullreq_228
git checkout merge_pullreq_228

Ahora, los documentos que puedo encontrar dicen "ahora fusiona la solicitud de extracción en tu rama". Puedo ver las confirmaciones para la extracción 228 en https://github.com/KentBeck/junit/pull/228/commits pero no puedo fusionarlas:

[neek junit (merge_pullreq_228)]$ git merge 57b49344
fatal: '57b49344' does not point to a commit

Dado que la solicitud de extracción no es para mi propio repositorio / rama, no puedo usar las herramientas de combinación en la interfaz gráfica de usuario web de github (AFAIK).

¿Estoy en lo correcto al pensar que quieres que fusione las 7 confirmaciones en mi propia rama y consiga que construya / pase pruebas unitarias? ¿Podrías explicarme qué hacer para fusionar una de estas confirmaciones y ponerme en camino?

Correcto, no puede usar las herramientas de combinación web. Lo que creo que debería funcionar es:

git remoto agregar leet3lite https://github.com/leet3lite/junit.git

Y luego desde tu sucursal, llama

git pull leet3lite master

Desafortunadamente, generalmente olvido una cosa cuando describo cómo usar git "por teléfono", así que avíseme si eso funciona para usted.

Ah, ya veo, no necesito fusionar cada una de esas confirmaciones ... la rama maestra de leet3lite ya las tiene, y es el acto de fusionar ese trabajo en el maestro original el problema.

Parece haber conflictos de fusión entre esa rama y HEAD. Supongo que ese es el objetivo de este ejercicio.

[neek junit (merge_pullreq_228)]$ git remote add leet3lite https://github.com/leet3lite/junit.git
[neek junit (merge_pullreq_228)]$ git pull leet3lite master
remote: Counting objects: 100, done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 85 (delta 34), reused 77 (delta 26)
Unpacking objects: 100% (85/85), done.
From https://github.com/leet3lite/junit
 * branch            master     -> FETCH_HEAD
Auto-merging acknowledgements.txt
CONFLICT (content): Merge conflict in acknowledgements.txt
Auto-merging src/main/java/org/junit/Assert.java
Auto-merging src/test/java/org/junit/tests/AllTests.java
CONFLICT (content): Merge conflict in src/test/java/org/junit/tests/AllTests.java
Automatic merge failed; fix conflicts and then commit the result.
[neek junit (merge_pullreq_228|MERGING)]$ 

Si eso le parece sensato, seguiré con esto mañana. Casi medianoche aquí.

Parece que estás en el lugar correcto. reconocimientos.txt y AllTests.java se tocan mucho, generalmente solo con adiciones, por lo que la operación de fusión es probablemente un acto simple de incluir todas las líneas agregadas en ambas rutas.

Muchas gracias por impulsar esto.

Creo que esto se solucionó hace 2 años.

dsaff -¿No ...?

No en 4.11; (también necesito esta función

La discusión sobre assertEquivalent() trasladó al # 228 y después de eso, creo que se trasladó al # 376 donde decidimos que realmente Hamcrest debería resolver esto.

@ junit-team / junit-committers ¿alguna objeción a que cierre esto?

No hay objeciones por mi parte.

Vaya, clic freudiano. :-) No hay objeciones aquí.

Bueno. Cerrando entonces.

No creo que el uso de Hamcrest Matcher solucione este problema. Por ejemplo este código:

   assertThat(product.getRating(), is(equalTo(new BigDecimal("2.3"))));

producirá este resultado:

Expected: is <2.3>
     but: was <2.30000>

Creo que junit o hamcrest todavía necesitan el método isNumericEquivalent .

¿Ha intentado usar comparesEqualTo ?

Sí, comparesEqualTo realmente funciona. Gracias.

Aquí hay una hoja de trucos que creé hace algún tiempo:
http://www.marcphilipp.de/blog/2013/01/02/hamcrest-quick-reference/

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

forvoid picture forvoid  ·  8Comentarios

sbrannen picture sbrannen  ·  22Comentarios

Reissner picture Reissner  ·  3Comentarios

keltik85 picture keltik85  ·  3Comentarios

lvc picture lvc  ·  6Comentarios