mrunit_使用MRUnit测试Hadoop程序

本文介绍了如何使用MRUnit进行Hadoop程序的单元测试,包括设置MRUnit库,测试映射器和减速器,以及进行集成测试。MRUnit简化了映射器和减速器的测试,但也提醒在复杂场景下应考虑解耦代码并独立测试。
摘要由CSDN通过智能技术生成

mrunit

这篇文章将略微绕开使用MapReduce实现数据密集型处理中发现的模式以讨论同样重要的测试。 汤姆•惠勒Tom Wheeler)在纽约2012年Strata / Hadoop World会议上参加的一次演讲给了我部分启发。 当处理大型数据集时,想到的并不是单元测试。 但是,当考虑到无论集群有多大或有多少数据时,都将相同的代码推送到所有节点以运行MapReduce作业,因此Hadoop映射器和化简器非常适合进行单元测试。 但是,对框架进行Hadoop的单元测试并不容易。 幸运的是,有一个使Hadoop测试相当容易的库– MRUnit 。 MRUnit基于JUnit并允许对映射器,化简器进行单元测试以及对映射器进行一些有限的集成测试-归化器与组合器,自定义计数器和分区器之间的交互。 在撰写本文时,我们正在使用最新版本的MRUnit 0.9.0。 所有测试的代码均来自上一则有关使用本地聚合计算平均值的文章

建立

要开始使用,请从此处下载MRUnit。 解压缩tar文件后,将cd插入mrunit-0.9.0-incubating / lib目录。 在其中,您应该看到以下内容:

  1. mrunit-0.9.0-incubating-hadoop1.jar
  2. mrunit-0.9.0-incubating-hadoop2.jar

我敢肯定,mrunit-0.9.0-incubating-hadoop1.jar用于Hadoop的MapReduce版本1,mrunit-0.9.0-incubating-hadoop2.jar用于处理Hadoop的新版本的MapReduce。 对于本文以及其他所有后续文章,我们将使用Cloudera CDH4.1.1发行版中的hadoop-2.0版本,因此我们需要mrunit-0.9.0-incubating-hadoop2.jar文件。 我在Intellij中将MRUnit,JUnit和Mockito添加为库(JUnit和Mockito与MRUnit jar文件位于同一目录中)。 现在我们已经建立了依赖关系,让我们开始测试。

测试映射器

设置测试映射器非常简单,最好先查看一些代码来说明。 我们将使用上一篇文章中的映射器内合并示例:

@Test
public void testCombiningMapper() throws Exception {
   new MapDriver<LongWritable,Text,Text,TemperatureAveragingPair>()
           .withMapper(new AverageTemperatureCombiningMapper())
           .withInput(new LongWritable(4),new Text(temps[3]))
           .withOutput(new Text('190101'),new TemperatureAveragingPair(-61,1))
           .runTest();
 }

注意流利的api样式,这增加了创建测试的难度。 要编写测试,您将:

  1. 实例化完全与被测映射器参数化的MapDriver类的实例。
  2. 在withMapper调用中添加要测试的Mapper实例。
  3. 在withInput调用中,输入您的键和输入值,在这种情况下,一个LongWritable具有任意值和一个Text对象,其中包含来自NCDC天气数据集的行,该数据集包含在名为“ temps”的字符串数组中,该数组早先在2000年建立。测试(此处不会显示,因为它会脱离演示文稿)。
  4. 在withOutput调用中指定期望的输出,在这里我们期望一个Text对象的值为“ 190101”,一个TemperatureAveragingPair对象的值为-61(温度)和1(计数)。
  5. 最后一个调用runTest将指定的输入值输入到映射器中,并将实际输出与“ withOutput”方法中设置的预期输出进行比较。

需要注意的一件事是,MapDriver每次测试仅允许一个输入和输出。 您可以根据需要多次调用withInput和withOutput,但是MapDriver会用新值覆盖现有值,因此您将只能在任何时间使用一个输入/输出进行测试。 要指定多个输入,我们将使用MapReduceDriver,稍后将介绍几节,但接下来将测试化简器。

测试减速器

测试减速器遵循与映射器测试相同的模式。 再次,让我们开始看一个代码示例:

@Test
public void testReducerCold(){
  List<TemperatureAveragingPair> pairList = new ArrayList<TemperatureAveragingPair>();
      pairList.add(new TemperatureAveragingPair(-78,1));
      pairList.add(new TemperatureAveragingPair(-84,1));
      pairList.add(new TemperatureAveragingPair(-28,1));
      pairList.add(new TemperatureAveragingPair(-56,1));

      new ReduceDriver<Text,TemperatureAveragingPair,Text,IntWritable>()
                .withReducer(new AverageTemperatureReducer())
                .withInput(new Text('190101'), pairList)
                .withOutput(new Text('190101'),new IntWritable(-61))
                .runTest();
    }
  1. 该测试首先创建一个TemperatureAveragingPair对象列表,以用作减速器的输入。
  2. 实例化了ReducerDriver,并且与MapperDriver一样,对它的参数设置也与被测试的reducer完全一样。
  3. 接下来,我们传递要在withReducer调用中测试的reducer实例。
  4. 在withInput调用中,我们传入键“ 190101”和在测试开始时创建的pairList对象。
  5. 接下来,我们指定我们期望减速器发出的输出,相同的键“ 190101”和一个IntWritable,它表示列表中的温度平均值。
  6. 最终调用runTest,它将为我们的减速器提供指定的输入,并将减速器的输出与期望输出进行比较。

ReducerDriver具有与MapperDriver相同的限制,即不接受多个输入/输出对。 到目前为止,我们已经单独测试了Mapper和Reducer,但我们也想在集成测试中一起测试它们。 可以通过使用MapReduceDriver类来完成集成测试。 MapReduceDriver还是用于测试组合器,自定义计数器或自定义分区程序使用情况的类。

整合测试

为了测试您的mapper和reducer一起工作,MRUnit提供了MapReduceDriver类。 如您现在所期望的,MapReduceDriver类有两个主要区别。 首先,参数化映射器的输入和输出类型以及化简器的输入和输出类型。 由于映射器输出类型需要与化简器输入类型匹配,因此最终需要3对参数化类型。 其次,您可以提供多个输入并指定多个预期输出。 这是我们的示例代码:

@Test
public void testMapReduce(){

new MapReduceDriver<LongWritable,Text,
                      Text,TemperatureAveragingPair,
                      Text,IntWritable>()
                .withMapper(new AverageTemperatureMapper())
                .withInput(new LongWritable(1),new Text(temps[0]))
                .withInput(new LongWritable(2),new Text(temps[1]))
                .withInput(new LongWritable(3),new Text(temps[2]))
                .withInput(new LongWritable(4),new Text(temps[3]))
                .withInput(new LongWritable(5),new Text(temps[6]))
                .withInput(new LongWritable(6),new Text(temps[7]))
                .withInput(new LongWritable(7),new Text(temps[8]))
                .withInput(new LongWritable(8),new Text(temps[9]))
                .withCombiner(new AverageTemperatureCombiner())
                .withReducer(new AverageTemperatureReducer())
                .withOutput(new Text('190101'),new IntWritable(-22))
                .withOutput(new Text('190102'),new IntWritable(-40))
                .runTest();
    }

从上面的示例中可以看到,设置与MapDriver和ReduceDriver类相同。 您传入映射器,reducer和(可选)组合器的实例进行测试。 MapReduceDriver允许我们传递具有不同键的多个输入。 此处的“临时”数组与在映射器示例中引用的数组相同,并包含来自NCDC天气数据集的几行,而这些示例行中的键是1901年1月和2月的月份,分别表示为“ 190101”和“ 190102“。 该测试是成功的,因此我们对映射器和化简器一起工作的正确性有了更多的信心。

结论

希望我们已经证明了MRUnit对于测试Hadoop程序有多么有用。 我想用我自己的一些观点来总结这篇文章。 尽管MRUnit使映射器和化简器代码的单元测试变得容易,但是这里介绍的映射器和化简器示例相当简单。 如果您的映射和/或精简代码开始变得更加复杂,则最好将代码与Hadoop框架解耦,然后单独测试新类。 另外,与MapReduceDriver类一样,它对于集成测试非常有用,很容易达到不再测试代码,而已经测试Hadoop框架本身的地步。 我提出了自己打算继续使用的测试策略:

  1. 单元测试映射/减少代码。
  2. 可能使用MapReduceDriver类编写一个集成测试。
  3. 作为一个健全性检查,请在单节点安装(在我的笔记本电脑上)上运行MapReduce作业,以确保其在Hadoop框架上运行。
  4. 然后,在我的案例中,使用Apache Whirr在EC2的测试集群上运行我的代码。

讨论如何在笔记本电脑(OSX Lion)上设置单节点安装以及如何使用Whirr在EC2上建立群集将使这篇文章过长,因此我将在下一篇文章中介绍这些主题。 谢谢你的时间。

资源资源


参考:随机编码》博客上的JCG合作伙伴 Bill Bejeck的《 使用MRUnit测试Hadoop程序》

翻译自: https://www.javacodegeeks.com/2012/11/testing-hadoop-programs-with-mrunit.html

mrunit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值