乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      hadoop單元測試方法--使用和增強(qiáng)MRUnit

       風(fēng)自向前 2011-06-22

      1前言

               hadoop的mapreduce提交到集群環(huán)境中出問題的定位是比較麻煩的,有時需要一遍遍的修改代碼和打出日志來排查一個很小的問題,如果數(shù)據(jù)量大的話調(diào)試起來相當(dāng)耗時間。因此有必要使用良好的單元測試手段來盡早的消除明顯的bug(當(dāng)然僅有單元測試是不夠的,畢竟跟集群的運(yùn)行環(huán)境還是不一樣的)。

             然而做mapreduce的單元測試會有一些障礙,比如Map和Reduce一些參數(shù)對象是在運(yùn)行時由hadoop框架傳入的,例如OutputCollector、Reporter、InputSplit等。這就需要有Mock手段。最初寫mapreduce單元測試的時候自己寫了幾個簡單的Mock也基本能滿足需要,后來發(fā)現(xiàn)MRUnit比我寫的要好用所以研究了一下就采用了。MRUnit是專門為hadoop mapreduce寫的單元測試框架,API簡潔明了,簡單實(shí)用。但也有一些薄弱的地方,比如不支持MultipleOutputs(很多情況下我們會用MultipleOutputs作為多文件輸出,后面將介紹如何增強(qiáng)MRUnit使之支持MultipleOutputs)。

      2 MRUnit

               MRUnit針對不同測試對象分別使用以下幾種Driver:

      l  MapDriver,針對單獨(dú)的Map測試。

      l  ReduceDriver,針對單獨(dú)的Reduce測試。

      l  MapReduceDriver,將Map和Reduce連貫起來測試。

      l  PipelineMapReduceDriver,將多個Map-Reduce pair貫串測試。

      MapDriver

               單獨(dú)測試Map的例子,假設(shè)我們要計(jì)算一個賣家的平均發(fā)貨速度。Map將搜集每一次發(fā)貨的時間間隔。針對Map的測試,

               //這是被測試的Map

          private Map mapper;

          private MapDriver<LongWritable, Text, Text, TimeInfo> mapDriver;

          @Before

          public void setUp() {

              mapper = new Map();

              mapDriver = new MapDriver<LongWritable, Text, Text, TimeInfo>();

          }

       

          @Test

          public void testMap_timeFormat2() {

              String sellerId = "444";

              //模擬輸入一行(withInput),假設(shè)從這行數(shù)據(jù)中我們可以獲得賣家(sellerId)      //某一次時間間隔 為10小時.

             //我們期望它輸出sellerId為key,value為代表1次10小時的TimeInfo對象。          //(withOutput)

             //如果輸入數(shù)據(jù)經(jīng)過Map計(jì)算后為期望的結(jié)果,那么測試通過。

             Text mapInputValue = new Text("……");

              mapDriver.withMapper(mapper)

                    .withInput(null, mapInputValue)

                    .withOutput(new Text(sellerId), new TimeInfo(1, 10))

                    .runTest();

          }

      ReduceDriver

               針對Reduce的單獨(dú)測試,還是這個例子。Reduce為根據(jù)Map或Combiner輸出的n次時間間隔的總和來計(jì)算平均時間。

          private Reduce reducer;

          @Before

          public void setUp() {

              reducer = new Reduce();

              reduceDriver = new ReduceDriver<Text, TimeInfo, Text,                                           LongWritable>(reducer);

          }

       

          @Test

          public void testReduce () {

              List<TimeInfo> values = new ArrayList<TimeInfo>();

              values.add(new TimeInfo(1, 3));//一次3小時

              values.add(new TimeInfo(2, 5));//兩次總共5小時

              values.add(new TimeInfo(3, 7));//三次總共7小時

             //values作為444這個賣家的reduce輸入,

             //期望計(jì)算出平均為2小時

              reduceDriver.withReducer(reducer)

                        .withInput(new Text("444"), values)

                        .withOutput(new Text("444"),new  LongWritable(2))

                        .runTest();

          }

      MapReduceDriver

          以下為Map和Reduce聯(lián)合測試的例子,

          private MapReduceDriver<LongWritable, Text, Text, TimeInfo, Text, LongWritable> mrDriver;

          private Map mapper;

          private Reduce reducer;

          @Before

          public void setUp() {

              mapper = new Map();

              reducer = new Reduce();

              mrDriver = new MapReduceDriver<LongWritable, Text, Text, TimeInfo,                    Text, LongWritable>(mapper, reducer);

          }

       

          @Test

          public void testMapReduce_3record_1user() {

             Text mapInputValue1 = new Text("……");

             Text mapInputValue2 = new Text("……");

             Text mapInputValue3 = new Text("……");

             //我們期望從以上三條Map輸入計(jì)算后,

             //從reduce輸出得到444這個賣家的平均時間為2小時.

              mrDriver.withInput(null, mapInputValue1)

                 .withInput(null, mapInputValue2)

                 .withInput(null, mapInputValue3)

                 .withOutput(new Text("444"),new LongWritable(2))

                 .runTest();

          }
       

      增強(qiáng)MRUnit

               下面介紹為MRUnit框架增加了支持MultipleOutputs、從文件加載數(shù)據(jù)集和自動裝配等幾個特性,使它更加便于使用。

      如何支持MultipleOutputs

               然而很多場景下我們需要使用MultipleOutputs作為reduce的多文件輸出,MRUnit缺少支持。分析源碼后為MRUnit增強(qiáng)擴(kuò)展了兩個DriverReduceMultipleOutputsDriverMapReduceMultipleOutputDriver來支持MultipleOutputs。

       

      ReduceMultipleOutputsDriver

               ReduceMultipleOutputsDriverReduceDriver的增強(qiáng)版本,假設(shè)前面例子中的Reduce使用了MultipleOutputs作為輸出,那么Reduce的測試將出現(xiàn)錯誤。


       

      使用ReduceMultipleOutputsDriver改造上面的測試用例(注意粗體部分),

      private Reduce reducer;

          @Before

          public void setUp() {

              reducer = new Reduce();

             //注意這里ReduceDriver改為使用ReduceMultipleOutputsDriver

              reduceDriver = new ReduceMultipleOutputsDriver<Text, TimeInfo,                                     Text, LongWritable>(reducer);

          }

       

          @Test

          public void testReduce () {

              List<TimeInfo> values = new ArrayList<TimeInfo>();

              values.add(new TimeInfo(1, 3));//一次3小時

              values.add(new TimeInfo(2, 5));//兩次總共5小時

              values.add(new TimeInfo(3, 7));//三次總共7小時

             //values作為444這個賣家的reduce輸入,

             //期望計(jì)算出平均為2小時

              reduceDriver.withReducer(reducer)

                     .withInput(new Text("444"), values)

                     //Note

                     //假設(shè)使用id(444)%8的方式來分文件

                    //表示期望"somePrefix"+444%8這個collector將搜集到數(shù)據(jù)xxx

                     . withMutiOutput ("somePrefix"+444%8,new Text("444"),new                                                     LongWritable(2))

                    .runTest();

          }

       

       

       

      MapReduceMultipleOutputDriver

               ReduceMultipleOutputsDriver類似,MapReduceMultipleOutputDriver用來支持使用了MultipleOutputsMap-Reduce聯(lián)合測試。MapReduceDriver一節(jié)中的例子將改為,

      private MapReduceDriver<LongWritable, Text, Text, TimeInfo, Text, LongWritable> mrDriver;

          private Map mapper;

          private Reduce reducer;

          @Before

          public void setUp() {

              mapper = new Map();

              reducer = new Reduce();

             //改為使用ReduceMultipleOutputsDriver

              mrDriver = new ReduceMultipleOutputsDriver<LongWritable, Text, Text,               TimeInfo, Text, LongWritable>(mapper, reducer);

          }

       

          @Test

          public void testMapReduce_3record_1user() {

             Text mapInputValue1 = new Text("……");

             Text mapInputValue2 = new Text("……");

             Text mapInputValue3 = new Text("……");

             //我們期望從以上三條Map輸入計(jì)算后,

             //reduce輸出得到444這個賣家的平均時間為2小時.

              mrDriver.withInput(null, mapInputValue1)

                 .withInput(null, mapInputValue2)

                 .withInput(null, mapInputValue3)

                 //表示期望"somePrefix"+444%8這個collector將搜集到數(shù)據(jù)xxx

                 . withMutiOutput ("somePrefix"+444%8,new Text("444"),new                                              LongWritable(2))

                 .runTest();

          }

       

       

       

      如何從文件加載輸入

               從以上例子看到使用MRUnit需要重復(fù)寫很多類似的代碼,并且需要把輸入數(shù)據(jù)寫在代碼中,顯得不是很優(yōu)雅,如果能從文件加載數(shù)據(jù)則會方便很多。因此通過使用annotation和擴(kuò)展JUnit runner,增強(qiáng)了MRUnit來解決這個問題。

             改造上面的例子,使得map的輸入自動從文件加載,并且消除大量使用MRUnit框架API的代碼。

      @RunWith(MRUnitJunit4TestClassRunner.class)

      public class XXXMRUseAnnotationTest {

       

          //表示自動初始化mrDriver,并加載數(shù)據(jù)(如果需要)

          @MapInputSet

          @MapReduce(mapper = Map.class, reducer = Reduce.class)

           private MapReduceDriver<LongWritable, Text, Text, TimeInfo, Text, LongWritable> mrDriver;

       

          @Test

          @MapInputSet("ConsignTimeMRUseAnnotationTest.txt")//從這里加載輸入數(shù)據(jù)

          public void testMapReduce_3record_1user() {

                 //只需要編寫驗(yàn)證代碼

             mrDriver. withMutiOutput ("somePrefix"+444%8,new Text("444"),new LongWritable(2))

                                       .runTest();

          }

      }

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多