単体テストを“神速”化するQuick JUnitとMockitoユカイ、ツーカイ、カイハツ環境!(16)

» 2010年08月02日 00時00分 公開
[岡本隆史,@IT]

Quick JUnitプラグインの3つの大きな特徴

 近年、JUnitHudsonを利用した継続的インテグレーションCI)によるテストの自動化や、テスト駆動開発TDD)の普及などにより、ユニットテスト単体テスト)のテストコードの作成が重要視されています。


 今回紹介する「Quick JUnit」プラグインは、JUnitによるテストコードの作成と実装を支援するEclipseプラグインです。Quick JUnitプラグインは石井勝さんにより開発されていましたが、石井さんが不慮の事故により死去後、Quick JUnitプラグインプロジェクトにより開発が継続されています。優れたオープンソースプロジェクトの模範のようなプロジェクトです。

訂正のお知らせ

故人のお名前について間違いがあり、修正させていただきました。

内容について正確を期せずに混乱を招いた点、故人およびご家族、関係者、読者の皆様におわび申し上げます(2010年8月3日)。


 Quick JUnitは、次のような3つの大きな特徴を持っています。

【1】テストコード切り替え機能

 テストコードの切り替え機能により、開発者は、たくさんのコードの中から現在エディタで開いているテストコードを探す手間が省けます。

 また、エディタ上で編集しているテストコードから、テスト元のコードを開くことも一瞬でできます。この機能により、現在実装しているクラステストクラスを簡単に表示できます。

【2】メソッドごとのテスト実行機能

 従来のEclipseではテストクラス単位でしかテストを実行できませんでしたが、Quick JUnitを導入すれば、JUnitのテストケースメソッド単位でテストを実行できます。この機能により、メソッドごとに実装・テストを迅速に行えます。

【3】Mockitoによるテスト支援機能

 「EasyMock」などより簡潔なモックができるオープンソースの「Mockito」がJavaモックフレームワークとして人気上昇中ですが、Quick JUnitは、Mockitoによるテスト作成を支援する機能があります。Mockitoを利用することにより、ミドルウェアや外部システムを利用するクラスのテストケースの作成を効率的に行えます。

 Mockitoのより詳細な情報については、下記ページをご覧ください。また、EasyMockとの違いに興味がある方は、Mockitoプロジェクト上の記事「Mockito VS EasyMock」もご覧ください。


 これらの機能により、実装、テストコード作成、メソッド単位のテストの実行をスムーズに行えます。

Quick JUnitプラグインをインストールするには

 Eclipseのメニューの[新規ソフトウェアインストール]を利用して、下記のアップデートサイトを入力してプラグインをインストールしてください。

  • http://quick-junit.sourceforge.jp/updates/current/

 またEclipse 3.6からは、「Eclipse Marketplace」からQuick JUnitプラグインを検索してインストールすることもできるようになっています(図1)。「Eclipse Marketplace」は、Eclipseのメニューの[Help]から[Eclipse Marketplace...]を選択すると、利用できます。

図1 Eclipse MarketplaceからQuick JUnitプラグインのインストール 図1 Eclipse MarketplaceからQuick JUnitプラグインのインストール(画像をクリックすると、拡大します)

テストケースの切り替えと実行

 テストケースの切り替えとメソッドのテストの実行のイメージは図2の通りです。実装コードをエディタに表示した状態で[Ctrl]+[9]キーを押すだけで、エディタをテストコードに切り替えられます。

 また、テストコードをエディタに表示しているときは、実装コードに切り替えます。実装コードとテストコードのソースフォルダが別の場合でも簡単に切り替えられるので、非常に便利です。

図2 テストの切り替えと実行 図2 テストの切り替えと実行(画像をクリックすると、拡大します)

 通常、実装コードとテストコードは別のフォルダに置くため、切り替えるのに時間がかかってしまいますが、Quick JUnitを利用すると、まさに一瞬で実装コードとテストコードを切り替えれます。

 テストコードが存在しない場合、[Ctrl]+[9]キーを押すとテストコードのひな型も生成できます。メソッド上で[Ctrl]+[0]キーを押すと、特定のメソッドのみユニットテストを実行できます。

 なお、Quick JUnitは、例えばXXX.javaというソースコードに対してXXXTest.javaとクラス名の後にTestがついたクラスをテストコードとして扱います。

Mockitoを利用したテストの作成

 システム間の連携やデータベースなどのミドルウェアを利用したソフトウェアのテストでは、ユニットテストのために関連システムのセットアップやミドルウェアを設定すると、テスト1つ1つに非常に時間がかかってしまいます。そのような場合、DI依存性の注入)を利用した開発では、従来、インターフェイスを定義して実装クラスとテスト用のモッククラスを切り替えてテストを行うようにいわれてきました。

 しかし、実装クラスごとにインターフェイスとモッククラスを用意する必要があったり、テストごとにDIコンテナの設定ファイルを切り替える必要があったり、非常に煩雑になります。

 Quick JUnitでは、Mockitoを利用したモック生成をサポートしています。Mockitoを利用すれば、データベースなどに依存した実装クラスのオブジェクトにインターフェイスの作成や設定ファイルの切り替えをすることなしにテストを行うことができます

Mockitoを利用したテストケースの追加

 テストメソッドを作成したい場所にカーソルを移動させ、[q](アルファベットのキュー)キーを入力した後、[Ctrl]+[スペース]キーでEclipseのコードアシスト機能を利用すると、[Quick JUnit Mockito Integration]が表示されます(図3)。

図3 Mockito用テストのひな型作成 図3 Mockito用テストのひな型作成

 この[Quick JUnit Mockito Integration]を選択すると、テストメソッドのひな型が生成されるとともに、JUnitやMockitoを利用するためのimport文が追加されます(図4)。

図4 Mockitoのimport文が追加されたテストコード 図4 Mockitoのimport文が追加されたテストコード

 また、プロジェクトにMockitoのjarへのクラスパスが通っていない場合、Mockitoのインポート文の警告をクリックし、[Fix project setup](プロジェクトのセットアップを修正)を選択します(図5)。

図5 エラーの修正候補 図5 エラーの修正候補(画像をクリックすると、拡大します)

 すると[Mockitoをライブラリへ追加する]という修正候補が表示される(図6)ので、[OK]と押すとQuick JUnitプラグインが内部で持っているMockitoのjarにクラスパスを自動的に通してくれます。

図6 Mockitoをライブラリへ追加 図6 Mockitoをライブラリへ追加

Mockitoを利用したテストケースの作成

 さて、ここまででQuick JUnitを使うと、Mockitoを簡単に使えることは分かりましたが、実際にMockitoを利用したテストを作成してみましょう。次のように、CartService.javaの中にカートの合計金額を計算するロジックがあるとします。

package xxx.yyy.zzz;
 
:
【省略】
:
 
public class CartService {
 
    @Inject
    CartDao dao;
 
    @Inject
    User user;
 
    public void setCartDao(CartDao dao){
        this.dao = dao;
    }
    
    @Inject
    public void setUser(User user){
        this.user = user;
    }
    
    // 現在のユーザーのカート内の商品の合計を計算
    public int calcTotal(){
        List<CartItem> itemList = dao.findCartItemsByUserID(user.getID());
        int total = 0;
        for(CartItem item:itemList){
            total += item.getPrice();
        }
        return total;
    }
}
CartService.java

 上記のメソッドは、DAO(Data Access Object)を利用して商品一覧を取得していますが、そのDAOが次のようなコードだとします。

package org.ultimania.sample;
 
import java.util.List;
 
import javax.persistence.*;
 
public class CartDao {
    @PersistenceContext
    EntityManager entityManager;
 
:
【省略】
:
 
    @SuppressWarnings("unchecked")
    public List<CartItem> findCartItemsByUserID(String name) {
        String queryStr = "select b from " + CartItem.class.getName()
                + " b where b.name=:name";
        Query query = entityManager.createQuery(queryStr);
        query.setParameter("name", name);
    
        return (List<CartItem>) query.getResultList();
    }
:
【省略】
:
}
CartDao.java

 findCartItemByUserIDメソッドは、内部でJPA(Java Persistence API)を利用しており、CartServiceのテストを作成しようとすると、データベースを作成して、データベース内にデータを設定して、と煩雑になってしまいます。

 Mockitoを利用すると、次のような感じでfindItemsByUserID()の実行結果を疑似的に設定でき、純粋にCartServiceクラスのテストだけができます。

@Test
public void testCalcTotal() {
    // テスト用のデータ作成
    User user = new User("okamototk");
 
    List<CartItem> itemList = new ArrayList<CartItem>();
    itemList.add(new CartItem("不愉快痛恨開発環境〜こうしてダメな社内開発環境は作られる〜",2480));
    itemList.add(new CartItem("トラブルハック大全〜火消の極意〜",2980));
    itemList.add(new CartItem("ウォータフォールは滅びぬ何度でも蘇るさ",1980));
 
    // モックのDAOオブジェクト作成
    CartDao dao = mock(CartDao.class);
    
    // dao.findCartItemsByUserID("okamototk")を実行したときにitemListを
    // 返却するようにdaoを設定
    when(dao.findCartItemsByUserID("okamototk")).thenReturn(itemList);
 
    // カートをインスタンス化し、DAOとユーザーオブジェクトを設定
    CartService cart = new CartService();
    cart.setCartDao(dao);
    cart.setUser(user);
    
    // テスト対象のメソッドの実行
    int total = cart.calcTotal();
 
    assertEquals(total,7440);
}

 データベースを利用したテストでは、テストごとにデータベースを初期化したり、テスト用データの投入を設定するなど煩雑な作業が必要であったり、データベースのセットアップコードをテストコードとして記述する必要がありますが、Mockitoを利用すれば、ほかのクラスの戻り値を簡単に設定できます

 これを応用すれば、Mockitoシステム間の接続が必要な場合や、ミドルウェアが必要なテストで接続対象のシステムやミドルウェアがなくても、ユニットテストを実施できます。

かゆいところに手が届き便利で病みつきになる

 Quick JUnitの提供する機能は非常にシンプルですが、まさにかゆいところに手が届くツールとなっています。一度、Quick JUnitを使い始めると便利で病みつきになってしまいます。ぜひQuick JUnitを導入して、テストを効率化してみてください。


「ユカイ、ツーカイ、カイハツ環境!」バックナンバー

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。