如何测试两个对象集合是否基于其中一个对象的属性处于不同的顺序?



我对单元测试相当陌生,遇到了一个问题。我有两个收藏(套牌(保存对象(卡片(,卡片是具有ID,值,花色等的对象。

我正在编写一个单元测试以查看我的 Shuffle(( 方法是否有效,所以我想测试未洗牌的套牌(创建 52 张 ID 为 0-51 的牌(和洗牌组的顺序是否相同。 显然,卡片是唯一的对象,即使它们具有相同的值。因此,根据定义,测试它们是否相同总是会导致 false。我对 NUnit 非常非常陌生(两天前刚刚安装它(,我仍然在这里和那里为语法而苦苦挣扎。

理想情况下,我想要一个断言来检查两个集合的顺序是否相同,顺序由卡片的 ID 决定,因为作为对象,它们都是唯一的,因此总是处于不同的顺序。 现在,我可以检查洗牌的牌组是否不再按 ID 排序,但这将是一个糟糕的单元测试,因为它假设未洗牌的牌组总是按 ID 排序。我也可以检查未洗牌的套牌,但是在没有实际比较两套牌的情况下以这种方式对其进行测试似乎相当不优雅。

我还想要一个断言来检查我的 deck 构造函数是否只创建唯一的 ID,但同样,集合中的所有对象始终是唯一的,但我不知道用于检查所有卡的一个特定属性的唯一性的语法(如果存在(。

我一直在疯狂地谷歌搜索,我一直在通过蛮力尝试许多不同的语法,但现在我不知所措。希望你们能帮到我,提前谢谢!

若要使用Id属性确定卡片的顺序是否相同,只需将该属性选择到IEnumerable中,然后使用System.Linq扩展方法SequenceEqual它们:

// Where 'unshuffled' and 'shuffled' are both 'List<Card>' objects
var areEqual = unshuffled.Select(c => c.Id).SequenceEqual(shuffled.Select(c => c.Id));

或者,您可以在Card类上覆盖EqualsGetHashCode,然后将其用于相等比较。这将有助于可能需要的其他卡片比较:

public class Card : IEquatable<Card>
{
public int Id { get; set; }
public bool Equals(Card other)
{
return Id == other?.Id;
}
public override bool Equals(object obj)
{
return Equals(obj as Card);
}
public override int GetHashCode()
{
return Id;
}
}

现在我们的比较代码稍微简单一些:

var areEqual = unshuffled.SequenceEqual(shuffled);

您可以将SequnceEqual与 LINQSelect一起使用,如下所示:

class Card
{
public int CardId { get; set; }
}
Assert.IsTrue(new[] { new Card {CardId = 1}, new Card {CardId = 2}}
.Select(c => c.CardId)
.SequenceEqual(new[] {1,2}));

另外,我建议查看Fluent Assertions库,有时如何在那里做事不是很明显,但总的来说它具有一些非常有用的功能。

对于仅使用 NUnit 功能的情况,最简单的方法是

Assert.That(shuffled, Is.Not.EqualTo(unshuffled);

请注意,这假定您已覆盖卡对象的等于。

为什么这有效...

  1. 你的套牌都有52张牌
  2. 您还在测试(我假设这一点(每副牌都包含正确的 52 张牌。
  3. NUnit 集合上的相等性定义为每对元素,按顺序排列,相等。

对于全套测试,我可能希望确保甲板大小不会改变,并且所有元素都是唯一的。像...

Assert.That(shuffled, Is.EqualTo(DECK_SIZE);
Assert.That(shuffled, Is.Unique);
Assert.That(shuffled, Is.Not.EqualTo(unshuffled));

相关内容

最新更新