Personal tools
You are here: Home Maven Notes Mojo and EoT
Document Actions

Mojo and EoT

by MIYACHI Yasuhiko last modified 2006-06-22 16:12

 Mojoは、Maven2のPlugin Frameworkであり、Maven1のJelly(と比較して、開発効率、特に、EoT(Ease of Testing: テスト容易性)が良い。

Maven2

 説明省略

Jelly

  • Jellyは、Maven1のPlugin 用スクリプトであり、XML形式である。
    Maven Project自身も、この選択は失敗だったと感じているようでMaven2ではあっさり捨てられた...
  • 悪い所
    • インタプリタである。
    • XML形式であり、記述性が悪い。(# スクリプト自体をXMLにするなんて...)
    • 継承が利用できない。
    • Unit Testが困難。

Mojo

  • Mojoは、Maven2のPlugin Frameworkであり、POJO(Plain Old Jav Object)である。
  • Mojoは、アフリカ系米国人社会のスラング( 調べてみよう!)
  • 良い所
    • POJOだ。
    • 使い慣れたJavaだ。
    • 既存のMojoからの継承ができる。
    • 既存のJava Libraryをバンバン活用できる
    • POJOであり、Unit Testが楽

Mojoの作り方

初めは、archetype:create

$ mvn archetype:create -DgroupId=example -DartifactId=plugin01 -DarchetypeArtifactId=maven-archetype-mojo
...

いきなり、install

$ mvn install
...

そのまま、goal

$ mvn example:plugin01:1.0-SNAPSHOT:touch <- ここに注目
[INFO] Scanning for projects...
[INFO]----------------------------------------------------------------------------
[INFO] Building Maven Mojo Archetype
[INFO] task-segment: [example:plugin01:1.0-SNAPSHOT:touch]
[INFO]----------------------------------------------------------------------------
[INFO] [01:touch] <- ここに注目
[INFO]----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO]----------------------------------------------------------------------------
[INFO] Total time: < 1 second
[INFO] Finished at: Thu Mar 02 11:39:14 JST 2006
[INFO] Final Memory: 1M/3M
[INFO]----------------------------------------------------------------------------
$

何がおこったか

  これは、archetype:createで作成されたSample Plugin(MyMojo.java)をcompile、Install(Local Repogitoryに)して、実行したためである。

src/main/java/example/MyMojo.java

package example;
...
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
* Goal which touches a timestamp file.
*
* @goal touch <- ここに注目
*
* @phase process-sources
*/
public class MyMojo
extends AbstractMojo <- ここに注目
{
/**
* Location of the file.
* @parameter expression="${project.build.directory}"
* @required
*/
private File outputDirectory;

public void execute() <- ここに注目
throws MojoExecutionException
{
File f = outputDirectory;

if ( !f.exists() )
{
f.mkdirs();
}

File touch = new File( f, "touch.txt" );
FileWriter w = null;
try
{
w = new FileWriter( touch );
w.write( "touch.txt" );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Error creating file " + touch, e );
}
finally
{
if ( w != null )
{
try
{
w.close();
}
catch ( IOException e )
{
// ignore
}
}
}
}
}

 このように、Maven2のMojoは、Maven1のJellyと比較して、開発、Install、実行が容易なことが理解できたと思う。
 Mojoの開発時にこのような作業を繰り返せば、誰でも、Mojoを開発することができる。
などと、思っていたら、ちゃんちゃら、間違い!

 MojoのEoTは、もっとスマートなのである!!

Log出力をさせる

 実行経過をLog出力させたいのは、だれでも思うことである。
 Mojoでは、以下の方法で、Log出力させる。

src/main/java/example/MyMojo.java(抜粋)

    public void execute()
throws MojoExecutionException
{
getLog().info("outputDirectory: " + outputDirectory); <- ここに注目
...
}

 実行結果は、

$ mvn example:plugin01:1.0-SNAPSHOT:touch
...
[INFO] [01:touch]
[INFO] outputDirectory: foobar <- ここに注目
[INFO] BUILD SUCCESSFUL
...
$

 通常は、Info Levelまでしか出力しない。
 Debug Levelまで出力させる場合は、実行時に-X(--debug) optionを付ける。
 しかし、実際は、他のModuleのDebug 情報まで出力されて、かえって見にくいのでお奨めしない。

Unit Testの方法

 Mojo(Maven Java Object)は、POJO(Plain Old Java Object)だから、Unit Testが簡単にできる。

Setter methodを書く

 MyMojo.javaには、private変数のoutputDirectoryにアクセスするsetter methodが無いので書く。
 Mavenの実行時には、Maven自体が今はやりのDI(Dependency Injection: 依存性注入)のしくみを使って、private 変数にアクセスするが、Test時にはその機能は使えない。
# Testのためだけに、publicなsetter methodを書くのは、設計の原則に反すると思うのは、私だけ?

src/main/java/example/MyMojo.java(抜粋)

public class MyMojo
    extends AbstractMojo
{
...
    private File outputDirectory;

// ここから
    public void setOutputDirectory(File outputDirectory)
    {
        this.outputDirectory = outputDirectory;
    }
// ここまで
...
}

Unit Testを書く

 Unit Test用のDirectoryは作られないので、自分で掘る。

$ mkdir -p src/test/java/example
...

 src/test/java/example/MyMojoTest/java

package example;

import java.io.File;

import junit.framework.TestCase;

import org.apache.maven.plugin.MojoExecutionException;

public class MyMojoTest
extends TestCase
{
public void testMyMojo()
{
try
{
File outputDirectory = new File("/tmp");

MyMojo mojo = new MyMojo();
mojo.setOutputDirectory(outputDirectory);
mojo.execute();

File f = new File(outputDirectory, "touch.txt");

assertTrue(f.isFile());
}
catch(MojoExecutionException e)
{
e.printStackTrace();
}
}
}

 まったく普通のPOJOのUnit Testのように書ける!!

Unit Testする

$ mvn test <- ここに注目
[INFO] Scanning for projects...
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
[info] outputDirectory: /tmp <- ここに注目
[surefire] Running example.MyMojoTest
[surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec

Results :
[surefire] Tests run: 1, Failures: 0, Errors: 0

[INFO] ----------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ----------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Thu Mar 02 17:02:54 JST 2006
[INFO] Final Memory: 4M/8M
[INFO] ----------------------------------------------------------------------------
$

 このようにMojoは、簡単にテストできる。
 しかも、getLog().info()の結果まで、ちゃんと表示される

  Mojo最高!!


Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: