Подтвердить что ты не робот

Техника для автоматической проверки согласованности равных, hashCode и compareTo?

Мне хорошо известно о контрактных потребностях, чтобы убедиться, что hashCode соответствует equals и что equals соответствует compareTo. Однако это часто нарушается на практике. Существуют ли какие-либо инструменты, методы или библиотеки, которые могут автоматически проверять эту согласованность?

Я подозреваю, к сожалению, что ответ "нет", но было бы полезно иметь unit test для такого рода вещей, которые могли бы использовать библиотечный вызов или структуру, а не писать тест вручную для каждого случая, когда это важно.

Если не ясно, что я подразумеваю под согласованностью, для hashCode и equals я ссылаюсь на следующее:

Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат.

Для equals и compareTo я ссылаюсь на следующее:

Естественное упорядочение для класса C называется согласованным с равенствами тогда и только тогда, когда e1.compareTo(e2) == 0 имеет то же булево значение как e1.equals(e2) для всех e1 и e2 класса C.

4b9b3361

Ответ 1

В тестах Guava есть утилита EqualsTester, которую мы используем как повседневную часть нашего подразделения тесты для тестирования equals и hashCode. Его использование выглядит как

new EqualsTester()
  .addEqualityGroup("hello", "h" + "ello")
  .addEqualityGroup("world", "wor" + "ld")
  .addEqualityGroup(2, 1 + 1)
  .testEquals();

который проверяет, что все значения в одной и той же группе равны и имеют одинаковые хэш-коды, что разные группы не равны и что все остальные инварианты выполнены. Вы можете использовать его самостоятельно или просто одолжить свои идеи.

Я был бы очень удивлен, если бы можно было протестировать, не генерируя или явно указывая тестовые значения, просто потому, что это кажется очень вероятным эквивалентом проблемы с остановкой.

Ответ 2

Если вы используете JUnit, пакет расширения имеет EqualsHashCodeTestCase, который полностью проверяет как equals, так и hashCode для всего, что указано в Спецификация Java (рефлексивная, транзитивная, симметричная и т.д.). Все, что вам нужно сделать, это предоставить равный и не равный объект для родительского класса, который будет использоваться для проверки.

Так как метод CompareTo является частью интерфейса Comparable, он фактически распадается на другой тестовый пример - ComparabilityTestCase. Это занимает три объекта - одно из меньшего значения, равное значение и большее значение. Переопределите их, а родительский класс позаботится обо всех остальных.

Ответ 3

Я написал несколько полезных методов, помогающих модульному тестированию hashCode и равным методам:

http://softsmithy.sourceforge.net/devlib/docs/api/org/softsmithy/devlib/junit/Tests.html

Библиотека является Open Source и может быть загружена отсюда: http://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v0.1/

или с Maven:

    <dependency>
        <groupId>org.softsmithy.devlib</groupId>
        <artifactId>devlib-core</artifactId>
        <version>0.1</version>
        <scope>test</scope>
    </dependency>

Ответ 4

Есть очень классный инструмент под названием Korat, который может выполнять исчерпывающие поиски, чтобы проверить правильность Java классы для малых случаев. Он фактически просматривает код, который выполняется для того, чтобы собрать все различные тестовые примеры заданного размера, которые программа действительно может различать. Я не знаю, насколько это полезно в больших случаях, но для многих программ он может автоматически использоваться для проверки корректности таких случаев.

Надеюсь, это поможет!

Ответ 5

Недавно я использовал meanbean (http://meanbean.sourceforge.net/) для автоматического тестирования класса для контрактов equals() и hashCode() (плюс пары setter/getter).

"Среднее значение Bean:

1. Проверяет, что пары метода getter и setter функции JavaBean/POJO корректно. 2. Проверяет, что методы equals и hashCode класса соответствуют контракту Equals и HashCode Contract соответственно. 3. Проверяет значение свойства в равенстве объекта.

У меня все еще есть много вопросов, специфичных для meanbean: проверяет ли она равенства() и hashCode(). Плюс, я не пытался его победить. Я считаю, что он не поддерживает compareTo(). И я не пробовал альтернативы. Заинтересованы в другом опыте.