メソッドのテストはEquals
(私の知る限り)非常に簡単です。しかし、一体どのようにしてメソッドをテストするのGetHashCode
でしょうか?
7 に答える
等しい 2 つの異なるオブジェクトが同じハッシュ コードを持つことをテストします (さまざまな値に対して)。等しくないオブジェクトが異なるハッシュ コードを与え、一度に 1 つの側面/プロパティが変化することを確認します。ハッシュ コードが異なる必要はありませんが、バグがない限り、たまたま同じハッシュ コードを与えるプロパティに異なる値を選択するのは本当に運が悪いでしょう。
Gallio/MbUnit v3.2GetHashCode()
には、との実装をテストできる便利なコントラクト検証ツールが付属していますIEquatable<T>
。EqualityContract
より具体的には、およびに興味があるかもしれませんHashCodeAcceptanceContract
。詳細については、ここ、ここ、およびそこを参照してください。
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))
};
}
Equals() とかなり似ています。「同じ」2 つのオブジェクトが少なくとも同じハッシュ コードを持っていることを確認する必要があります。つまり、.Equals() が true を返す場合、ハッシュ コードも同一である必要があります。適切なハッシュコード値に関する限り、それはハッシュ方法によって異なります。
個人的な経験から。同じオブジェクトが同じハッシュ コードを与えるなどの明白なことは別として、一意のオブジェクトの十分な大きさの配列を作成し、それらの間で一意のハッシュ コードをカウントする必要があります。一意のハッシュ コードが全体のオブジェクト数の 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);
同じ値を持つ個別のインスタンスを作成し、インスタンスの GetHashCode が同じ値を返すこと、および同じインスタンスで繰り返し呼び出しを行うと同じ値が返されることを確認します。
これは、ハッシュ コードが機能するための唯一の要件です。うまく機能するためには、もちろん、ハッシュ コードが適切に分散されている必要がありますが、それをテストするには多くのテストが必要です...
既知の/予想されるハッシュを事前に提供し、GetHashCode の結果を比較します。