miau's blog?

Maven2 でハマったところいくつか

Maven2 を使ってることはどこかで書きましたが、いくつかどうでもいいところでハマったりしたのでその話でも。




■Cobertura のレポートがおかしい

テストカバレッジを cobertura-maven-plugin で出すようにしてます。

Cobertura Maven Plugin - Introduction

こんな感じ でレポートが出せるようになって、「まだ真っ赤だなー。ちゃんとテスト書かないとなー」とか思ってたんですが・・・よく見るとちゃんと集計されてなかったようで、全体で 2 行しかカバーしてないことになってる。

これについてはいろいろ調査してまして。

・テストには djUnit を使ってて(これは別項でまた書こうかと書きました)、Cobertura とどちらも ASM を利用してるから何か競合とかしてるのかな?→ちゃんと調べるには surefire の仕組み調べないとダメかな?
・カバレッジに含まれている 2 行が interceptor まわりだから aopalliance と Cobertura の組み合わせが悪いのかな?

というように結構ごそごそやってたんですが、全然見当違いだったようで。

今回 DB アクセスには S2Dao を使ってて、一部外部 SQL を使ってるんですが・・・テスト時にこの .sql がないと unit test が通らないのでわけもわからずに

<testResources>
:
<testResource>
<directory>src/main/java</directory>
</testResource>
</testResources>

こんなことをやっていたのが原因。target/test-classses に .java ファイルがあったせいで動いてなかったようで。

<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.sql</include>
</includes>
</resource>
</resources>

みたいに resources に移動することで解決。ついでに .sql だけコピーするように指定。(こうしないと .war に .java が含まれてかっこ悪いので。)

■mvn clean 重要

今回は Continuum で CI もやってます。一時間に一度ビルド&unit test を実行して、コンパイルエラーやテストの NG があればメールが飛んでくる仕組みです。

ある日こんなエラーが。
;
junit.framework.AssertionFailedError
junit.framework.AssertionFailedError: 1:TableName=SYN_M_XXXXXXX[1:TableName=SYN_M_XXXXXXX:Row=0:columnName=XXXXXXX_DATE expected:<2009-11-04 00:00:00.0> but was:<2009-11-04 00:00:00.0>, 1:TableName=SYN_M_XXXXXXX:Row=0:columnName=VALID_LIMIT_DATE expected:<2008-12-11 00:00:00.0> but was:<2008-12-11 00:00:00.0>]
at junit.framework.Assert.fail(Assert.java:47)
at org.seasar.extension.unit.S2TestCase.assertEquals(S2TestCase.java:273)
at org.seasar.extension.unit.S2TestCase.assertEquals(S2TestCase.java:239)
at org.seasar.extension.unit.S2TestCase.assertBeanListEquals(S2TestCase.java:331)
at org.seasar.extension.unit.S2TestCase.assertEquals(S2TestCase.java:294)
:

「expected:<2009-11-04 00:00:00.0> but was:<2009-11-04 00:00:00.0>」って期待どおりなのになんで NG になってるの?

担当のひとが Eclipse で unit test 動かすと、ちゃんと OK になるとのこと。その人が「Date と Timestamp で比較やってるせいですかね?」みたいなことを言ってたので見てみると、

・expected: java.sql.Timestamp(extends java.util.Date)
・actual: java.sql.Date

だそうで。S2TestCase のソース(今回は S2DAO 使ってるので)とか見てみると、

expected.equals(actual)

みたいな感じで比較しているところがある。Timestamp と Date の比較って false になるもんなの?と調べてみると・・・

裏表(Phinloda のもう裏だか表だか分からないページ) | compare java.util.Date with java.sql.Timestamp

Date#equals(Timestamp) は true になるけど Timestamp#equals(Date) は false になるそうな。

java.sql.Date vs java.sql.Timestamp | mattfleming.com

型の継承でなく実装の継承にしてるのが問題だと。

・・・まあそれはわかったんだけど、だったらなんで Eclipse ではテスト OK になるんだろ?

とりあえず Timestamp と Date の比較がうまくできるように改造できないかな?とソースをもっと丁寧に追ってみると・・・実は S2 のどこかでこの辺はちゃんと実装されてたり。Date を渡しても結局 Timestamp に変換して比較しているような感じ。今度は mvn のほうで動かないのが謎になってきた。

よくわからないながらもしばらく S2 まわりのソースを眺めてたら cache という文字が目に入ってきて。もしかして何か情報がキャッシュされちゃってる?ということで mvn clean を実行すると・・・あっさりテスト OK に。どこかでクラスの型を TimeStamp から Date に変更してたんだけど、型情報のキャッシュが残っていたせいで Date から Timestamp への型変換がスキップされていたとかかな、たぶん。

そんなこんなで 5 時間くらい調査に要してしまった。mvn clean を外してたのは target 配下のファイルにロックがかかってると clean に失敗して鬱陶しかったからなんだけど、必ず mvn clean は流すようにしよう・・・。よく見たら failOnError なんてパラメータもあるし。

Maven Clean Plugin - maven-clean-plugin - clean:clean

■scope 指定重要

Tomcat へのデプロイは cargo-maven2-plugin を使ってます。

Cargo - Maven2 plugin

でもデプロイした環境にブラウザでアクセスするとエラーになったりとか。

org.apache.jasper.JasperException: JSPのクラスをコンパイルできません:

JSPファイル: /login.jsp の中の33行目でエラーが発生しました
The method setPageContext(PageContext) is undefined for the type XxxXxxxxxxxx

どうも jsp-api の .jar ファイルが競合しているのが原因のようで。jsp-api の scope に provided を指定したら解決。この辺は

構成管理 実践入門 第4章 Maven2によるビルド入門 さらに開発を進めよう

にもきっちり書いてあって、servlet-api はちゃんと指定してたんだけど・・・jsp-api は抜けてたっぽい。

posted at 18:25:20 on 2008-12-06 by miau - Category: Java No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

No comments yet

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。