我正在使用.NET 2.0,最近的代码更改使我以前的Assert.AreEqual调用失效(它比较了两个XML字符串)。在新的代码库中,只有一个XML元素实际上是不同的,所以我希望对所有其他元素进行比较会得到我想要的结果。比较需要以编程方式完成,因为它是单元测试的一部分。
起初,我正在考虑使用几个XmlDocument实例。但后来我发现了这个: http://drowningintechnicaldebt.com/blogs/scottroycraft/archive/2007/05/06/comparing-xml-files.aspx
看起来它可能有效,但我对Stack Overflow反馈感兴趣,以防有更好的方法。
如果可能的话,我想避免为此添加另一个依赖项。
答案 0 :(得分:10)
这实际上取决于你想要检查的“差异”。
目前,我们正在使用Microsoft XmlDiff:http://msdn.microsoft.com/en-us/library/aa302294.aspx
答案 1 :(得分:4)
您可能会发现将XML解析为XmlDocument并将您的Assert调用基于XPath Query不太脆弱。以下是我经常使用的一些辅助断言方法。每个都使用XPathNavigator,您可以通过在XmlDocument上或从文档中检索的任何节点上调用CreateNavigator()来获取它。使用的一个例子是:
XmlDocument doc = new XmlDocument( "Testdoc.xml" );
XPathNavigator nav = doc.CreateNavigator();
AssertNodeValue( nav, "/root/foo", "foo_val" );
AssertNodeCount( nav, "/root/bar", 6 )
private static void AssertNodeValue(XPathNavigator nav,
string xpath, string expected_val)
{
XPathNavigator node = nav.SelectSingleNode(xpath, nav);
Assert.IsNotNull(node, "Node '{0}' not found", xpath);
Assert.AreEqual( expected_val, node.Value );
}
private static void AssertNodeExists(XPathNavigator nav,
string xpath)
{
XPathNavigator node = nav.SelectSingleNode(xpath, nav);
Assert.IsNotNull(node, "Node '{0}' not found", xpath);
}
private static void AssertNodeDoesNotExist(XPathNavigator nav,
string xpath)
{
XPathNavigator node = nav.SelectSingleNode(xpath, nav);
Assert.IsNull(node, "Node '{0}' found when it should not exist", xpath);
}
private static void AssertNodeCount(XPathNavigator nav, string xpath, int count)
{
XPathNodeIterator nodes = nav.Select( xpath, nav );
Assert.That( nodes.Count, Is.EqualTo( count ) );
}
答案 2 :(得分:1)
在xml
字符串上进行简单的字符串比较并不总是有效。为什么?
例如:
<MyElement></MyElmennt>
和<MyElment/>
从xml
角度来看是相等的。
有一些转换算法使xml
看起来总是一样,它们被称为
规范化算法。 .Net
支持规范化。
答案 3 :(得分:1)
我写了一个带有断言序列化的小型库,source。
示例:
[Test]
public void Foo()
{
...
XmlAssert.Equal(expected, actual, XmlAssertOptions.IgnoreDeclaration | XmlAssertOptions.IgnoreNamespaces);
}
答案 4 :(得分:0)
由于XML文件的内容可以具有不同的格式,并且在测试相等性时仍然被认为是相同的(从DOM的角度来看),您需要确定该等式的度量是什么,例如格式忽略?元数据被忽略等等是重要的,很多边缘情况。
通常,您将创建一个定义相等规则的类并将其用于比较,如果您的比较类实现了IEqualityComparer and/or IEqualityComparer<T>
接口,那么您的类可以在一堆内置框架列表中用作同样测试实现也是如此。此外,当然,根据您的要求,您可以根据需要尽可能多地衡量平等。
即
IEnumerable<T>.Contains
IEnumerable<T>.Equals
The constructior of a Dictionary etc etc
答案 5 :(得分:0)
我最终使用以下代码获得了我想要的结果:
private static void ValidateResult(string validationXml, XPathNodeIterator iterator, params string[] excludedElements)
{
while (iterator.MoveNext())
{
if (!((IList<string>)excludedElements).Contains(iterator.Current.Name))
{
Assert.IsTrue(validationXml.Contains(iterator.Current.Value), "{0} is not the right value for {1}.", iterator.Current.Value, iterator.Current.Name);
}
}
}
在调用方法之前,我以这种方式在XmlDocument实例上创建一个导航器:
XPathNavigator nav = xdoc.CreateNavigator();
接下来,我创建一个XPathExpression实例,如下所示:
XPathExpression expression = XPathExpression.Compile("/blah/*");
在使用表达式
创建迭代器后调用该方法XPathNodeIterator iterator = nav.Select(expression);
我仍然在想如何进一步优化它,但它现在可以解决这个问题。
答案 6 :(得分:0)
我做了一个创建简单XML路径的方法。
static XElement MakeFromXPath(string xpath)
{
XElement root = null;
XElement parent = null;
var splits = xpath.Split('/'); //split xpath into parts
foreach (var split in splits)
{
var el = new XElement(split);
if (parent != null)
parent.Add(el);
else
root = el; //first element created, set as root
parent = el;
}
return root;
}
样品用量:
var element = MakeFromXPath("My/Path/To/Element")'
element
将包含值:
<My>
<Path>
<To>
<Element></Element>
</To>
</Path>
</My>