Подтвердить что ты не робот

Модульное тестирование XML Generation

Какие стратегии тестирования компонентов, которые люди рекомендуют для тестирования xml, генерируются правильно.

Мои текущие тесты кажутся примитивными, что-то вроде:

[Test]
public void pseudo_test()
{
   XmlDocument myDOC = new XmlDocument();
   mydoc = _task.MyMethodToMakeXMLDoc();

   Assert.AreEqual(myDoc.OuterXML(),"big string of XML")
}
4b9b3361

Ответ 1

Во-первых, поскольку почти все говорят, проверяйте XML, если для него определена схема. (Если нет, определите его.)

Но вы можете создавать тесты, которые намного более гранулированы, чем при выполнении запросов XPath к документу, например:

string xml="Your xml string here" ;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
path = "/doc/element1[@id='key1']/element2[. = 'value2']";
Assert.IsTrue(doc.SelectSingleNode(path) != null);

Это позволяет вам проверять не только, является ли ваш документ семантически допустимым, но и то, производит или нет его создающий метод с ожидаемыми значениями.

Ответ 2

XMLUnit может вам помочь.

Ответ 3

Другой возможностью может быть использование XmlReader и проверка количества ошибок > 0. Что-то вроде этого:

    void CheckXml()
    {
        string _xmlFile = "this.xml";
        string _xsdFile = "schema.xsd"; 
        StringCollection _xmlErrors = new StringCollection();

        XmlReader reader = null;
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationEventHandler += new ValidationEventHandler(this.ValidationEventHandler);
        settings.ValidationType = ValidationType.Schema;
        settings.IgnoreComments = chkIgnoreComments.Checked;
        settings.IgnoreProcessingInstructions = chkIgnoreProcessingInstructions.Checked;
        settings.IgnoreWhitespace = chkIgnoreWhiteSpace.Checked;
        settings.Schemas.Add(null, XmlReader.Create(_xsdFile));
        reader = XmlReader.Create(_xmlFile, settings);
        while (reader.Read())
        {
        }
        reader.Close();
        Assert.AreEqual(_xmlErrors.Count,0);
    }    

    void ValidationEventHandler(object sender, ValidationEventArgs args)
    {
        _xmlErrors.Add("<" + args.Severity + "> " + args.Message);
    }

Ответ 4

Fluent Assertions - отличная библиотека для выражения утверждений теста в свободном, легко читаемом стиле. Он работает со всеми основными модулями тестирования модулей.

В нем также есть полезная функциональность XML (все взяты из примеров здесь), например:

xElementA.Should().Be(xElementB);

xDocument.Should().HaveRoot("configuration");
xDocument.Should().HaveElement("settings");

xElement.Should().HaveAttribute("age", "36");
xElement.Should().HaveElement("address");

xAttribute.Should().HaveValue("Amsterdam");

Обратите внимание, что это работает с LINQ-To-XML, а не с объектом XmlDocument, указанным в исходном вопросе, но лично в эти дни мне кажется, что я использую LINQ-To-XML в качестве первого выбора.

Он также довольно легко расширяется, если вы хотите добавить дополнительные утверждения XML в соответствии с вашими потребностями.

Ответ 5

Проверяйте схему XML или DTD, также проверяйте ключ, что узлы имеют ожидаемые значения.

Ответ 6

Если у вас есть стандартный формат, который вы ожидаете от вывода, почему бы не создать схему XML или DTD и не подтвердить это. Это не будет зависеть от данных, поэтому будет гибким. Кроме того, определение того, как XML может быть сформировано, может быть полезно при проектировании вашей системы.

Ответ 7

Это сообщение в блоге от marianor дает легкий способ сравнить структуры XElement, поэтому я собираюсь попробовать это, прежде чем решать XMLUnit.

Первое, что нужно сделать, это нормализовать два XML файла... используя Linq... После того, как оба элемента были нормализованы, просто вы можете сравнить обе строки.

XML нормализуется путем сортировки имен элементов и атрибутов.

Ответ 8

почему бы не предположить, что какой-то коммерческий синтаксический анализатор xml корректен и проверяет ваш xml-код на него? что-то вроде.

Assert.IsTrue(myDoc.Xml.ParseOK)

кроме этого, и если вы хотите быть основательным, я бы сказал, что вам нужно будет самостоятельно создать парсер и проверить каждое правило, требуемое для спецификации xml.

Ответ 9

Подтвердите его против схемы XSD, используя класс XmlSchema. Его можно найти в System.XML, я думаю. Другой вариант - написать класс сериализации (XMLSerializer) для десериализации XML в объект. Усиление будет заключаться в том, что оно будет неявно проверять вашу структуру, и после этого значения могут быть легко доступны для тестирования с использованием результирующего объекта.

Ответ 10

Другой причиной использования схемы для проверки является то, что, хотя узлы XML явно упорядочены, атрибуты XML не являются.

Итак, ваше сравнение строк:

Assert.AreEqual(myDoc.OuterXML(),"big string of XML")

завершится с ошибкой, если атрибуты находятся в другом порядке, что может легко произойти, если один бит XML был создан вручную, а другой программно.

Ответ 11

Убедитесь, что результирующий документ сформирован Убедитесь, что результирующий документ действителен Убедитесь, что результирующий документ верен.

Предположительно, вы создаете XML-документ из полезных данных, поэтому вам нужно убедиться, что у вас есть правильный охват исходных данных для ваших тестов. Наиболее распространенными проблемами, которые я вижу, являются

  • Неправильно экранированные элементы
  • Неправильно экранированные атрибуты
  • Неверно сохраненные имена элементов
  • Неверно присвоенные имена атрибутов

Итак, если вы еще этого не сделали, вам нужно будет просмотреть спецификацию XML, чтобы узнать, что разрешено в каждом месте.

Сколько "проверок" должно произойти в каждом тесте, не сразу понятно. Полагаю, это будет зависеть от того, что подразделение находится в вашем проблемном пространстве. Кажется разумным, что каждый unit test проверяет правильность выражения одной части данных в XML. В этом случае я согласен с Робертом, что простая проверка того, что вы находите правильные данные в одном месте XPath, лучше всего.

Для более крупных автоматических тестов, где вы хотите проверить весь документ, я считаю, что эффективный результат - это ожидаемые результаты, которые также являются документом, и пройти через него node на node, используя XPath, чтобы найти соответствующий node в фактическом документе, а затем применить правильное сравнение данных, закодированных в этих двух узлах.

При таком подходе вы обычно захотите поймать все сбои сразу, вместо того, чтобы прервать первый сбой, поэтому вам может быть сложно понять, как вы отслеживаете, где произошли несоответствия.

С небольшим количеством работы вы можете распознавать определенные типы элементов как извинения из теста (например, отметки времени) или проверять, что они являются указателями на эквивалентные узлы, или... любой тип пользовательской проверки, которую вы хотите.

Ответ 12

Я планирую использовать эту новую проверку тестирования, чтобы помочь в тестировании XML.

Он выглядит идеально подходит для работы, но сначала прочитайте его, так как у меня нет опыта его использования.

Ответ 13

Вы можете использовать DTD для проверки достоверности сгенерированного xml.

Чтобы проверить правильность содержимого, я бы пошел на XMLUnit.

Утверждение xml с помощью XMLUnit:

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);