Mac OS X で maven の出力が文字化けする

JUnit4 の Parametrized を Groovy で使う

概略

現在こっそり開発しているツールのテストに Groovy を使用しています. テスト対象は Java なのですが, テストには柔軟に書ける Groovy が便利です.

プロジェクト自体は Maven3 で管理していて, ビルド, テスト, パッケージングを全て pom.xml で設定しています. そこのちょっとした設定の間違いで数時間ハマってしまったので, 記録として残しておきます.

Groovy テストスクリプト

JUnit4 ではパラメータ化されたテストを実行することができます.

クラスに org.junit.runner.RunWith アノテーション, パラメータを供給するメソッドに org.junit.runners.Parameterized.Parameters アノテーションを付けると, そのクラスはパラメータ化されたテストを実行できるようになります.

詳しいことは http://groovy.codehaus.org/Using+JUnit+4+with+Groovy あたりを見てください.

pom.xml

pom をそのまま書くのが面倒なので,

<aaa>
  <bbb>
    <ccc>value</ccc>
  </bbb>
</aaa>

というのを

aaa
`-bbb
    `-ccc=value

と書くことにします.

プロジェクトの build 要素以下はこのようになっています.

build
`-plugins
  `-plugin
    `-groupId=org.codehaus.gmaven
    `-artifactId=gmaven-plugin
    `-version=1.4
    `-configuration
    | `-providerSelection=1.8
    `-executions
    | `-execution
    |   `-goals
    |     `-goal=generateStubs
    |     `-goal=compile
    |     `-goal=generateTestStubs
    |     `-goal=testCompile
    `-dependencies
      `-dependency
        `-groupId=org.codehaus.groovy
        `-artifactId=groovy-all
        `-version=1.8

この pom で mvn clean test を実行すると以下のようなエラーが出ました.

シンボルを見つけられません。
シンボル: クラス Parameterized$Parameters
場所    : org.junit.runners の パッケージ

Groovy で書いたテストスクリプトが Java クラスに変換され, さらに javac でコンパイルされます. その段階で上のエラーが出ています.

確かに Groovy から変換された Java ソースを見ると @Parameter アノテーションが @org.junit.runners.Parametrized$Parameter に変換されてしまっています. Java ソースとしては $ ではなく . が正しいはずなのでコンパイルエラーが出た理由が分かりました.

しかし, いくらググってもこの Groovy スクリプトのマズいところが見付かりません.

ふと思い立って goal=generateTestStubs の部分を消してみました. 「変な Java ソースを生成するくらいなら, そこを消してしまえ」と, 思い立ったというよりヤケクソでというのが正しい表現な気もします. すると無事テストが実行されました.

なぜかと考えてみると, そもそも generateTestStubs で生成された Java ソースは, メソッドの本体が return null のような意味の無いクラスでまさにスタブでした. なぜこのようなクラスが必要になるのかと言うと, おそらく Java 側からこの Groovy スクリプトを呼び出すコードをコンパイルするためのクラスなのでしょう. 今回, そのような Java クラスは無いので実はこのゴールは不要なのでした.

まとめ

ということで答えは「余計なゴールがあったために, 変な Java ソースをコンパイルしなくてはならなくなり, そこでエラーが起きていた」ということでした.

う〜ん, 我ながら嫌なハマり方をしましたが, 解決できたときはスッキリしました.

そして教訓は「ツールについてきちんと理解しよう」ということでした. maven は便利なツールですが, まだ自分にとって複雑なツールです. まだまだ勉強しないとですね.

それでは.

playing with maven (1)

最近, 仕事で maven を使うことが多くなり, 自分でも色々触ってみたかったのでいじってみました.

(まだ雛形しか作ってませんが)

環境

maven のバージョンなどは以下の感じです. (まだ Lion にしてなかったや ^^;)

$ mvn --version
Apache Maven 3.0.3 (r1075438; 2011-03-01 02:31:09+0900)
Maven home: /usr/share/maven
Java version: 1.6.0_26, vendor: Apple Inc.
Java home: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
Default locale: en_US, platform encoding: MacRoman
OS name: "mac os x", version: "10.6.8", arch: "x86_64", family: "mac"

maven plugin

せっかくなので maven plugin の作り方も勉強します.

http://www.slideshare.net/guestd4898b/maven2

ここに素晴しいスライド資料を見付けたので, これに沿って plugin プロジェクトを作成. maven のバージョンが 2 と 3 で違っていますが, そんなに大きな違いは無いようです. (maven の 1 と 2 では大違い, という話は伝え聞いていました.)

$ mvn archetype:create -DpackageName=net.elliptium.maven.plugins.sample -DgroupId=net.elliptium.maven.plugins -DartifactId=maven-sample-plugin -DarchetypeArtifactId=maven-archetype-mojo
$ cd maven-sample-plugin
$ mvn install

でプロジェクトを作成し, ローカルレポジトリに install します.

最初のプロジェクト作成のコマンドは少し長いですが, スライドの17枚目を見ていただくと理解できるかと思います.

packageName は Java の慣習に従って, このブログでも使っている私有のドメイン名を引っ繰り返したものの下にくるものを付けました. groupId も他人のものと区別できるように, 似た感じに付けました.

maven の素晴しいところは最初に雛形となるプロジェクトが作成され, 最低限の内容が記述されたソースコードと設定ファイルが出来上がるところです. Rails から始まった流儀なのかなぁ? となんとなく思っていますが, その思想は現在は Sphinx や PlayFramework など, 言語や分野の壁を越えて広まっています.

最初の一歩を踏み出す人には, 実際に動くサンプルソースから始めて, 少しずつそれを改造しながら進むのが一番と考えています. なので, この maven の思想には強く共感を覚えます.

さて, プロジェクトを作ったら, プロジェクトのディレクトリに入り最初のコンパイルをしましょう.

maven には build lifecycle という概念があって, 開発→コンパイル→テスト→出荷のような一連の開発の流れを管理しています. それぞれの1ステップのことを phase と呼ぶそうです.

http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Build_Lifecycle_Basics

今回は install までやってしまうので, .class ファイルへのコンパイルをし, jar に固め, ローカルレポジトリに入れるところまで行います.

$ ls target/
maven-sample-plugin-1.0-SNAPSHOT.jar
$ ls ~/.m2/repository/net/elliptium/maven/plugins/maven-sample-plugin/1.0-SNAPSHOT/
maven-sample-plugin-1.0-SNAPSHOT.jar

plugin プロジェクトのディレクトリに居るものとして, 成果物の出力先である target ディレクトリの中を見ると .jar ファイルが出来上がっています. また maven のローカルリポジトリにも同じ .jar がコピーされています.

package するだけでなく install まで行なうと, 他のプロジェクトからもこの .jar ファイルが使えるようになり, plugin を使用することができます.

maven project

さて, 次はこの maven plugin を使う Java プロジェクトを作成しましょう. ここでも maven を使うことができます.

$ mvn archetype:generate -DgroupId=net.elliptium.java.sample -DartifactId=sample
$ cd sample
$ emacs pom.xml
// なんらかの方法で pom.xml を編集
$ cat pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http ...

Licenses