@Ruleは素晴らし。

@Rule。このアノテーションは、あまり知られていないようですが、ヤバいです。このアノテーションが追加されたのは4.7からなので結構古いのです。@Ruleのうれしさは、カスタムで作られているRunnerをほぼ置き換えられる、ということを言われていました。ただ、僕はあんまり使った事がなかったですし、周りでも使っている話はあまり聞いた事がありません。でも、使ってみて非常に便利だと感じました。
例えばTemporaryFolderを利用して作成されたファイルは、テストの終了時に自動的に削除されます。ちなみにTemporaryFolderの使い方はこんな感じです。

public static class HasTempFolder {
        @Rule
        public TemporaryFolder folder= new TemporaryFolder();
 
        @Test
        public void testUsingTempFolder() throws IOException {
                File createdFile= folder.newFile("myfile.txt");
                File createdFolder= folder.newFolder("subfolder");
                // ...
        }
 }

... この例はJUnitJavadocからお借りしました:-P 要するにfolderから作ったcreatedFileやcreatedFolderはtestUsingTempFolderのテストメソッドが終了すると削除されます。テストケース毎に新しいファイル、フォルダが作られる事が保証される訳です。
で、この@Ruleですが、一つのクラスで一つだけ、という事はありません。JUnitにある@Ruleは他にTestWatchmanやTimeoutなどがあります。どれもそのテストクラス全体を通じて必要な、横断した前処理、後処理をルールとして宣言できるのです。(Runnerと比べたらRuleの方が良い名前だと思いませんか?)
@Ruleの追加も簡単です。こうしたメソッド毎の前処理や後処理を追加するルールであれば、MethodRuleを継承して実装します。MethodRuleのインタフェースを見てみると、次のメソッドが一つ定義されています。

Statement apply(Statement base,
                FrameworkMethod method,
                Object target)

第1引数のbaseは、テストメソッドが担う一連の処理を持ったインスタンスです。evaluate()を呼び出すと、テストメソッドが評価されます。第2引数のmethodはテストメソッドのモデルです。そのメソッドの名前やアノテーションを取得できます。第3引数はテストのインスタンスそのものです。
さて、返り値のStatementですが、Ruleの中で生成しても良いですし、baseをそのまま返してもいいです。ほとんどの場合、Ruleの中で生成する形式をとります。Ruleの中で生成すると、テストケース前後に処理を追加する事ができます。例えば、TestWatchmanという、テスト実行中の状況をログに出力するなどの処理を行うためのルールクラスのapplyの実装は次のようになっています。

  public Statement apply(final Statement base, final FrameworkMethod method,
          Object target) {
      return new Statement() {
          @Override
          public void evaluate() throws Throwable {
              starting(method);
              try {
                  base.evaluate();
                  succeeded(method);
              } catch (Throwable t) {
                  failed(t, method);
                  throw t;
              } finally {
                  finished(method);
              }
          }
      };
  }

starting()やsucceded()をオーバーライドする子クラスを実装する事で、テストメソッドの実施状況を知るためのルールを書く事ができるのです。
ではbaseをそのまま返す場合はどんな場合かというと、そのテストケースの実行自体を判断するようなルールで使えるでしょう。例えば実行しているOSにより、テストを実行するかどうか判断するようなケースです。*1
これまでカスタムでRunnerを作成するのは、テストの前処理や後処理を追加するために書かれる事が多かったと思われます。また、親のテストクラスを作って、それを継承するようなテストクラス設計をする方もいるでしょう。しかし@Ruleの追加により、もっと汎用的に、しかも複数の処理を割り込ます事ができます。っすごいっす。

*1:残念ながら、実行結果をIgnoreにするルールは作れないですが

Xvncプラグインを使ってみた。

GUIのテストを含む場合、Linux環境だとXが必要だったり、Windowsだと権限のあるセッションが必要だったりする訳です。Linuxでは別のセッションを立ち上げて環境変数DISPLAYに設定して・・・みたいな事をすればできそうだったのですが、設定せど設定せどうまくいかず。なのであきらめていたんですが、いつの間にかHudsonにはXvncと連携するプラグインができていたので、利用してみました。Hudsonが動作している環境はUbuntu Linux 8.04です。LTS期限切れなので、もうセキュリティパッチが提供されないらしいので、近々いれかえようか。

インストールしておくもの

vncserverにはvnc4serverを使いました。tightvncserverというものもあるのですが、vnc4serverの方が情報が多かったのでそちらを選択しました。

$ sudo aptitude install vnc4server
$ sudo aptitude install imagemagick

これだけです。下記のコマンドを打って、インストールできている事を確認しましょう。

$ which vncserver
$ which import

続いてHudson環境のセットアップをば

Xvncプラグインをインストールします。XvncプラグインはHudsonのプラグインマネージャからダウンロードできます。今日インストールしたのは下記のプラグインです。

パスワードファイルを作成しよう

インストール後、まずはHudsonの管理画面で設定を行う前に、勝手にvnc画面にログインできないよう、パスワードファイルを作成する必要があります。下記のコマンドを打ってパスワードファイルを作成してください。

$ vncpasswd /path/to/password.file

Xvncプラグインの設定をしよう

Hudsonの管理画面を開くと下記の項目が増えています。こんな感じに設定してください。

写真のコマンドは下記のとおり

vncserver :$DISPLAY_NUMBER -geometry 1024x768 -PasswordFile /path/to/password.file

ジョブにXvncの設定をしよう

Xを利用したいジョブに下記の設定をしましょう。

終了後にスクリーンショットを撮る必要がなければ、imagemagickのインストールは不要だと思われます。

と言う事でenjoy continuous testing!

Quick JUnitの次期リリース版(0.6.0)の機能まとめ

Quick JUnitの0.6.0を近くリリースする予定です。どんな機能なのか、ここで簡単に紹介したいと思います。EclipseでいうNew and Noteworthyです。リリース候補版を http://quick-junit.sourceforge.jp/updates/beta/ で公開しています。リリース候補版ですが、特に問題なければこのまま正式版として配布する予定です。

Quick JUnitのアイコン

まず大事な事から。このはてダで投票して頂いていたQuick JUnitのアイコンについてです。

このアイコンは@さんが描かれたアイコンです。@さんのアイコンをベースに、少し手直しをして頂きました。応募してくださった@さん、@さん、@さん、@さんありがとうございました。後日何らかの形でお礼をさせていただくつもりです。ありがとうございました。
では機能面を見ていきましょう。

Quick JUnitのビルド・テスト自動化に取り組み始めました。

長らく懸案であった、Quick JUnitのビルド・テストの自動化に取り組み始めました。環境はhttp://kompiro.dyndns-server.com/hudson/job/Quick%20JUnit%20CI/で公開しています。テストの件数は少ないですが、少しずつ追記しています。テストの作成にご興味のある方はquick-junit-devel@lists.sourceforge.jpまで名乗りを上げてくだされば、と思います。

新Feature


元々のQuick JUnitの機能は、小さくてもぴりりと効くFeatureのため、今回のリリースでもそんな機能を追加しています。例えば今年の夏に取り組んだテスト実行後にGrowlに通知したり、別途プロセスを立ち上げるFeatureもexperimentalとして公開しています。(どちらのFeatureも僕は常用しています。)また、Mockito integrationはexperimentalを卒業し、Mainに格上げしました。

コンテントアシスト「Q」を本体に組み込み

Mockitoと連携するために組み込んだ「Q」ですが、使い勝手が良いので本体に組み込みました。ただし、Mockito Integrationは別のFeatureに分離しているため、自動で行っていたstatic importの宣言は除いています。その代わり、次の機能を追加しました。

テストでよく使うstaticメソッドをFavoriteに追加


EclipseのPreference PageにはFavoritesという項目があります。ここにstatic importしたいクラスやメソッドを記述すると、コンテントアシスト時に補完してくれます。下記のように補完ができてとても便利です。

僕がこの他によく設定するのはjava.lang.String.formatだったりします。

コンテントアシストの追加

テストを書きやすいように、下記のコンテントアシストを追加しました。これらのコンテントアシストはjunit.extensions.eclipse.quick.template.featureで追加できます。

A:@Afterメソッドを追加する

B:@Beforeメソッドを追加する

AC:@AfterClassメソッドを追加する

BC:@BeforeClassメソッドを追加する

AT:assertThatメソッドを追加する



初期値は直近のローカル変数とexpectedという名前をisで等値比較しています。タブキーでexpectedに飛べるので大抵はカーソルキー触らずにassertThat書けます。

Quick JUnitソースコードFeatureの公開

このビルド・テストの自動化では、Buckminsterを用いています。Eclipse Pluginのビルド・テストプロセスは複雑なのですが、Buckminsterを用いる事で幾分か単純になっています。その二次的な効果ですが、Quick JUnitソースコードも別Featureで配布する事ができています。Quick JUnitのソフトウェアサイトからダウンロードしてください。

