2009-02-02 44 views
31

¿Qué estrategias de pruebas unitarias recomiendan las personas para probar que xml se está generando correctamente?Pruebas unitarias XML Generation

Los mis pruebas actuales parecen un poco primitiva, algo a lo largo de las líneas de:

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

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

Respuesta

0

por qué no suponer que algunos analizador XML comercial es correcta y validar el código XML en contra de ella? algo como.

Assert.IsTrue(myDoc.Xml.ParseOK) 

aparte de eso y si quieres ser exhaustiva diría que tendría que construir un analizador de ti mismo y validar cada regla requiere la especificación XML.

5

Otra posibilidad podría ser la de utilizar XmlReader y compruebe si hay un recuento de errores> 0. Algo como esto:

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 ya se compararán los archivos XML y contar el número de diferencias si quieres ... – djangofan

3

Si usted tiene un formato estándar que se puede esperar que la salida sea, por qué no crear un XML esquema o DTD y validar contra eso. Esto no dependerá de los datos, por lo que será flexible. También definir cómo se puede formar el XML puede ser útil al diseñar su sistema.

4

Valide contra el esquema XML o DTD, también compruebe que los nodos tienen los valores que espera.

+0

1, y C# 's XmlSerialization podría ayudar con esto. – user7116

0

Validarlo con un esquema XSD utilizando la clase XmlSchema. Se encuentra en System.XML, creo. Otra opción sería escribir una clase de serialización (XMLSerializer) para deserializar su XML en un objeto. La ganancia será que validará implícitamente su estructura y luego se podrá acceder fácilmente a los valores para realizar pruebas utilizando el objeto resultante.

+0

existe un mejor método de validación usando XMLUnit ... – djangofan

20

En primer lugar, como todo el mundo dice, valide el XML si hay un esquema definido para él. (Si no hay, definir una.)

Pero se puede construir pruebas que son mucho más granular que que al ejecutar consultas XPath contra el documento, por ejemplo:

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

Esto le permite probar no sólo si o no, su documento es semánticamente válido, pero si el método que lo produce está llenándolo con los valores que espera.

-1

Otra razón para usar un esquema para validar contra es que mientras que los nodos XML se ordenan explícitamente, los atributos XML no lo son.

Por lo que su comparación de cadenas de:

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

fallaría si los atributos están en un orden diferente, como podría ocurrir fácilmente si un bit de XML fue creado manualmente y el otro mediante programación.

0

Verificar que el documento resultante esté bien formado Verificar que el documento resultante sea válido Verificar que el documento resultante sea el correcto.

Presumiblemente, está creando un documento XML a partir de datos útiles, por lo que querrá asegurarse de tener la cobertura correcta de las entradas para sus pruebas.Los problemas más comunes que veo son

  • incorrectamente escaparon elementos
  • incorrectamente escaparon atributos
  • incorrectamente escapado nombres de los elementos
  • nombres de atributos incorrectamente escapado

Así que si aún no lo ha hecho por lo tanto, necesitaría revisar las especificaciones XML para ver lo que está permitido en cada lugar.

La cantidad de "verificación" que debería ocurrir en cada prueba no está clara inmediatamente. Dependerá mucho de lo que sea una unidad en su espacio problemático, supongo. Parece razonable que cada prueba unitaria verifique que una pieza de datos esté correctamente expresada en el XML. En este caso, estoy de acuerdo con Robert en que una simple comprobación de que encuentre los datos correctos en una única ubicación XPath es la mejor.

Para las pruebas automáticas más grandes, en las que desea comprobar todo el documento, lo que he encontrado efectivo es tener un resultado esperado que también es un documento, y recorrerlo nodo por nodo, usando expresiones XPath para encuentre el nodo correspondiente en el documento real y luego aplique la comparación correcta de los datos codificados en los dos nodos.

Con este enfoque, normalmente querrá detectar todas las fallas a la vez, en lugar de abortar en la primera falla, por lo que es posible que tenga que ser truculento acerca de cómo rastrear dónde se produjeron desajustes.

Con un poco más de trabajo, puede reconocer ciertos tipos de elementos como excusados ​​de una prueba (como una marca de tiempo), o para validar que son punteros a nodos equivalentes, o ... cualquier tipo de verificación personalizada que querer.

1

This blog post por marianor ofrece una manera ligera de comparar estructuras XElement, así que voy a intentarlo antes de abordar XMLUnit.

Lo primero que debe hacer es normalizar los dos XML ... utilizando Linq ... Después de que ambos elementos se normalizaron, simplemente puede comparar ambas cadenas.

El XML se normaliza ordenando los nombres de elementos y atributos.

0

Planeo usar esta nueva biblioteca Approval Testing para ayudar con las pruebas XML.

Parece ser perfecto para el trabajo, pero léelo primero ya que no tengo experiencia en usarlo.

6

Fluent Assertions es una excelente biblioteca para expresar las afirmaciones de prueba en un estilo fluido y fácil de leer. Funciona con todos los principales marcos de pruebas de unidades.

También tiene algunas funciones útiles XML (todos tomados de los ejemplos here), por ejemplo:

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

Tenga en cuenta que esto funciona con LINQ to XML en lugar del objeto XMLDocument especificado en la pregunta original pero personalmente estos días encuentro que estoy usando LINQ-To-XML como primera opción.

También es bastante fácil de ampliar, si desea agregar más afirmaciones XML para satisfacer sus necesidades.

+1

Nuevo enlace [aquí] (https://github.com/dennisdoomen/fluentassertions/wiki#xml-classes). –

+0

@BenGulapa Gracias, respuesta actualizada con nuevos enlaces. – Holf

0

Puede usar una DTD para verificar la validez del xml generado.

Para probar el contenido correcto, me gustaría XMLUnit.

Afirmar XML utilizando XMLUnit:

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

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

Una cosa que puede venir a través es el hecho de que el XML generado puede contener cambiantes identificadores (id/atributos UID o igual). Esto se puede resolver usando un DifferenceListener al afirmar el xml generado.

Ejemplo implementación de tales 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 
    } 
} 

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