A melhor maneira de validar XML em um teste unitário?
-
09-06-2019 - |
Pergunta
Eu tenho uma aula com um ToString
método que produz XML.Quero fazer um teste de unidade para garantir que está produzindo xml válido.Eu tenho um DTD para validar o XML.
Devo incluir o DTD como uma string no teste de unidade para evitar uma dependência nele, ou existe uma maneira mais inteligente de fazer isso?
Solução
Se o seu programa validar o XML em relação ao DTD durante a execução normal, você deverá obter o DTD de onde quer que seu programa o obtenha.
Caso contrário, e o DTD for extremamente curto (apenas algumas linhas), provavelmente não há problema em armazená-lo como uma string em seu código.
Caso contrário, eu o colocaria em um arquivo externo e faria com que seu teste de unidade o lesse desse arquivo.
Outras dicas
eu usei Unidade Xml no passado e achei que era útil.
Ele pode ser usado para validar XML em relação a um esquema ou comparar seu XML em relação a uma string.É inteligente o suficiente para entender as regras de análise do XML.Por exemplo, ele sabe que "<e1/>" é equivalente a "<e1></e1>" e pode ser configurado para ignorar ou incluir espaços em branco.
Usar um DTD no teste unitário para testar sua validade é uma coisa, testar o conteúdo correto é outra.
Você pode usar o DTD para verificar a validade do xml gerado, que eu simplesmente leria da mesma forma que você faz no seu programa.Eu pessoalmente não o incluiria in-line (como uma String);sempre há uma dependência entre o código do seu aplicativo e o teste de unidade.Quando o xml gerado for alterado, o DTD também será alterado.
Para testar o conteúdo correto, eu escolheria Unidade XML.
Afirmando xml usando XMLUnit:
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreDiffBetweenTextAndCDATA(true);
Diff diff = new Diff(expectedDocument, obtainedDocument);
XMLAssert.assertXMLIdentical("xml invalid", diff, true);
Uma coisa que você pode encontrar é o fato de que o xml gerado pode conter identificadores variáveis (atributos id/uid ou similares).Isso pode ser resolvido usando um DiferençaListener ao declarar o xml gerado.
Exemplo de implementação de tal 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);