한 단위가 hashCode-equals 계약을 어떻게 테스트해야합니까?
요컨대, Java의 object.hashCode ()에 따른 hashCode 계약 :
- 동일 함 ()에 영향을주지 않는 것이 변경되지 않습니다.
- 같음 ()은 해시 코드가 ==임을 의미합니다.
주로 변경 불가능한 데이터에서 관심이 가정 해 봅시다. 해당 정보는 생성되지 않습니다. 그것은 # 2를 남깁니다. ==를 의미한다는 것을 확인하는 것입니다.
분명히 우리는 그 집합이 사소하게 작지 않는 한 모든 상상할 수있는 데이터 개체를 테스트 할 수 없습니다. 일반적인 경우를 포함 할 수있는 단위 테스트를 작성하는 가장 좋은 방법은 무엇입니까?
이 클래스의 인스턴스는 변경 불가능한 클래스의 인스턴스를 생성하는 방법을 생성합니다. 이 단위 테스트는 모든 것을 다루어야합니다. 내 머리 생성자에서 진입 점은 생성자, 역 생성자입니다 (생성자 호출 문제를 수 있어야 함).
[연구를 통해 내 질문에 답하려고 노력할 것입니다. 다른 StackOverflowers의 입력은이 프로세스에 대한 환영받는 안전입니다.]
[다른 OO 언어에도 적용 할 수 있으므로 태그를 추가하겠습니다.]
EqualsVerifier 는 계약을 테스트하는 데이며 동일합니다. GSBase의 EqualsTester 에는 문제 가 없습니다 . 나는 그것을 확실히 추천 할 것입니다.
내 조언은 이것이 사실이 아닌 이유 / 방법을 생각한 다음 상황을 대상으로하는 단위 테스트를 작성하는 것입니다.
예를 들어 사용자 지정 Set
클래스 가 존재 가정 해 보겠습니다 . 두 세트가 동일한 요소를 포함하는 경우 동일하지만 두 세트의 기본 데이터 구조는 해당 요소가 다른 순서로 저장되는 경우 다를 수 있습니다. 예를 들면 :
MySet s1 = new MySet( new String[]{"Hello", "World"} );
MySet s2 = new MySet( new String[]{"World", "Hello"} );
assertEquals(s1, s2);
assertTrue( s1.hashCode()==s2.hashCode() );
이 경우 구현 한 해싱 알고리즘에 따라 세트의 요소 순서가 해시에 영향을 미칠 수 있습니다. 그래서 이것은 제가 말하는 테스트의 종류입니다. 왜냐하면 그것은 두 가지 경우에서 발생하는 것과 동일하다는 것입니다.
어떤 것이 든 자신의 사용자 정의 클래스와 권장 표준을 사용합니다.
이를 위해 junit 애드온을 사용할 가치가 있습니다. EqualsHashCodeTestCase http://junit-addons.sourceforge.net/ 클래스를 확인하십시오. 관리자 확장 및 createInstance 및 createNotEqualInstance를 구현할 수 있습니다. 그러면 hashCode 메소드가 올바른지 확인합니다.
GSBase 의 EqualsTester 를 추천 합니다 . 기본적으로 원하는 것을 수행합니다. 그래도 두 가지 (사소한) 문제가 있습니다.
- 생성자는 모든 작업을 수행하기 좋은 방법이라고 생각하지 않습니다.
- 클래스 A의 인스턴스가 클래스 A의 하위 클래스의 인스턴스와 같으면 실패합니다. 이것은 반드시 같음 계약을 위반하는 것은 아닙니다.
[이 글을 쓰는 시점에 다른 세 개의 답변이 게시되었습니다.]
다시 말해서, 내 질문의 목적은 표준 테스트 사례를 찾아서 서로 동의 hashCode
하고 있는지 확인하는 것 equals
입니다. 이 질문에 대한 나의 접근 방식은 문제의 클래스, 즉 불변 데이터를 사용할 때 프로그래머가 취하는 경로입니다. 예를 들면 :
- 쓴
equals()
작성하지 않고hashCode()
. 이것은 종종 두 인스턴스의 필드가 동등 함을 의미하는 동등성이 정의 의미합니다. - 쓴
hashCode()
작성하지 않고equals()
. 이 프로그래머가보다 효율적인 해싱 알고리즘을 찾고 있음을 의미 할 수 있습니다.
# 2의 경우 문제가없는 것입니다. 추가 인스턴스가 만들어 equals()
지지 않을까요? 최악의 경우 해시 알고리즘은 질문의 범위를 벗어난 해시 맵의 성능을 사용할 수 있습니다.
# 1의 경우 표준 단위 테스트는 생성자에 전달 된 동일한 데이터를 사용하여 동일한 개체의 두 인스턴스를 동일한 해시 코드를 확인하는 작업을 수반합니다. 오탐은 어떻습니까? 그럼에도 불구하고 건전하지 않은 알고리즘에서 동일한 해시 코드를 생성하는 생성자 변수를 선택할 수 있습니다. 우선 순위 변수를 피하는 경향이있는 정신을 나열하는 것입니다. 여기서 길은 소스 코드를 검사하고 equals()
, 열심히 생각하고,이를 기반으로 테스트를 작성하는 것이지만, 경우에 따라 필요한 수있는 문제를 신속하게 테스트 할 수 있습니다. 이 질문의.
예를 들어 테스트 할 클래스 (Data라고 함)에 문자열을 사용하는 생성자와. 인 인스턴스가 생성 된 문자열에서 equals()
생성 된 인스턴스가 equals()
있는 경우 좋은 테스트는 다음을 테스트 할 것입니다.
new Data("foo")
- 다른
new Data("foo")
내 생각에 올바른 결과를 더 많은 new Data(new String("foo"))
것 보다 올바른 해시를 할 가능성이 더 높지만, 해시 코드를 확인하여 String이 인턴 코드가 없어도 Data.equals()
됩니다.
Eli Courtwright 의 대답은 equals
사양 에 대한 지식을 기반으로 해시 알고리즘을 깨는 방법을 열심히 생각하는 예입니다 . 특수 컬렉션의 예는 사용자가 만든 Collection
s가 표시되고 해시 알고리즘에서 엉망이 경향 이 있으므로 좋은 컬렉션입니다 .
이 테스트에서 여러 개의 어설 션이있는 유일한 경우 중 하나입니다. 메소드를 테스트해야 할 때 hashCode 메소드를 확인해야합니다. 따라서 각 메소드는 메소드 테스트 케이스에서 hashCode 계약도 확인하십시오.
A one = new A(...);
A two = new A(...);
assertEquals("These should be equal", one, two);
int oneCode = one.hashCode();
assertEquals("HashCodes should be equal", oneCode, two.hashCode());
assertEquals("HashCode should not change", oneCode, one.hashCode());
물론 좋은 hashCode를 확인하는 것은 또 다른 연습입니다. 솔직히 저는 hashCode가 동일한 실행에서 변경되지 않았는지 확인하기 위해 이중 검사를 수행하지 않을 것입니다. 더 잘 처리되는 문제는 코드에서 해결되고 개발자가 좋은 방법이 아닌지 이해하도록 도와 줌. hashCode 메서드를 작성합니다.
http://code.google.com/p/guava-libraries/source/browse/guava-testlib/src/com/google/common/testing/EqualsTester.java 와 사용하는 것을 하여 equals 및 hashCode를 테스트 할 수도 있습니다. .
클래스가 있으면 Thing
대부분의 다른 클래스 처럼 ThingTest
해당 클래스에 대한 모든 단위 테스트를 보유 하는 클래스를 작성합니다 . 각각 ThingTest
방법이 있습니다
public static void checkInvariants(final Thing thing) {
...
}
경우 Thing
클래스 재정의 해시 코드가 동일하고는 방법이있다
public static void checkInvariants(final Thing thing1, Thing thing2) {
ObjectTest.checkInvariants(thing1, thing2);
... invariants that are specific to Thing
}
이 메서드는 개체 쌍 사이에 유지되도록 설계된 모든 불변성 을 확인 Thing
합니다. ObjectTest
객체의 쌍 사이에 유지해야하는 모든 불변을 확인하기위한 책임에 방법을 위임합니다. 마찬가지로 equals
그리고 hashCode
모든 객체 방법, 그 방법이 확인되어 hashCode
와 equals
일치한다.
그런 다음 Thing
개체 쌍을 생성 하고이를 pairwise checkInvariants
메서드에 전달하는 몇 가지 테스트 메서드가 있습니다 . 등가 분할을 사용하여 테스트 할 가치가있는 쌍을 결정합니다. 일반적으로 각 쌍을 하나의 속성에서만 다르게 만들고 두 개의 동등한 객체를 테스트하는 테스트를 만듭니다.
나는 또한 때때로 3 개의 인수 checkInvariants
방법을 가지고 있지만 그것이 findinf 결함에서 덜 유용하다는 것을 알게 되었기 때문에 이것을 자주하지 않습니다.
참고 URL : https://stackoverflow.com/questions/188311/how-should-one-unit-test-the-hashcode-equals-contract
'ProgramingTip' 카테고리의 다른 글
어떤 소멸자가 실행되고 (0) | 2020.10.27 |
---|---|
C ++에서 부호있는 정수 오버플로가 여전히 정의되지 않은 동작입니까? (0) | 2020.10.27 |
iOS 7 iPad Safari Landscape innerHeight / outerHeight 레이아웃 문제 (0) | 2020.10.27 |
부모 CSS 스타일을 무시하는 방법 (0) | 2020.10.27 |
MSSQL GetDate ()를 사용할 때 날짜 만 가져 오려면 어떻게해야합니까? (0) | 2020.10.27 |