MRUnitを用いたMapReduceの単体テスト

提供: omotenashi-mind
移動先: 案内検索

MapReduceの実装を行う場合、わざわざHadoopの環境を用していたら開発者負担が大きく、非効率的です。
そんな問題を解決してくれるのがMRUnitです。

MRUnitはMapReduceの処理を簡単にテスト可能な仕組みを提供します。

前提

必要ライブラリを取得するため、mavenを利用します。

準備作業

まずはMapReduce処理の実装に必要なライブラリを取得します。
必要なライブラリは次の2つです。

  • hadoop-common
  • hadoop-mapreduce-client-core


さらに単体テスト処理に必要なMRUnitのライブラリも取得します。

  • mrunit

Hadoopの1系、2系それぞれでライブラリが分かれていますので、利用したいHadoopのバージョンに合わせて選択してください。


実装

ここでは、MRUnitのチュートリアルに記載されているCDR(Call Detail Record)の解析処理をベースに解説を進めていきます。

MapおよびReduce処理の実装

Map処理の実装クラス

 1 import org.apache.hadoop.io.LongWritable;
 2 import org.apache.hadoop.io.IntWritable;
 3 import org.apache.hadoop.io.Text;
 4 import org.apache.hadoop.mapreduce.Mapper;
 5 
 6 public class SMSCDRMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
 7  
 8   private Text status = new Text();
 9   private final static IntWritable addOne = new IntWritable(1);
10  
11   /**
12    * Returns the SMS status code and its count
13    */
14   protected void map(LongWritable key, Text value, Context context)
15       throws java.io.IOException, InterruptedException {
16  
17     //655209;1;796764372490213;804422938115889;6 is the Sample record format
18     String[] line = value.toString().split(";");
19     // If record is of SMS CDR
20     if (Integer.parseInt(line[1]) == 1) {
21       status.set(line[4]);
22       context.write(status, addOne);
23     }
24   }
25 }


Reduce処理の実装クラス

 1 import org.apache.hadoop.io.IntWritable;
 2 import org.apache.hadoop.io.Text;
 3 import org.apache.hadoop.mapreduce.Reducer;
 4 
 5 public class SMSCDRReducer extends
 6   Reducer<Text, IntWritable, Text, IntWritable> {
 7  
 8   protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws java.io.IOException, InterruptedException {
 9     int sum = 0;
10     for (IntWritable value : values) {
11       sum += value.get();
12     }
13     context.write(key, new IntWritable(sum));
14   }
15 }


テスト実装クラス

 1 import java.io.IOException;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 
 5 import org.apache.hadoop.io.IntWritable;
 6 import org.apache.hadoop.io.LongWritable;
 7 import org.apache.hadoop.io.Text;
 8 import org.apache.hadoop.mrunit.mapreduce.MapDriver;
 9 import org.apache.hadoop.mrunit.mapreduce.MapReduceDriver;
10 import org.apache.hadoop.mrunit.mapreduce.ReduceDriver;
11 import org.junit.Before;
12 import org.junit.Test;
13  
14 public class SMSCDRMapperReducerTest {
15   MapDriver<LongWritable, Text, Text, IntWritable> mapDriver;
16   ReduceDriver<Text, IntWritable, Text, IntWritable> reduceDriver;
17   MapReduceDriver<LongWritable, Text, Text, IntWritable, Text, IntWritable> mapReduceDriver;
18  
19   @Before
20   public void setUp() {
21     SMSCDRMapper mapper = new SMSCDRMapper();
22     SMSCDRReducer reducer = new SMSCDRReducer();
23     mapDriver = MapDriver.newMapDriver(mapper);
24     reduceDriver = ReduceDriver.newReduceDriver(reducer);
25     mapReduceDriver = MapReduceDriver.newMapReduceDriver(mapper, reducer);
26   }
27  
28   @Test
29   public void testMapper() throws IOException {
30     mapDriver.withInput(new LongWritable(), new Text(
31         "655209;1;796764372490213;804422938115889;6"));
32     mapDriver.withOutput(new Text("6"), new IntWritable(1));
33     mapDriver.runTest();
34   }
35  
36   @Test
37   public void testReducer() throws IOException {
38     List<IntWritable> values = new ArrayList<IntWritable>();
39     values.add(new IntWritable(1));
40     values.add(new IntWritable(1));
41     reduceDriver.withInput(new Text("6"), values);
42     reduceDriver.withOutput(new Text("6"), new IntWritable(2));
43     reduceDriver.runTest();
44   }
45    
46   @Test
47   public void testMapReduce() throws IOException {
48     mapReduceDriver.withInput(new LongWritable(), new Text(
49               "655209;1;796764372490213;804422938115889;6"));
50     mapReduceDriver.withOutput(new Text("6"), new IntWritable(1));
51     mapReduceDriver.runTest();
52   }
53 }


単体テスト用コードをご覧いただくと分かる通り、Map、Reduceを別々にテストしたり、MapReduceとしてまとめてテストすることもできるようになっています。

参考サイト

https://cwiki.apache.org/confluence/display/MRUNIT/MRUnit+Tutorial