背景
从使用hadoop的第一天开始,就一直没有离开过对Hadoop自身功能的开发以及hadoop本身bug的修复的相关开发。这样的开发模式已经持续了好几年,但是可以从中发现的一个现象:对于我们修复的bug或者开发的功能,一直都没有一种很规范,很统一,高效,好管理,并且一目了然的测试的方式。常常的现象是:开发了一个功能或修复了一个bug后,就针对该修改进行一些人为手动的环境模拟和测试,然后测试确认没有问题以后,就合入基线版本进行打包上线。这种模式的缺点是:
- 1. 没有统一的测试框架和测试规范,很容易导致做一次修改,就需要认为的搭建或模拟一些针对该修改的现象进行测试,而这次测试完成后,环境撤掉,又没有形成相应的文档,导致后续进行版本发布的时候,无法进行回归测试。
- 2. 测试环境的模拟取决于进行测试的人员自身的考虑。所以对同一个修改的测试,隔一段时间以后换一个人测,方式和结果可能大相径庭。
- 3. 对于一些性能相关的测试,没有相应的性能测试工具,这样很容易导致对于运行了很长时间的集群,没有人能够准确的说出集群的各种性能指标。对于以后的改进和优化,也无法量化优化和改进的效果数据,很难进行评估。
- 4. 开发人员跟测试人员通常是同一个人。
其实,hadoop每个版本都包含有很多功能和改进所对应的测试代码,每个版本发布,或者每个patch合入的时候,都会将所有的测试用例进行一次完整的回归,这样可以确保修改不会影响到其他的模块或其他的功能。所以对hadoop测试相关的了解其实跟对hadoop本身代码的了解以及后续的开发,其实同样重要。
本文接下来的部分会对目前hadoop中测试相关的框架和结构进行简单介绍,并会在介绍后提供一些例子,以展示如何对hadoop的内核开发进行测试代码的编写。
0.21以前的版本
目录结构
在hadoop 0.21以前的版本中(这里拿0.20为例,其他版本可能有少许不同),所有的测试相关代码都是放置在${HADOOP_HOME}/src/test下,在该目录下,是按照不同的目录来区分针对不同模块的测试代码。这里需要了解的是:对于相应的hadoop代码和class的包结构,在test中也是以相同的包结构来管理。比如,对于org.apache.hadoop.hdfs.server.namenode中的代码,其源码在src/hdfs/org/apache/hadoop/hdfs/server/namenode中,其测试用例的代码就位于:/src/test/org/apache/hadoop/hdfs/server/namenode内。其他模块以此类推。
测试用例结构
以hdfs为例,对于不需要集群环境的测试,其测试代码就跟寻常的单元测试代码一样,无非是程序级别的一些验证和assert,跟一般的测试用例代码没有什么区别。
MiniDFSCluster
若需要模拟HDFS集群环境,但有没有真是的集群情况下,hadoop测试代码中提供了一个MiniDFSCluster的类,这个类提供了一个本机单进程的hdfs集群环境,用来模拟对hdfs集群环境的模拟。在对该类进行初始化时,程序会根据构造函数参数来设置集群环境下相应的关键配置和参数设置,比如:dfs.name.dir,dfs.data.dir,fs.checkpoint.dir,fs.default.name(这里会设置为hdfs://localhost:port,相当于一个一台机器的hdfs分布式环境),同时会根据从参数获取的datanode数来初始化一些datanode,这样一个真实的分布式环境就能构建出来,如果对某项功能的测试中需要设置相应的namenode或datanode配置参数,只需对构造函数参数中的conf对象进行set即可。
Example
这里拿TestDFSRename用例来做example:
- 构建MiniDFSCluster环境,所以在testcase的setup()中如下初始化hdfs cluster
- 获取DistributeFileSystem实例:
- 编写自己的testRename()方法。
运行testcase
在IDE中调试运行
通常对于这种单元测试的testcase,都是可以在开发环境的IDE中直接运行,如下如所示:
更多详细信息,请您微信关注“计算网”公众号: