Hatena::ブログ(Diary)

Fly me to the Juno! このページをアンテナに追加 RSSフィード

2008-02-29

プラグインのテストコードを書く(ツールバー編:v3.3)

今日は4年に1度の大肉の日。今日リリースとかやったらかっこいいのだけれども、今回も断念。へたれっぷりにがっくし。

さて、 プラグインのテストコードを書く(コマンド編:v3.3) - Fly me to the Juno!/ プラグインのテストコードを書く(ショートカット編:v3.3) - Fly me to the Juno!に引き続きテストコードの型シリーズ第3回。今回もKenichi Takahashi氏のFontSizeChangerですよー。リポジトリ

https://eclipse-study.svn.sourceforge.net/svnroot/eclipse-study/EasyFontChanger/branches/TRY-Active-View/

です。

今回のお題はツールバー-コマンド間の実行(Toolbar-Command)です。

ツールバーとコマンドの関係はplugin.xmlに次のように書きます。

 <extension
   point="org.eclipse.ui.menus">
  <menuContribution
    locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
   <toolbar
     id="net.shu_cream.eclipse.font">
    <command
      commandId="net.shu_cream.eclipse.font.large" (1)
      icon="icons/large.gif"
      id="large" (3)
      label="Large"
      style="push"
      tooltip="Large">
    </command>
   </toolbar>
  </menuContribution>
 </extension>
 <extension
   point="org.eclipse.ui.commands">
  <command
    categoryId="net.shu-cream.eclipse.font.category1"
    id="net.shu_cream.eclipse.font.large" (1)
    name="Large">
 </extension>

例によって(1)がToolbarとCommandを結びつけるキーです。で、今回書いたテストコードはこんな感じ。

 @Test
 public void このクラスがツールバーに登録されているか() throws Exception {
  IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
  for(IWorkbenchWindow w : windows){
   ApplicationWindow window = (ApplicationWindow) w;//(a)
   ICoolBarManager coolbar = window.getCoolBarManager2();
   ToolBarContributionItem contributionItem = (ToolBarContributionItem) coolbar.find("net.shu_cream.eclipse.font");
   assertNotNull(contributionItem);
   
   ToolBarManager barManager = (ToolBarManager) contributionItem.getToolBarManager();
   IContributionItem item = barManager.find("large");//(b)
   assertNotNull(item);
   assertTrue(item instanceof CommandContributionItem);
   
   CommandContributionItem commandItem = (CommandContributionItem) item;
   assertTrue(commandItem.isEnabled());

   doCommand(barManager);
  }
  
 }

 private void doCommand(ToolBarManager barManager) {
  ToolBar toolbar = barManager.getControl();
  ToolItem[] toolItems = toolbar.getItems();
  for(ToolItem toolItem : toolItems){
   if("Large".equals(toolItem.getToolTipText())){
    // execute toolbar item
    toolItem.notifyListeners(SWT.Selection, null);//(c)
   }
  }
 }

若干無理やり感が漂っているコードですが、これでもツールバーに登録されていて、きちんと動くかどうかを確認できます。

まず(a)ですが、直接インスタンスを確認するとWorkbenchWinndowクラスが返ってきています。そうです。Eclipseのウィンドウクラスです。それを無理やりJFaceのApplicationWindowクラスへキャストしているのは、WorkbenchWindowクラスがinternalだから。不要なinternalへの参照はなるだけ避けるようにしましょう。

(b)ではlargeというキー名でツールバーのアイテムを取得しています。plugin.xmlの(3)のキー名です。さらっと取得してみましょ。

(c)では実際に取得したツールバーのアイテムを実行しています。ちょっとズルいのはラベル名を取得して比較しているところでしょうか。でもそういう名前のチェックがあってもいいよねー。(と言い訳にならない言い逃れ。)

これで一応FontSizeCheckerの一機能に関してはテストが書けたのではないかと自画自賛。プラグインのテストを書くと何が一番うれしいかって、バージョンやOSなどの環境の違うEclipse上できちんと動くかどうかさらっと検証ができる点。LL系のソフトでは実働環境で動いているかどうかを確認するためのテストコードが付属することが多いですが、Eclipse Pluginでそこまで手をまわす人が少ないこの事実。Eclipse Foundationが公開しているWikiにもあんまりその辺の情報がない点が足を引っ張っているんでしょうね。

以上テストで足らない点があればご指摘くださいね。

2008-02-27

プラグインのテストコードを書く(ショートカット編:v3.3)

プラグインのテストコードを書く(コマンド編:v3.3) - Fly me to the Juno!に引き続きテストコードの型シリーズ。以外に簡単にいけちゃいそう。今回はショートカット編。題材もKenichi Takahashi氏のFontSizeChanger。リポジトリ

