今回はいよいよプログラムの作成に入ります。
TDDなので、まずはテストケースから作成します。
- Eclipseのパッケージエクスプローラー上で、testフォルダーで右クリック、「新規」→「JUnitテスト・ケース」をクリック。
- 「新規JUnit テスト・ケース」ダイアログで「新規 JUnit 4 テスト」を選択、パッケージにパッケージ構造を入力。今回は「jp.co.littel.hadoop」と入力しました。
- 名前に「TestLogAnalysisMapper」を入力。「setUp」と「tearDown」、お好みで「コメントの生成」にチェックを入れ「完了」ボタンをクリックします。
- 「JUnit4がビルド・パスにありません。追加しますか?」と聞かれるので、「次のアクションを実行」が選択され、「JUnit4ライブラリをビルド・パスに追加」が選択されていることを確認して「OK」ボタンをクリック。
- testフォルダー配下のjp.co.littel.hadoopパッケージ内にTestLogAnalysisMapperが追加されました。
まずはテストを作成しましょう。
import org.junit.After; import org.junit.Before; import org.junit.Test; /** * * @author yoshitsugu */ public class HadoopGrepMapperTest { /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { } /** * @throws java.lang.Exception */ @After public void tearDown() throws Exception { } /** * 抽出するパターン * @throws Exception 例外発生時 */ @Test public void testMapExtract() throws Exception { String[] lines = { "2009-12-14 00:00:26,340 INFO hogehoge @ abcdefg hijklmn opqrstu" };verify(context, new Times(1)).write(new LongWritable(1), new Text(lines[0]));verify(context, new Times(1)).write(new Text(lines[0]), new LongWritable(1)); } }
「待てぇ~い!コンパイルが全然通らんではないか。」というお叱りの声が聞こえてきそうです。
TDDは、まず「何をテストしているのか」を意識します。まず、何をテストするのかを書くのです。コンパイルを通すのはその後です。
「ちょっと待て、テストから書くのならJUnitで見慣れたassertEqualsなどのメソッドがあるはずだろう?どこにも見あたらないぞ?」
ここが今回の肝、モックオブジェクトライブラリ mockitoです。
verify(context, new Times(1)).write(new LongWritable(1), new Text(lines[0]));
verify(context, new Times(1)).write(new Text(lines[0]), new LongWritable(1));
に注目して下さい。
ここで、contextはorg.apache.hadoop.mapreduce.Mapper.Contextクラスのモックインスタンスです。
verifyメソッドはcontext.write(KEY, VALUE)メソッドが、「KEYがどんな値で」「VALUEがどんな値で」「何度」呼ばれるかを判別します。
上記の例では、context.writeが、KEY=new LongWritable(1)という値で、VALUE=new Text(lines[0])という値では、1度(1 time)だけ呼ばれれば、テストOKであるという事になります。
では、テストができたので、コンパイルを通せるようにしましょう。
コンパイルエラーとなっている部分をマウスでポイントして、[Ctrl]+[1]キーを押下することで、LongWritableやTextはimport文を追加することができるはずです。
つづいて、contextのコンパイルエラーをなくすために、contextを宣言します。
次の一文をtestMapExtract()メソッドの一文目に追加しましょう。
Mapper.Context context;
そうするとMapperがコンパイルエラーになるはずです。
[Ctrl]+[1]キーでorg.apache.hadoop.mapreduce.Mapperのimport文を追加しましょう。
まだverifyがコンパイルエラーになっていますね。
これはEclipse任せでは解消できないので次のimport static文を追加して下さい。
import static org.mockito.Mockito.verify;
そうすると、再びcontextが初期化されてないのでコンパイルエラーになると思います。
とりあえず、context = nullで初期化しましょう。
ここまでで、コンパイルが一通り通りました。
今回はここまでにします。
お詫び:
返信削除肝心のテストの所、引数を
verify(context, new Times(1)).write(new Text(lines[0]), new LongWritable(1));
としないと、複数datanodeで実行した時に結果がおかしくなってしまう事に気がつきました。謹んで訂正いたします。