Equals
메서드를 테스트하는 것은 꽤 간단합니다 (지금까지 내가 아는 한). 그러나 어떻게 지구상에서 GetHashCode
방법을 테스트합니까?C# : 어떻게 단위 테스트 GetHashCode겠습니까?
답변
동일한 두 개의 서로 다른 개체가 동일한 해시 코드 (다양한 값)를 가지고 있는지 테스트합니다. 동일하지 않은 객체가 한 번에 하나의 애스펙트/속성을 변화시키는 다른 해시 코드를 제공하는지 확인하십시오. 해시 코드가 일 때이 다른 것은 아니지만 성격이 다른 값을 선택하는 것은 정말 불행한 일입니다. 이 발생하면은 버그가없는 한 동일한 해시 코드를 제공합니다.
나는 알려진/예상되는 해시를 미리 제공하고 GetHashCode의 결과가 무엇인지 비교합니다.
그러면 테스트가 매우 약해집니다. 예를 들어, GetHashCode가 이전 버전에서 부여한 것의 부정 된 값을 반환하도록 할 수 있어야하며 메서드는 여전히 유효합니다. 당신이 신경 쓰는 것을 테스트하십시오. 이것은 동일하거나 다른 값의 해시 코드를 비교하는 것입니다. –
잘 부탁드립니다. 의견을 보내 주셔서 감사합니다. – Myles
Equals()와 매우 비슷합니다. "같음"인 두 객체가 적어도 같은 해시 코드를 가졌는지 확인하고 싶을 것입니다. 즉, .Equals()가 true를 반환하면 해시 코드도 동일해야합니다. 지금까지 올바른 해시 코드 값이 무엇인지는 해싱 방법에 따라 다릅니다.
+1 - 그건 분명히 한 가지 시험입니다. 배포는 잊어라.하지만 같은 객체는 반드시 같은 해시 코드를 가져야한다. – TomTom
동일한 값을 사용하여 별도의 인스턴스를 만들고 인스턴스의 GetHashCode가 동일한 값을 반환하고 동일한 인스턴스에서 반복되는 호출이 동일한 값을 반환하는지 확인합니다.
해시 코드가 작동하는 유일한 요구 사항입니다. 잘 작동하려면 해시 코드는 물론 좋은 배포를 가져야하지만 그 테스트를 위해서는 많은 테스트가 필요합니다 ...
개인적인 경험에서. 똑같은 객체가 같은 해시 코드를 제공하는 명백한 것들을 제외하고, 고유 한 객체 배열을 충분히 많이 생성하고 그 중 고유 한 해시 코드를 계산해야합니다. 고유 한 해시 코드가 전체 개체 수의 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);
Gallio/MbUnit v3.2는 GetHashCode()
및 IEquatable<T>
의 구현을 테스트 할 수있는 편리한 계약 검증기와 함께 제공됩니다. 더 구체적으로는 EqualityContract
및 HashCodeAcceptanceContract
입니다. 자세한 내용은 here, here 및 there을 참조하십시오. 그런 다음
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))
};
}
는 해시 코드의 평등을 의미하고, 해시의 분포가 얀 Trevin에 의해 제안 상당히 평평하다 (있는 경우 성능 문제가있는 경우) 개체의 속성을 변경하면 어떤 일이 발생하는지 고려할 수도 있습니다.
사전/해시 세트에있는 동안 개체가 변경된다고 가정합니다. Contains (객체)를 여전히 true로 유지 하시겠습니까? 그렇다면 GetHashCode가 변경된 변경 가능한 속성에 의존하지 않는 것이 좋습니다.
내장 된 일부 유형에 대해 동일한 해시 코드를 얻는 것은 매우 쉽습니다. 예를 들어 새로운 Point (1,1) .GetHashCode()와 새로운 Point (2,2) .GetHashCode()는 같은 값을 제공합니다. – Guffa
다른 사람의 코드가 잘 분산 된 해시 값을 생성하지 못해도 코드에 대한 좋은 테스트가 아님을 의미하지는 않습니다. –
@ Pete : 맞아. 그래서 해시 코드에 XOR을 사용하지 않습니다 ... –