设定
要开始使用,请从此处下载MRUnit。 解压缩tar文件后,将cd插入mrunit-0.9.0-incubating / lib目录。 在其中,您应该看到以下内容:
- mrunit-0.9.0-incubating-hadoop1.jar
- 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样式,这增加了创建测试的便利性。 要编写测试,您将:
- 实例化完全与被测映射器参数化的MapDriver类的实例。
- 在withMapper调用中添加要测试的Mapper实例。
- 在withInput调用中,输入您的键和输入值,在这种情况下,一个LongWritable具有任意值和一个Text对象,该对象包含来自NCDC天气数据集的行,该数据集包含在名为“ temps”的字符串数组中,该数组早些时候在其中建立。测试(此处不会显示,因为它会从演示文稿中删除)。
- 在withOutput调用中指定期望的输出,这里我们期望一个Text对象的值为“ 190101”,一个TemperatureAveragingPair对象的值为-61(温度)和1(计数)。
- 最后一个调用runTest将指定的输入值输入到映射器中,并将实际输出与“ withOutput”方法中设置的预期输出进行比较。
要注意的一件事是MapDriver每次测试仅允许一个输入和输出。 您可以根据需要多次调用withInput和withOutput,但是MapDriver会用新值覆盖现有值,因此您将只能在任何时候使用一个输入/输出进行测试。 为了指定多个输入,我们将使用MapReduceDriver,稍后将介绍几节,但接下来将测试reducer。
测试减速器
测试减速器遵循与映射器测试相同的模式。 再次,让我们看一个代码示例:
@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();}
- 该测试首先创建一个TemperatureAveragingPair对象列表,用作减速器的输入。
- 实例化了ReducerDriver,并且与MapperDriver一样,对它的参数设置也与被测试的reducer完全相同。
- 接下来,我们要在withReducer调用中传入要测试的reducer实例。
- 在withInput调用中,我们传入键“ 190101”和在测试开始时创建的pairList对象。
- 接下来,我们指定我们期望减速器发出的输出,相同的键“ 190101”和一个IntWritable,它表示列表中的温度平均值。
- 最后调用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允许我们传递具有不同键的多个输入。 此处的“温度”数组与Mapper样本中引用的数组相同,并包含NCDC天气数据集中的几行内容,这些样本行中的关键字为1901年1月和2月,分别表示为“ 190101”和“ 190102“。 该测试是成功的,因此我们对映射器和化简器一起工作的正确性有了更多的信心。
结论
希望我们已经证明了MRUnit对于测试Hadoop程序有多么有用。 我想用我自己的一些观点来总结这篇文章。 尽管MRUnit使映射器和化简器代码的单元测试变得容易,但是这里介绍的映射器和化简器示例相当简单。 如果您的映射和/或精简代码开始变得更加复杂,则最好将代码与Hadoop框架解耦,然后单独测试新类。 另外,与MapReduceDriver类一样,它用于集成测试也非常有用,很容易达到不再测试代码,而已经测试Hadoop框架本身的地步。 我提出了自己打算继续使用的测试策略:
- 单元测试映射/减少代码。
- 可能使用MapReduceDriver类编写一个集成测试。
- 作为健全性检查,请在单节点安装(在我的笔记本电脑上)上运行MapReduce作业,以确保其在Hadoop框架上运行。
- 然后在我的案例中,使用Apache Whirr在EC2的测试集群上运行我的代码。
讨论如何在笔记本电脑(OSX Lion)上设置单节点安装以及如何使用Whirr在EC2上建立群集将使这篇文章过长,因此我将在下一篇文章中介绍这些主题。 谢谢你的时间。
资源资源
- Jimmy Lin和Chris Dyer 使用MapReduce进行的数据密集型处理
- Hadoop: Tom White 的权威指南
- 来自博客的源代码
- Hadoop API
- MRUnit用于单元测试Apache Hadoop映射减少工作
- Gutenberg项目提供了大量纯文本格式的书籍,非常适合在本地测试Hadoop作业。
参考:来自我们的JCG合作伙伴 Bill Bejeck的《 Random Thoughts On Coding》博客中的MRUnit测试Hadoop程序 。
翻译自: https://www.javacodegeeks.com/2012/11/testing-hadoop-programs-with-mrunit.html