JavaプロジェクトでのXMLデータの検証

こんにちは、%ユーザー名%。

多くのプロジェクトで、テストでXMLデータを比較する必要がありました。

実際、モジュールの結果はXMLデータになります。 その場合、 TDDの原則に従って、それらの生成方法を確認する必要があります。 私は、開発時にそれらに固執するようにします。

私の意見では、コード内でXMLの生成をテストするための最良の方法について話をしようと思います。 XML比較ツールとして、 XmlUnitを使用しました


テストでXMLデータを迅速かつ便利に比較する必要があります。 私は車輪を再発明したくなかったので、これらの目的のために最も人気のあるライブラリを選びました。 最初に、解決した問題のリストを説明しようとします。

それがすべて始まった方法


どういうわけか、次のプロジェクトに取り組んでいる間に、同僚のテストを破りました。 テストの勉強を始めたとき、次のようなことがわかりました。
@Test public void testSomeXmlGeneration() { //      String result = someModule.generateXML(); //     XML  File file = File.createTempFile("actial_data", ".xml"); FileWriter fileWriter = new FileWriter(file); fileWriter.write(result); fileWriter.close(); File fileExpect = new File(this.getClass().getResource("/expected_data.xml").getFile()); FileAssert.assertBinaryEquals(fileExpect, file); } 


ここで、データが生成され、リソースの元のデータと比較されます。 テストには、 JUnit4が使用されます。 また、理想的には、元のファイルは開発者が手動で作成する必要があることに注意してください。

このコードが悪いのはなぜですか?

ポイントを正当化しようとします。

1. 2つのファイルを比較するにはジェスチャが多すぎます



実際、多くの動きがあり、頻繁に比較する必要がある場合、何らかの形でこのコードが前後にコピーされ、実際に頻繁に発生します。 これに関係するのは時間の不足です。

2.生成されたXMLコードの検証はありません



有効性がチェックされなかったという事実により、別のモジュールは無効なデータの処理を拒否しましたが、テストではすべてが正常でした。 テストをデバッグする段階でこの問題を解決したかったのです。

3.タグまたは属性の順序が異なるため、同一のXML構造とデータは同じではない場合があります。



たとえば、次のように:
オプション1タグを並べ替える
 <?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project> 

 <?xml version="1.0" encoding="UTF-8"?> <project> <description>desc</description> <name>some project</name> </project> 


または:
オプション2属性の順序を変更する
 <?xml version="1.0" encoding="UTF-8"?> <project name=”some projectdescription=”desc”/> 

 <?xml version="1.0" encoding="UTF-8"?> <project description=”desc” name=”some project”/> 



4. XMLフォーマットテストが必要



記事の冒頭に示したテストでは、XMLデータはスペースや改行なしで表示されました。 違いを感じてください:
オプション3スペースと改行を削除する
 <?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project> 

 <?xml version="1.0" encoding="UTF-8"?> <project><description>desc</description><name>some project</name></project> 



5.データ内の自動処理された転送



オプション3データ内の行を折り返す
 <?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project> 

 <?xml version="1.0" encoding="UTF-8"?> <project> <name> some project </name> <description>desc</description> </project> 



記事の冒頭で検討したテストでは、ソースデータは1行で、タグと属性のみがわずかに大きくなりました。 そこにエラーを置くことは非常に簡単で、テストがパスするように修正するのは長くて苦痛です。

上記のすべての問題は、座標を修正することにしました。


短い検索の後、私の選択はXmlUnitに落ちました。

基本的なXmlUnit接続メソッド



XmlUnitライブラリは、主にJUnit3の拡張です。
その基盤は、JUnit3のTestCaseクラスの子孫であるXMLTestCaseクラスです。 ここでは、クラスの使用の主な例を見ることができます。
実際には、XmlUnitは他のテストライブラリで簡単に使用できます。 これにはDiffクラスがあります。

さあ行こう


私のプロジェクトでは、mavenを使用します。 XmlUnitをMavenの依存関係として接続します。 これを行うには、pom.xmlを開き、依存関係に新しい依存関係を追加します。
 <dependencies> <!-- ….-  ... --> <dependency> <groupId>xmlunit</groupId> <artifactId>xmlunit</artifactId> <version>1.3</version> </dependency> </dependencies> 


テストを開き、そこに新しい比較を記述します

 @Test public void testSomeXmlGeneration() { //      String result = someModule.generateXML(); Diff diff = new Diff(getResourceAsString("/expeced_data.xml"), result); assertTrue("XML   ", diff.similar()); } 


テストを実行します...そして動作しません。 インターネットでもう少し検索した後、解決策を見つけました。 タグ間のスペースの問題でした。 それらを無視するには、プリセットを追加する必要があります。

 @Before public void setUp() throws Exception { XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreWhitespace(true); } 


すべてのようで、結果を楽しむことができます。 ただし、XMLでエラーが発生したとします。 次に、どのタグが問題であるかを知る必要があります。
次の例は、解決に役立ちます。

 //    class TestXmls { @Before public void setUp() throws Exception { XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreWhitespace(true); } @Test public void testSomeXmlGeneration() { //      String result = someModule.generateXML(); Diff diff = new Diff(getResourceAsString("/expeced_data.xml"), result); Tools.showXmlDiff(diff); assertTrue("XML   ", diff.similar()); } } //    public final class Tools { public static void showXmlDiff(Diff diff) { DetailedDiff detDiff = new DetailedDiff(diff); List differences = detDiff.getAllDifferences(); for (Object object : differences) { Difference difference = (Difference) object; System.out.println("***********************"); System.out.println(difference); System.out.println("***********************"); } } } 


showXmlDiffメソッドに注意してください。 その中で、差異のリストを取得して表示します。

他に何ができますか?





文学



情報を得たリンク。



UPD: Lure_of_Chaosとの議論の後に、別のリンクを参照リスト追加しました。 そこでは、何らかの理由で公式ドキュメントには書かれていないXML検証やその他の美しい機能について読むことができます。

繰り返しになりますが、XmlUnitを使用すると、 DTDおよびXSDスキームに対してXMLの有効性を確認できます。
Lure_of_Chaosが正しく指摘しているように、XSDスキームでは、 要素が 定義される 順序を要求できます。 テストでこれをテストすることは重要です。

UPD2検証 最後の例を 修正しました 。 ありがとう、 コルウィン
それだけです、ご清聴ありがとうございました。

Source: https://habr.com/ru/post/J127473/


All Articles