https://eclipse-study.svn.sourceforge.net/svnroot/eclipse-study/EasyFontChanger/branches/TRY-Active-View/

です。

今回のお題はショートカット-コマンド間の実行(Binding-Command)です。ショートカットとコマンドの関係はplugin.xmlに次のように書きます。

<extension
  point="org.eclipse.ui.commands">
 <command
   categoryId="net.shu-cream.eclipse.font.category1" (2)
   id="net.shu_cream.eclipse.font.large" (1)
   name="Large">
 </command>
</extension>
<extension
 point="org.eclipse.ui.bindings">
  <key
   commandId="net.shu_cream.eclipse.font.large" (1)
   contextId="org.eclipse.ui.contexts.dialogAndWindow"
   schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
   sequence="M1+M3+;">
  </key>
</extension>

(1)がCommandとHandlerを結びつけるキーで、(2)のカテゴリーを設定しないと環境によってはせっかく設定したCommandが動作しなくなることがあるようです。

WindowsだとM1はCtrlキー、M3はAltキーに相当します。*1で、今回書いたテストコードはこんな感じ。

  @Test
  public void このクラスがショートカットに登録されているか() throws Exception {
    IBindingService service = (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class);
    TriggerSequence[] sequences = service.getActiveBindingsFor("net.shu_cream.eclipse.font.large");
    assertEquals(1, sequences.length);
    KeyStroke s = (KeyStroke)sequences[0].getTriggers()[0];
    System.out.println(s.format());
    assertEquals("Ctrl+Alt+;",sequences[0].format());
  }

ありがたいことにorg.eclipse.ui.keys.IBindingServiceにはコマンドのIDからアクティブなキーバインドを取得できるgetActiveBindingsFor(String)というAPIが用意されているんですね。これでキーバインドを取得して、ショートカットキーの文字列を比較すれば一応テストできます。*2

IBindingServiceクラスには他にBinding IBindingService#getPerfectMatch(TriggerSequence)というAPIがあり、BindingクラスからgetParametarizedCommand()を取得すると前述のコマンドなので、それを実行してあげると(Binding - Command - Handler)の一連の流れを実行することができます。

*1:他のプラットフォームだとどうなのかなど、詳しい情報をお探しの方はHelp - Eclipse Platformのkey - sequenceの辺りを見てください。

*2:マルチOSには未対応

2008-02-19

プラグインのテストコードを書く(コマンド編:v3.3)

TDDをしたいと思っていてもどうしてもできないことってあるじゃないですか。Eclipse Pluginの開発なんて諸にそうなんですが、振る舞いをコードに落とし込めない時はどうしようもありません。例えばツールバーをポチッと押したらアクションがあるアクションが呼ばれてエディタフォントが大きくなるっていう一連を、コードに落とし込めなかったらTDDのしようがありません。ということでPlugin開発でTDDをするにはどうすればいいかを単発的にとりあげてみようという試み。今回はコマンド編。題材はKenichi Takahashi氏のFontSizeChanger。リポジトリ

https://eclipse-study.svn.sourceforge.net/svnroot/eclipse-study/EasyFontChanger/branches/TRY-Active-View/

です。勝手にテストプラグインを作りつつ、はてダにて取り上げようという作戦。

今回のお題はコマンド-ハンドラ間の実行(Command-Handler)。plugin.xmlに書くこの結びつきを実行できているかどうか確認できれば、後はメニューから呼ぶのもショートカットから呼ぶのもできそうじゃないですか。

plugin.xmlの実体はこんな感じ(必要なところ以外省略)

   <extension
         point="org.eclipse.ui.handlers">
      <handler
            class="net.shu_cream.eclipse.font.ToLargeHandler"
            commandId="net.shu_cream.eclipse.font.large">
      </handler>
   </extension>
   <extension
         point="org.eclipse.ui.commands">
      <command
            categoryId="net.shu-cream.eclipse.font.category1"
            id="net.shu_cream.eclipse.font.large"
            name="Large">
      </command>
   </extension>

commandのid "net.shu_cream.eclipse.font.large"が同じというのを見て確認ができるとおもいます。ここのid名が間違っていた場合、呼び出す事ができなくなるので、それをあらかじめ確かめたい。そこで書くのが次のコード

public class TestToLargeHandler {
	@Before
	public void テスト実行のその前に(){
		Command.DEBUG_COMMAND_EXECUTION = true;
	}
	@Test
	public void このクラスがハンドラサービスに登録されていますか() throws Exception{
		ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
		assertNotNull(commandService);
		Command command = commandService.getCommand("net.shu_cream.eclipse.font.large");
		assertNotNull(command);
		command.executeWithChecks(null);
	}
}

Command.DEBUG_COMMAND_EXECUTIONをtrueにしておくと、どのコマンドが実行されたか確認する事ができます。