と言う事で駆け足ですがざっと今回のQuick JUnitの拡張をまとめました。是非お試しを〜。では。

Scala Meetup Tokyo開催しました!

昨日Scala Meetup Tokyoを開催しました!告知から10日あまりでしたが、id:kmizushimaさんが積極的に宣伝してくださったおかげで、20人くらいの方が参加されるイベントになりました。ありがとうございました。
今回来日されたMiles Sabin氏はScalaの前身のfunnelから触れられており、Scala普及のためにツールを整備しよう、と言う事で、Scala IDE for Eclipseを開発され始めたそうです。で、今回のお話は、Scala IDE for Eclipseの開発者、と言う事もあって、どうやってScalaのIDEを実装しているかが主になりました。IntelliJNetBeansとの比較検討もありました。IntelliJScalaの構造を解析する実装を自前で持ち、頑張って実装した結果、結局Java用の環境を整えるくらい労力をかけているそうです。しかし、Scala IDE for Eclipseの実装は、できるだけJDTに寄り添ってScalaの開発ができるように、AspectJを使ってScalaのコードをJDTがJavaを扱うのと同じように扱えるように環境を整えているそうです。当然、デバッグは難しいですが、ベースにしているJDTは、パッケージの隠蔽を駆使しているため、そのまま拡張できないのです。これはAspectJの開発環境を提供するプロジェクトでも同様の手法を駆使しており、Scala IDEもそれを参考に実装した、とのことでした。ただ、JDTプロジェクトは、JVMで動作する他の言語の開発環境のベースとしても使えるよう、話し合いが進んでいるようです。
id:kmizushimaさんはScala Daysでお話されたPEGEXについてのお話でした。
当日はustを希望されていた方もいましたが、みんながそれぞれ手弁当でイロイロ持ち寄ってできたイベントなので、ご勘弁ください。参加してくださった皆様、お手伝いいただいた皆様ありがとうございました!

10/19 19:00からScala Meetup Tokyoを開催します

Scala IDE for Eclipseの開発者であるMiles Sabinさんが来日される、ということで、それに合わせてScala Meetup Tokyoを開催することになりました!昨年OSGiについて語って頂いた、Neil Bertlettさんからのご紹介です。10/19(火) 19:00〜 新宿の豆蔵さんのトレーニングルームで開催します。
詳しくはこくちーずをご覧ください。
http://kokucheese.com/event/index/5106/

で、コンテンツなのですが、Milesさんに1時間語っていただく他、せっかくの機会ですので、日本のScala事情を話せる場になったらいいと思っています。すでにid:kmizushimaこと水島さんが手を挙げてくださっています。海外のエンジニアの方と語れるそれほど多くない機会でもあると思うので、是非ご参加ください。

Shibuya.trac第8回勉強会に行ってきました。

渋谷で行われた第7回Shibuya.trac勉強会ことTanabata.tracで分散環境でのTracでLTをやりたい!と飛び入りを申し入れたところ、さくっとreject。なので、第8回Shibuya.trac勉強会がやりたい!とつぶやいたら、@氏から、「企画に名前を書いたらみんななんとかなるんじゃ?」と言う事で名前を書いたら、開催されました。みなさま、本当にありがとうございました!
発表した資料はこちら

でもね。今回は「Mikogoという、デスクトップ共有ツールが強力!」というデモをするため、@さんに協力をお願いしたり、ちょっと準備をしたのですが、途中事故があってプレゼンを完遂できませんでした。と言うのも、当日たまたま2台PCを持っていたので、そちらに環境をつくり、2台ならべてプレゼンしたら、話している最中にメインで使っていたMacBook Airの端子が抜けてしまい、マシンがフリーズ。その後のプレゼンにも支障が出る、というさいあくのじたいに。

一番最後に、Shibuya.tracでもデモしたJAM Circleが、マイコミジャーナルに掲載されました、という報告をするため、LTの枠を頂いたんですが、結局そちらもうまくできず。そして、@氏や@氏からつっこまれるまで忘れてたんですが、今、Google先生に尋ねると、徳島にあるソー○ランドじゃなくなりました!やったね!

と、こんな感じだったのですが、Shibuya.tracの創立者である@氏が挨拶したり、仕切らなくても運営されるコミュニティになりつつあるShibuya.trac。みんなオープンに貢献しているとても素晴らしいグループになりつつあるんだと思いました。

