单元测试中的 XPath 断言
扩展 Visual Studio 单元测试断言
引言
XPath 断言允许你对返回或发出 XML 的代码进行单元测试。这在从 Web 应用程序到 XML 生成代码的任何地方都很有用。
背景
XPath 是一种 XML 查询标准。你使用 XPath 来检索 XML 节点 - 元素或属性。你可以将 XPath 视为一个具有有限功能集的 SQL 查询。XPath 语法在这里有详细文档。
.NET 通过其 System.Xml.Xpath 命名空间支持 XPath 版本 1.0 查询。
在本文中,我将介绍一个类,它封装了用于 MS .NET 单元测试框架的 XPath 断言。它可以很容易地转换为使用其他单元测试框架。
我在编写客户端-服务器应用程序时广泛使用了单元测试,该应用程序的双方都通过 XML 文档进行通信。所提供的代码允许我单独测试每一方,并为我节省了大量工作。希望对您有所帮助!
使用代码
XpathAssert
类公开静态方法,你调用这些方法来断言 XPath 表达式。该类核心的方法,所有其他方法都使用它,检索 XPath 表达式的结果集的迭代器
private static XPathNodeIterator GetIterator(XmlDocument xDoc, string xpath)
{
XPathNavigator xNav = xDoc.CreateNavigator();
XPathNodeIterator xItr = xNav.Select(xpath);
return xItr;
}
其他方法仅仅是围绕此方法的包装。例如,如果 XPath 查询产生意外的节点计数,此方法将失败
public static XPathNodeIterator NodeCountEquals(XmlDocument xDoc, string xpath, int expectedCount)
{
XPathNodeIterator xItr = GetIterator(xDoc, xpath);
Assert.AreEqual(expectedCount, xItr.Count,
string.Format("Xpath expression '{0}' was expected to return {1} results", xpath, expectedCount));
return xItr;
}
如果 XPath 查询产生具有意外子元素的結果,以下方法将失败
public static void LegitimateChildren(XmlDocument xDoc, string elemKidsXpath, params string[] legitimateChildren)
{
Assert.IsNotNull(legitimateChildren);
string allowedKids = string.Format("[name()!='{0}'", legitimateChildren[0]);
for (int i = 1; i < legitimateChildren.Length; ++i)
{
allowedKids += string.Format("and name()!='{0}'", legitimateChildren[i]);
}
string xpath = elemKidsXpath + allowedKids + "]";
NodeCountEquals(xDoc, xpath, 0);
}
如你所见,此方法修改查询以计算具有意外名称的子元素。断言测试结果计数是否为 0。
现在我们来看一些 XPath 断言
// Test XML node count
XpathAssert.NodeCountEquals(xmlDoc, "//updatecheck/urls/url", expectedUrlList.Count);
// Allow specific child node names
XpathAssert.LegitimateChildren(xmlDoc, "/response/*", "daystart", "app");
// XPath expressions yield equal node count
XpathAssert.NodeCountEqual(xmlDoc, "//ping", "//app/ping");
// Expect a minimal node count
XpathAssert.NodeCountMin(xmlDoc, "//urls[count(/*)=0]", 0);
关注点
这个类是我实现来扩展 MS 标准单元测试框架的几个类之一。在后续文章中,我将提供更多类。