2009-02-02 4 views
31

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

В моих текущих тестах кажутся ABIT примитивно, что-то вдоль линий:

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

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

ответ

0

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

Assert.IsTrue(myDoc.Xml.ParseOK) 

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

5

Другая возможность может быть использование 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); 
    } 
+0

XMLUnit уже будут сравнивать XML-файлы и сосчитайте количество различий, если вы хотите ... – djangofan

3

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

4

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

+0

+1, и C# 's XmlSerialization может помочь в этом. – user7116

0

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

+0

есть лучший метод проверки с использованием XMLUnit ... – djangofan

20

Во-первых, поскольку почти все говорят, проверяйте 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); 

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

-1

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

Так что ваша строка сравнения:

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

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

0

Проверьте, что результирующий документ хорошо сформирован Проверьте, что результирующий документ действителен Проверьте полученный документ.

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

  • Некорректно спасся элементы
  • Некорректно спасся атрибуты следующим
  • Некорректно сбежавших имена элементов
  • Некорректно сбежавших имена атрибутов

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

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

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

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

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

1

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

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

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

0

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

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

6

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

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

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 в соответствии с вашими потребностями.

+1

Новая ссылка [здесь] (https://github.com/dennisdoomen/fluentassertions/wiki#xml-classes). –

+0

@BenGulapa Спасибо, ответьте на новые ссылки. – Holf

0

Вы можете использовать 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); 
Смежные вопросы