Использование JUnit для проверки значений BigDecimal всегда является больным местом. Это потому, что BigDecimal учитывает точность с помощью equals (), но игнорирует ее в compareTo (). Лучшим способом справиться с этим будет новый метод assertEquals, который позволяет при необходимости оценивать точность. Вы также можете добавить альтернативный метод, принимающий сообщение:
public static void assertEquals (ожидается BigDecimal, фактическое BigDecimal, логическое значение precisionMatters) {
if (precisionMatters) {
Assert.assertEquals (ожидаемый, фактический);
} еще {
Assert.assertEquals (0, ожидаемый .compareTo (фактический));
}
}
Было бы легко собрать вилку или заплатку; Я был бы готов сделать это, если это будет уместно.
Я бы предпочел иметь утверждение assertNumericallyEqualTo, чем логический флаг, переданный в assertEquals.
Хорошее имя. Я бы сократил его до assertNumericallyEquals ().
Хотя я согласен с мнением, я не уверен, что наличие другого метода assert с другим именем действительно поможет устранить путаницу, особенно среди людей, которые совершенно не осознают разницу или сами действительно не сталкивались с проблемой. То есть, если бы я не читал этот выпуск, я бы пошел дальше и использовал assertEquals()
для BigDecimal
. В общем случае он действительно будет работать так, как рекламируется - он будет работать точно так, как работает BigDecimal#equals()
. Я бы даже сказал, что это хорошо - это заставляет кого-то осознать, что BigDecimal#equals()
сравнивает и значение, и масштаб, тогда, возможно, это не то, чего они пытались достичь - хотя в других случаях я утверждаю это. _является_. Я имею в виду, что в некоторых случаях мы хотим проверить, что фактическое значение, возвращаемое методом, _ точно_ 'равно' ожидаемому значению (а не просто логически / численно равно). Иными словами: что дает assertNumericallyEquals()
(помимо краткости), чего не дает assertEquals(0, actual.compareTo(expected))
? Лично я бы, вероятно, создал сопоставитель Hamcrest и пошел бы assertThat(actual, isNumericallyEqualTo(expected))
если он мне нужен достаточно часто - плюс, его можно использовать везде, где можно использовать сопоставители Hamcrest (среди прочего, проверка данных).
Извините за позднее взвешивание, но мое личное мнение близко к Алистеру.
Иными словами: что дает
assertNumericallyEquals()
(помимо краткости), чего не даетassertEquals(0, actual.compareTo(expected))
?
Более четко передает намерение? Подход Hamcrest Matcher меня устраивает.
Джеффри,
Вы хотите сказать, что хорошо пишете этот матчер для своего собственного проекта или хотите, чтобы он поставлялся с hamcrest? Или JUnit, но не hamcrest?
Любое или все из вышеперечисленного - большинство проектов, которые я пишу, в конечном итоге имеют несколько настраиваемых сопоставителей hamcrest. Наличие общих случаев, охватываемых Hamcrest и / или JUnit, экономит немного времени, но для меня это тоже не очень распространенный случай.
Небольшой замечание о менее полезных сообщениях об ошибках. Я только что преобразовал свои вызовы Assert.assertEquals в Assert.assertTrue, столкнувшись с ошибками при сравнении BigDecimals с Assert.assertEquals. Конечно, теперь мои тесты терпят неудачу из-за ошибки типа «логическая ошибка теста», не сообщая мне, каковы были значения. Таким же образом assertEquals (0, actual.compareTo (ожидаемый)) будет регистрировать, например, «ожидаемый 0, но получил: 1», когда гораздо более полезное сообщение об ошибке будет от assertNumericallyEquals (фактическое, ожидаемое) будет «ожидается 12,45, но получено : 123 »(фактические значения« фактических »и« ожидаемых »аргументов).
http://www.bssd.eu/blog/?p=113 также представляет собой интересное чтение.
assertEquivalent из https://github.com/KentBeck/junit/pull/228 должен решить эту проблему.
Спасибо, dsaff. Эта работа выглядит великолепно. Я не делал этого раньше, означает ли это, что мне нужно получить исходный код junit, самостоятельно объединить этот запрос на перенос и создать собственную сборку?
Из справки на http://help.github.com/send-pull-requests/ кажется, что мне следует:
git clone https://github.com/KentBeck/junit.git
cd junit
а затем добавьте пульт для запроса на перенос, затем либо выберите, либо объедините, либо и то, и другое.
Учитывая, что это похоже на запрос на перенос, то есть не официальный junit, разумно ли использовать его в приложении? Есть ли шанс, что это выйдет за пределы основного junit, и у меня возникнут проблемы с отправкой моего кода другим, для кого он не будет построен?
Никфенвик,
Да, вы на правильном пути в отношении того, как это сделать сейчас. Я намерен объединить этот запрос в ветку 4.10, но у исходного автора возникли проблемы с получением объединяемого статуса git. Если у вас есть время сделать миру одолжение, вы можете форкнуть репозиторий KentBeck, объединить все и отправить запрос на вытягивание для ветки 4.10, чтобы всем было проще (если это звучит популярно, я мог бы даже развернуть когда-нибудь загрузите банку предварительного просмотра 4.10).
Я действительно никогда не делал этого раньше :) Итак, я разветвил репо и клонировал [email protected] : neekfenwick / junit.git на свой локальный компьютер (у меня уже есть учетная запись github и настроены ключи ssh) и добавил пульт для репо, из которого я его раздвоил:
git remote add upstream https://github.com/KentBeck/junit.git
На всякий случай я разветвился, чтобы можно было объединить запрос на перенос где-нибудь, кроме HEAD:
git branch merge_pullreq_228
git checkout merge_pullreq_228
Теперь документы, которые я могу найти, говорят: «Теперь объедините запрос на перенос в свою ветку». Я вижу коммиты для pull 228 на https://github.com/KentBeck/junit/pull/228/commit, но не могу их объединить:
[neek junit (merge_pullreq_228)]$ git merge 57b49344
fatal: '57b49344' does not point to a commit
Поскольку запрос на перенос не для моего собственного репо / ветки, я не могу использовать инструменты слияния в веб-интерфейсе github (AFAIK).
Правильно ли я думаю, что вы хотите, чтобы я объединил 7 коммитов в мою собственную ветку и заставил ее создавать / проходить модульные тесты? Не могли бы вы объяснить, что нужно сделать, чтобы объединить один из этих коммитов, чтобы заставить меня продолжить свой путь?
Правильно, вы не можете использовать инструменты веб-слияния. Я считаю, что должно работать:
git remote добавить leet3lite https://github.com/leet3lite/junit.git
А потом из своего филиала позвоните
git pull leet3lite master
К сожалению, я обычно забываю одну вещь, описывая, как использовать git «по телефону», поэтому дайте мне знать, работает ли это для вас.
А, я понимаю, мне не нужно объединять каждый из этих коммитов .. В ветке master leet3lite они уже есть, и проблема заключается в слиянии этой работы с исходным мастером.
Кажется, есть конфликты слияния между этой веткой и HEAD. Думаю, в этом весь смысл этого упражнения.
[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)]$
Если это кажется вам разумным, я займусь этим завтра. Здесь почти полночь.
Похоже, вы попали в нужное место. Подтверждения.txt и AllTests.java часто затрагиваются, обычно просто добавлением, поэтому операция слияния, вероятно, представляет собой простой акт включения всех строк, добавленных на обоих путях.
Большое спасибо за продвижение вперед.
Думаю, это было исправлено 2 года назад.
dsaff - Нет ...?
Не в 4.11; (мне тоже нужна эта функция
Обсуждение assertEquivalent()
переместилось в # 228, а после этого, я думаю, оно переместилось в # 376, где мы решили, что на самом деле Hamcrest должен решить эту проблему.
@ junit-team / junit-committers есть ли возражения против того, чтобы я закрыл это?
Никаких возражений с моей стороны.
Ой, фрейдистский щелчок. :-) Здесь нет возражений.
Хорошо. Итак, закрытие.
Я не думаю, что использование подборщика hamcrest исправит эту проблему. Например этот код:
assertThat(product.getRating(), is(equalTo(new BigDecimal("2.3"))));
даст такой результат:
Expected: is <2.3>
but: was <2.30000>
Я думаю, что junit или hamcrest все еще нуждается в методе isNumericEquivalent
.
Вы пробовали использовать comparesEqualTo
?
Да, comparesEqualTo
действительно работает. Спасибо.
Вот шпаргалка, которую я создал некоторое время назад:
http://www.marcphilipp.de/blog/2013/01/02/hamcrest-quick-reference/
Самый полезный комментарий
Вы пробовали использовать
comparesEqualTo
?