在单元测试中验证 XML 的最佳方法是什么?

发布于 2024-07-04 13:48:00 字数 171 浏览 8 评论 0原文

我有一个带有生成 XML 的 ToString 方法的类。 我想对其进行单元测试以确保它生成有效的 xml。 我有一个 DTD 来验证 XML。

我应该将 DTD 作为字符串包含在单元测试中以避免对其的依赖,还是有更聪明的方法来做到这一点?

I have a class with a ToString method that produces XML. I want to unit test it to ensure it is producing valid xml. I have a DTD to validate the XML against.

Should I include the DTD as a string within the unit test to avoid a dependency on it, or is there a smarter way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

哑剧 2024-07-11 13:48:00

如果您的程序在正常执行期间根据 DTD 验证 XML,那么您应该从程序将获取 DTD 的任何地方获取它。

如果不是,并且 DTD 非常短(只有几行),那么将其作为字符串存储在代码中可能就可以了。

否则,我会将其放入外部文件中,并让您的单元测试从该文件中读取它。

If your program validates the XML against the DTD during normal execution, then you should just get the DTD from wherever your program will get it.

If not and the DTD is extremely short (only a few lines), then storing it as a string in your code is probably okay.

Otherwise, I'd put it in an external file and have your unit test read it from that file.

陌伤ぢ 2024-07-11 13:48:00

在单元测试中使用 DTD 来测试其有效性是一回事,测试内容的正确性又是另一回事。

您可以使用 DTD 来检查生成的 xml 的有效性,我将按照您在程序中的方式简单地读取它。 我个人不会将其包含在内联(作为字符串); 应用程序代码和单元测试之间始终存在依赖关系。 当生成的xml发生变化时,DTD也会发生变化。

为了测试正确的内容,我会选择 XMLUnit

使用 XMLUnit 断言 xml:

XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

Diff diff = new Diff(expectedDocument, obtainedDocument);
XMLAssert.assertXMLIdentical("xml invalid", diff, true);

您可能会遇到的一件事是生成的 xml 可能包含更改的标识符(id/uid 属性或类似属性)。 这可以通过使用 DifferenceListener 来解决断言生成的 xml。

这种 DifferenceListener 的示例实现:

public class IgnoreVariableAttributesDifferenceListener implements DifferenceListener {

    private final List<String> IGNORE_ATTRS;
    private final boolean ignoreAttributeOrder;

    public IgnoreVariableAttributesDifferenceListener(List<String> attributesToIgnore, boolean ignoreAttributeOrder) {
        this.IGNORE_ATTRS = attributesToIgnore;
        this.ignoreAttributeOrder = ignoreAttributeOrder;
    }

    @Override
    public int differenceFound(Difference difference) {
        // for attribute value differences, check for ignored attributes
        if (difference.getId() == DifferenceConstants.ATTR_VALUE_ID) {
            if (IGNORE_ATTRS.contains(difference.getControlNodeDetail().getNode().getNodeName())) {
                return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }
        // attribute order mismatch (optionally ignored)
        else if (difference.getId() == DifferenceConstants.ATTR_SEQUENCE_ID && ignoreAttributeOrder) {
            return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
        }
        // attribute missing / not expected
        else if (difference.getId() == DifferenceConstants.ATTR_NAME_NOT_FOUND_ID) {
            if (IGNORE_ATTRS.contains(difference.getTestNodeDetail().getValue())) {
                return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }

        return RETURN_ACCEPT_DIFFERENCE;
    }

    @Override
    public void skippedComparison(Node control, Node test) {
        // nothing to do
    }
}

使用 DifferenceListener:

    XMLUnit.setIgnoreWhitespace(true);
    XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

    Diff diff = new Diff(expectedDocument, obtainedDocument);
    diff.overrideDifferenceListener(new IgnoreVariableAttributesDifferenceListener(Arrays.asList("id", "uid"), true));

    XMLAssert.assertXMLIdentical("xml invalid", diff, true);

Using a DTD in the unit test to test its validity is one thing, testing for the correct content is another.

You can use the DTD to check for the validity of the generated xml which I would simply read the way you do in your program. I personally would not include it inline (as a String); there is always a dependency between you application code and the unit test. When the generated xml changes, the DTD will also change.

To test for the correct content I would go for XMLUnit.

Asserting xml using XMLUnit:

XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

Diff diff = new Diff(expectedDocument, obtainedDocument);
XMLAssert.assertXMLIdentical("xml invalid", diff, true);

One thing you might come across is the fact that the generated xml might contain changing identifiers (id/uid attributes or alike). This can be solved by using a DifferenceListener when asserting the generated xml.

Example implementation of such DifferenceListener:

public class IgnoreVariableAttributesDifferenceListener implements DifferenceListener {

    private final List<String> IGNORE_ATTRS;
    private final boolean ignoreAttributeOrder;

    public IgnoreVariableAttributesDifferenceListener(List<String> attributesToIgnore, boolean ignoreAttributeOrder) {
        this.IGNORE_ATTRS = attributesToIgnore;
        this.ignoreAttributeOrder = ignoreAttributeOrder;
    }

    @Override
    public int differenceFound(Difference difference) {
        // for attribute value differences, check for ignored attributes
        if (difference.getId() == DifferenceConstants.ATTR_VALUE_ID) {
            if (IGNORE_ATTRS.contains(difference.getControlNodeDetail().getNode().getNodeName())) {
                return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }
        // attribute order mismatch (optionally ignored)
        else if (difference.getId() == DifferenceConstants.ATTR_SEQUENCE_ID && ignoreAttributeOrder) {
            return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
        }
        // attribute missing / not expected
        else if (difference.getId() == DifferenceConstants.ATTR_NAME_NOT_FOUND_ID) {
            if (IGNORE_ATTRS.contains(difference.getTestNodeDetail().getValue())) {
                return RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
            }
        }

        return RETURN_ACCEPT_DIFFERENCE;
    }

    @Override
    public void skippedComparison(Node control, Node test) {
        // nothing to do
    }
}

using DifferenceListener:

    XMLUnit.setIgnoreWhitespace(true);
    XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);

    Diff diff = new Diff(expectedDocument, obtainedDocument);
    diff.overrideDifferenceListener(new IgnoreVariableAttributesDifferenceListener(Arrays.asList("id", "uid"), true));

    XMLAssert.assertXMLIdentical("xml invalid", diff, true);
初心未许 2024-07-11 13:48:00

我过去使用过 XmlUnit 并发现它很有用。

它可用于根据架构验证 XML 或将 XML 与字符串进行比较。 它足够聪明,能够理解XML的解析规则。
例如,它知道“” 相当于“” 并且可以配置为忽略或包含空格。

I've used XmlUnit in the past and found it to be useful.

It can be used to validate XML against a schema or compare your XML against a string. It is clever enough to understand XML's parsing rules.
For example it knows that "<e1/>" is equivalent to "<e1></e1>" and can be configured to ignore or include whitespace.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文