当您有一个简单的方法(例如sum(int x,int y))时,编写单元测试很容易。您可以检查该方法是否正确求和两个样本整数,例如2 + 3应该返回5,然后您将检查某些“非常规”数字是否相同,例如负值和零。这些每个都应该是单独的单元测试,因为单个单元测试应该包含单个断言。
当您有复杂的输入输出时,该怎么办?以Xml解析器为例。您可以使用单个方法parse(String xml)来接收String并返回一个Dom对象。您可以编写单独的测试,以检查某些文本节点是否正确解析,属性是否正确解析,该子节点属于父级等。对于所有这些,我都可以编写一个简单的输入,例如
<root><child/></root>
Run Code Online (Sandbox Code Playgroud)
它将用于检查节点之间的父子关系,以此类推。
现在,看看以下Xml:
<root>
<child1 attribute11="attribute 11 value" attribute12="attribute 12 value">Text 1</child1>
<child2 attribute21="attribute 21 value" attribute22="attribute 22 value">Text 2</child2>
</root>
Run Code Online (Sandbox Code Playgroud)
为了检查该方法是否正常工作,我需要检查许多复杂的条件,例如attribute11和attribute12属于element1,Text 1属于child1等。我不想在单元测试中放置多个断言。我该怎么做?
您所需要的-是在单独的测试中检查SUT(被测系统)的一个方面。
[TestFixture]
public class XmlParserTest
{
[Test, ExpectedException(typeof(XmlException))]
public void FailIfXmlIsNotWellFormed()
{
Parse("<doc>");
}
[Test]
public void ParseShortTag()
{
var doc = Parse("<doc/>");
Assert.That(doc.DocumentElement.Name, Is.EqualTo("doc"));
}
[Test]
public void ParseFullTag()
{
var doc = Parse("<doc></doc>");
Assert.That(doc.DocumentElement.Name, Is.EqualTo("doc"));
}
[Test]
public void ParseInnerText()
{
var doc = Parse("<doc>Text 1</doc>");
Assert.That(doc.DocumentElement.InnerText, Is.EqualTo("Text 1"));
}
[Test]
public void AttributesAreEmptyifThereAreNoAttributes()
{
var doc = Parse("<doc></doc>");
Assert.That(doc.DocumentElement.Attributes, Has.Count(0));
}
[Test]
public void ParseAttribute()
{
var doc = Parse("<doc attribute11='attribute 11 value'></doc>");
Assert.That(doc.DocumentElement.Attributes[0].Name, Is.EqualTo("attribute11"));
Assert.That(doc.DocumentElement.Attributes[0].Value, Is.EqualTo("attribute 11 value"));
}
[Test]
public void ChildNodesInnerTextAtFirstLevel()
{
var doc = Parse(@"<root>
<child1>Text 1</child1>
<child2>Text 2</child2>
</root>");
Assert.That(doc.DocumentElement.ChildNodes, Has.Count(2));
Assert.That(doc.DocumentElement.ChildNodes[0].InnerText, Is.EqualTo("Text 1"));
Assert.That(doc.DocumentElement.ChildNodes[1].InnerText, Is.EqualTo("Text 2"));
}
// More tests
.....
private XmlDocument Parse(string xml)
{
var doc = new XmlDocument();
doc.LoadXml(xml);
return doc;
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法具有很多优点:
UPD:参见Gerard Meszaros(xUnit测试模式书的作者)对以下主题的看法:xunitpatterns
每个测试验证一个条件的一个可能有争议的方面是我们所说的“一个条件”。一些测试驱动程序坚持每个测试一个声明。这种坚持可以基于使用“测试方法”的“每个灯具”组织的“测试用例类”,并基于一个断言正在验证的内容(例如AwaitingApprovalFlight.validApproverRequestShouldBeApproved)来命名每个测试。每个测试只有一个断言,这样的命名非常容易,但是如果我们必须对许多输出字段进行断言,确实会导致更多的测试方法。当然,我们通常可以通过提取自定义断言(第X页)或验证方法(请参阅自定义断言)来遵循这种解释,这使我们可以将多个断言方法调用减少为一个。