jOpenDocumentを2021年にリブートしてみる その2: テストを動かす
前回の記事
のつづき。今回は目標が低くてテストを動かすところまで。 これが全然苦戦して、ほとんど進捗がないんですねえこれが。
テストの位置をMaven標準に動かす
その前に前の記事の落穂ひろいですが、
To compile you need to put iText ( http://www.lowagie.com/iText/download.html ) and junit4 ( http://www.junit.org/ ) into the lib/ dir.
って書いてあるので、iText と Junit4 が必要ですね。ということで pom.xml
に次の二つを追加しておいてました。
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> </dependency>
(なんで最初からlib
ディレクトリに入ってないんでしょ、再配布制限的な何かあるのかな)
それとこれも前回からの書き漏れですが、
src/product.properties
を参照できなくてコケるので src/main/resources
に移動しておきました。
ここまでは前回の落穂ひろい。
で、ここからが今回の本題ですが、junit4が必要だよと言ってるってことは当然テストコードがあるわけで、
Maven的には src/test/java
以下にソースがないとたぶんだめですよね。
まあこれはきっと @Test
アノテーションがあるファイルはテストコードだと見極めをつけて移動しました。
$ grep -rl "@Test" src/main/java/org/jopendocument/dom/ODSingleXMLDocumentTest.java src/main/java/org/jopendocument/dom/OOXMLTest.java src/main/java/org/jopendocument/util/cache/ICacheTest.java
こいつらをまるっと test に(同名のフォルダを掘って)移動。 すると Intellij IDEA上でテストコードが実行できるようになりました。やった!
で、まあテストはrunできるようになったんですが結果を見ると真っ赤っ赤。 あとはぼちぼちこれを直していけばよかろうと。
リソースの移動
まずはテストコードの中で指定されてる .odt
がないとテストコード内でファイルが読めないので移動します。これは簡単。
diff見るとこんな感じですね。
diff --git a/src/main/java/org/jopendocument/dom/empty.odt b/src/test/resources/org/jopendocument/dom/empty.odt similarity index 100% rename from src/main/java/org/jopendocument/dom/empty.odt rename to src/test/resources/org/jopendocument/dom/empty.odt diff --git a/src/main/java/org/jopendocument/dom/styles.odt b/src/test/resources/org/jopendocument/dom/styles.odt similarity index 100% rename from src/main/java/org/jopendocument/dom/styles.odt rename to src/test/resources/org/jopendocument/dom/styles.odt diff --git a/src/main/java/org/jopendocument/dom/test.odt b/src/test/resources/org/jopendocument/dom/test.odt similarity index 100% rename from src/main/java/org/jopendocument/dom/test.odt rename to src/test/resources/org/jopendocument/dom/test.odt
で、よく見ると、普通に src/main/java
にもいかにもリソースなファイルがあるので移動しとかないとですね。
具体的には src/main/java/org/jopendocument/dom/oofficeDTDs/
にあるやつを丸っと src/main/resources/
以下に移動します。
ほかにも getResource(AsStream)()
で参照されてるファイルを探してはリソースに放り込む日々。
XML関係のテストがそもそも動いてない
これで結構テスト通るようになってきたんですが、問題は、XML関係のテストでスキーマによるバリデーションを試みてるところで落ちてる。 具体的には
private Schema createSchema(final String name) throws SAXException { return SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI).newSchema(getClass().getResource("/oofficeDTDs/" + name)); }
こんなコードが、
Caused by: java.util.ServiceConfigurationError: javax.xml.validation.SchemaFactory: org.iso_relax.verifier.jaxp.validation.RELAXNGSchemaFactoryImpl Unable to get public no-arg constructor
こういう例外を吐いて落ちるんですな。
なぬ?スキーマに対する適切なコンストラクタがない? いやいや、XMLConstants.RELAXNG_NS_URI
はJava標準なんだからそんなわけないだろう……と、Java力(ちから)がないわたくしは考えておりました。
しかし色々調べると「java.xml.validation
のデフォルトの実装に含むべきなのはW3Cなソレだけで、それ以外のスキーマを利用したい場合は自分で何とかしなさい」ってことらしいじゃーないですか。おうふ。なるほど……。ここでしばらく停滞、袋小路にハマってました*1。
でもよく見るとREADMEにこんな記述がありました。
To validate XML (needed for JUnit tests) you need to download http://java.net/downloads/msv/releases/msv.20090415.zip and put msv.jar, relaxngDatatype.jar, xsdlib.jar and isorelax.jar in the classpath.
いや、だったらなんで最初から入れといてくれないの……というのはともかく、これらをMavenの依存関係に足せばよいのですね。足しましょう。足しました。
<dependency> <groupId>msv</groupId> <artifactId>msv</artifactId> <version>20050913</version> </dependency> <dependency> <groupId>msv</groupId> <artifactId>relaxngDatatype</artifactId> <version>20050913</version> </dependency> <dependency> <groupId>msv</groupId> <artifactId>xsdlib</artifactId> <version>20050913</version> </dependency> <dependency> <groupId>msv</groupId> <artifactId>isorelax</artifactId> <version>20050913</version> </dependency>
これで行けるだろ!と思ったんですが、いざValidationをしようとするとコケるのです……しくしく。
@Override public Validator getValidator(final Document doc, final boolean ignoreForeign) { final Schema schema; try { if (doc.getRootElement().getQualifiedName().equals("manifest:manifest")) schema = this.getManifestSchema(); else schema = this.getSchema(); } catch (SAXException e) { throw new IllegalStateException("relaxNG schemas pb", e); } return schema == null ? null : new Validator.JAXPValidator(doc, ignoreForeign ? UNKNOWN_PRED : null, schema); }
こういうコードで、 this.getSchema()
したところで
Caused by: org.xml.sax.SAXParseException; systemId: file:/C:/Users/naruhiko/gosrc/src/github.com/naruoga/jOpenDocument/target/classes/oofficeDTDs/OpenDocument-schema-v1.1.rng; lineNumber: 123; columnNumber: 36; 同名のパターンが既に定義されています。combine属性を使って結合するか、パターン名を"office-meta-content"以外のものに変更してください
って例外が出ちゃうのです(しかし上のコードの "relaxNG schemas pb" ってどういう意味なんだろう。pbってスイスの工具屋さんじゃないよね)。
うーん。わからん。言葉通りだとすると元のスキーマに問題があるっぽく読めるけどスキーマは何にも変えてないしなあ(当たり前)。
office-meta-content
でgrepしてみると
grep -r "\"office-meta-content\"" src/main/resources/oofficeDTDs/OpenDocument-schema-v1.1.rng: <ref name="office-meta-content"/> src/main/resources/oofficeDTDs/OpenDocument-schema-v1.1.rng:<define name="office-meta-content"> src/main/resources/oofficeDTDs/OpenDocument-strict-schema-v1.1.rng: <define name="office-meta-content">
となってるのは確かにそうなんだけど、これがいいのか悪いのか……何も変えてないので悪いってことはないと思うし、そもそもスキーマなんだから標準から引っ張ってきてると思うんで、なにがなんやらさっぱりです。
わからないので後回しにして*2落ちてるほかのテストを調べることにします。次回へ続く。