Buckminsterを試してみる(1)

BuckminsterとはEclipse Plug-inのビルドやテストを補助するEclipse Plug-inです。Eclipse Demo Camp Tokyoで、「こんなネタで話したかったんだ」とつぶやいたネタの一つがBuckminsterでした。それで興味を持ってくださった方がいらっしゃったのと、PluginBuilderのHelios版がリリースされる様子がないので、この機会に試してみました。ここで公開されているチュートリアルを試しました。このチュートリアルを訳しつつ、メモをとりました。

準備
  • まっさらなEclipse RCP/RAPパッケージを用意*1

やったこと

RCPのサンプルとしてよく使われる、Mailテンプレートプロジェクトを作成する。
  • プラグインプロジェクト(com.example.mail)を作成
  • RCPの作成を選択
  • Nextを選ぶとテンプレートプロジェクトが表示される。Mailテンプレートを選択
配布用フィーチャーを作る(com.example.mail.feature)
  • フィーチャープロジェクト(com.example.mail.feature)を作る
  • Plug-insにcom.example.mailを追加
  • include featuresにcom.eclipse.rcp*2を追加
RCPとしてビルドできる事を確認する。
  • com.example.mail.featureにproductファイル*3を追加する。
  • 下記の写真みたいに情報を追加する。

  • "The product configuration is based"にfeatureを選択し、Dependencyタブでcom.example.mail.featureを選ぶ
  • 試しにプロダクトが起動するか確認する。OverviewタブのLaunch an Eclipse Applicationを選択する。*4
Buckminsterをインストールする。
Buckminster用のフィーチャープロジェクト(com.example.mail.site)を作成

target platform*5の定義と共有をします。

  • Preference画面を開き、 Plug-in Development > Target Platformを選ぶ。
  • 空の定義を作成し、Eclipse Software SiteからEclipse RCP SDKEclipse Platform Launchersを追加する。
  • Include required softwareのチェックは外し、Include all environmentsにチェックを入れる。
  • 現在のターゲットプラットフォームに指定する
Buckminsterを使ってp2リポジトリを作成する

Buckminsterを使ってp2リポジトリを作るのは簡単です。

  • com.example.mail.siteを選択し、コンテキストメニューを表示し、Buckminster > Invoke Action を選択すると次のダイアログが表示される。

  • しばらく待つと、site.p2が表示される。site.p2を選択すると、同じワークスペースにBuckminster.outputというフォルダが出来る。それがp2のリポジトリ
  • 今度はp2リポジトリの出力先等、カスタマイズ。まず下記のプロパティファイルを作る。
# 出力先
buckminster.output.root=${user.home}/tmp/mail
# 一時ファイルの出力先
buckminster.temp.root=${user.home}/tmp/buildtmp
# .qualifier の置換方法(リビジョンで置き換える)
qualifier.replacement.*=generator:lastRevision

target.os=*
target.ws=*
target.arch=*
  • 先ほどのダイアログではpropertiesファイルの指定欄があったが、そこに作成したbuckminster.propertiesを指定。

これで出力先のカスタマイズ等できます。.qualifierの指定方法は他にもgenerator:lastModifiedや generator:buildTimestamp があります。一般的にeclipse上からエクスポートされると置換されるのは、buildTimestamp形式です。先ほどのbuckminster.propertiesはこんな感じで指定します。

qualifier.replacement.*=generator:buildTimestamp
generator.buildTimestamp.format=yyyyMMddHHmm

これで自動ビルドの下準備が整いました。続いてHudson...と行きたいところですが、ちょうど区切りがいいので次回。ちなみに紹介したチュートリアルのサイトではHudsonの自動化までやられており、実際にやってみたのですが、拍子抜けするくらい簡単でした。ただ、作業は簡単ですが、実際はp2のインストールに時間がかかる事があるので、なんか止まってるっぽいと思って終了しないように。ハマったのは、フィーチャーIDの指定が間違っていた、ということくらいです。

*1:他のプラグインによる干渉を防ぐため。何か変な動作があったとき、その原因を探る時間がもったいないでしょう。

*2:RCP用のベース機能を用意しているフィーチャー

*3:RCPとしてパッケージするための情報を格納したファイル

*4:Macの場合、64bit Java VMを利用しているのであれば、VM引数に-d32が含まれていないと起動しない。

*5:target platformとは開発中のプラグインを載せるためのプラットフォームの定義です。