2009-11-08 2 views

답변

30

동일한 두 개의 서로 다른 개체가 동일한 해시 코드 (다양한 값)를 가지고 있는지 테스트합니다. 동일하지 않은 객체가 한 번에 하나의 애스펙트/속성을 변화시키는 다른 해시 코드를 제공하는지 확인하십시오. 해시 코드가 일 때이 다른 것은 아니지만 성격이 다른 값을 선택하는 것은 정말 불행한 일입니다. 이 발생하면은 버그가없는 한 동일한 해시 코드를 제공합니다.

+0

내장 된 일부 유형에 대해 동일한 해시 코드를 얻는 것은 매우 쉽습니다. 예를 들어 새로운 Point (1,1) .GetHashCode()와 새로운 Point (2,2) .GetHashCode()는 같은 값을 제공합니다. – Guffa

+6

다른 사람의 코드가 잘 분산 된 해시 값을 생성하지 못해도 코드에 대한 좋은 테스트가 아님을 의미하지는 않습니다. –

+0

@ Pete : 맞아. 그래서 해시 코드에 XOR을 사용하지 않습니다 ... –

0

나는 알려진/예상되는 해시를 미리 제공하고 GetHashCode의 결과가 무엇인지 비교합니다.

+7

그러면 테스트가 매우 약해집니다. 예를 들어, GetHashCode가 이전 버전에서 부여한 것의 부정 된 값을 반환하도록 할 수 있어야하며 메서드는 여전히 유효합니다. 당신이 신경 쓰는 것을 테스트하십시오. 이것은 동일하거나 다른 값의 해시 코드를 비교하는 것입니다. –

+0

잘 부탁드립니다. 의견을 보내 주셔서 감사합니다. – Myles

5

Equals()와 매우 비슷합니다. "같음"인 두 객체가 적어도 같은 해시 코드를 가졌는지 확인하고 싶을 것입니다. 즉, .Equals()가 true를 반환하면 해시 코드도 동일해야합니다. 지금까지 올바른 해시 코드 값이 무엇인지는 해싱 방법에 따라 다릅니다.

+0

+1 - 그건 분명히 한 가지 시험입니다. 배포는 잊어라.하지만 같은 객체는 반드시 같은 해시 코드를 가져야한다. – TomTom

0

동일한 값을 사용하여 별도의 인스턴스를 만들고 인스턴스의 GetHashCode가 동일한 값을 반환하고 동일한 인스턴스에서 반복되는 호출이 동일한 값을 반환하는지 확인합니다.

해시 코드가 작동하는 유일한 요구 사항입니다. 잘 작동하려면 해시 코드는 물론 좋은 배포를 가져야하지만 그 테스트를 위해서는 많은 테스트가 필요합니다 ...

3

개인적인 경험에서. 똑같은 객체가 같은 해시 코드를 제공하는 명백한 것들을 제외하고, 고유 한 객체 배열을 충분히 많이 생성하고 그 중 고유 한 해시 코드를 계산해야합니다. 고유 한 해시 코드가 전체 개체 수의 50 % 미만이라고하면 해시 함수가 좋지 않아 문제가 발생합니다.

 List<int> hashList = new List<int>(testObjectList.Count); 
     for (int i = 0; i < testObjectList.Count; i++) 
     { 
      hashList.Add(testObjectList[i]); 
     } 

     hashList.Sort(); 
     int differentValues = 0; 
     int curValue = hashList[0]; 
     for (int i = 1; i < hashList.Count; i++) 
     { 
      if (hashList[i] != curValue) 
      { 
       differentValues++; 
       curValue = hashList[i]; 
      } 
     } 

     Assert.Greater(differentValues, hashList.Count/2); 
9

Gallio/MbUnit v3.2GetHashCode()IEquatable<T>의 구현을 테스트 할 수있는 편리한 계약 검증기와 함께 제공됩니다. 더 구체적으로는 EqualityContractHashCodeAcceptanceContract입니다. 자세한 내용은 here, herethere을 참조하십시오. 그런 다음

public class Spot 
{ 
    private readonly int x; 
    private readonly int y; 

    public Spot(int x, int y) 
    { 
    this.x = x; 
    this.y = y; 
    } 

    public override int GetHashCode() 
    { 
    int h = -2128831035; 
    h = (h * 16777619)^x; 
    h = (h * 16777619)^y; 
    return h; 
    } 
} 

는이 같은 계약 검증을 선언

해당 개체의 평등을 확인하는 것 외에도
[TestFixture] 
public class SpotTest 
{ 
    [VerifyContract] 
    public readonly IContract HashCodeAcceptanceTests = new HashCodeAcceptanceContract<Spot>() 
    { 
    CollisionProbabilityLimit = CollisionProbability.VeryLow, 
    UniformDistributionQuality = UniformDistributionQuality.Excellent, 
    DistinctInstances = DataGenerators.Join(Enumerable.Range(0, 1000), Enumerable.Range(0, 1000)).Select(o => new Spot(o.First, o.Second)) 
    }; 
} 
0

는 해시 코드의 평등을 의미하고, 해시의 분포가 얀 Trevin에 의해 제안 상당히 평평하다 (있는 경우 성능 문제가있는 경우) 개체의 속성을 변경하면 어떤 일이 발생하는지 고려할 수도 있습니다.

사전/해시 세트에있는 동안 개체가 변경된다고 가정합니다. Contains (객체)를 여전히 true로 유지 하시겠습니까? 그렇다면 GetHashCode가 변경된 변경 가능한 속성에 의존하지 않는 것이 좋습니다.