TestNG源代码分析 --- 依赖管理的实现(二)
来源:互联网 发布:淘宝类目 编辑:程序博客网 时间:2024/06/05 04:02
转自: http://blog.csdn.net/dm_vincent/article/details/7641570
在上一篇文章中,留下了一些的问题:
- Graph对象中的一些字段是怎么被初始化的?在使用Graph对象的topologicalSort方法的时候,需要用到这些字段,比如m_nodes以及m_independentNodes这两个集合,它们分别存放的是所有的节点的引用以及所有独立节点的引用。
- Graph对象是如何使用的,即方法调用栈的上层是如何调用Graph中的topologicalSort方法的。
- 关于环路检测算法的实现,用于在发现循环依赖的时候,检测出具体的循环依赖路径。
本文就对上述的几个问题作出解释:
环路检测算法
先来看看算法的实现:
这里实现的实际上是Tarjan判断强连通子图的算法,因为对于有向cycle,它一定是强连通的,所以在我们的场景中使用这个算法是没问题的,但是在细节上,上面的实现存在一点小瑕疵,即最后只能maintain一个cycle,如果在依赖关系中存在多个cycle的话,是无法将它们全部记录下来的。当然,这个算法的实现是为了提示用户存在循环依赖,而不是为了输出所有的循环依赖。有兴趣的可以查看维基百科中对于Tarjan SCC算法的描述。
http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
另外,在上面的实现中,和Tarjan SCC算法的实现也不是完全一致的,比如,是对当前node的所有前驱结点进行检查,而不是像Tarjan SCC中,是对所有的可达节点进行检查。这样做也是为了加快算法的执行速度,即在存在循环依赖的情况下,尽量减少循环的次数,只需要保证至少能够检测到一个环即可。
Graph对象的初始化以及使用
我们再来回顾一下那个stacktrace:
可以发现,调用Graph中的拓扑排序方法的是MethodHelper类中的静态方法topologicalSort,而后者又被该类中的几个静态方法调用,所以,为了弄清楚Graph中的数据是如何准备的,我们需要对这个类进行探究:
MethodHelper.topologicalSort方法
以上代码的几个关键步骤:
- 对于每个ITestNGMethod对象的操作:
- 添加到Graph中,通过addNode方法
- 创建一个list,用来维护该方法依赖的方法
- 获得该方法依赖的所有方法,添加到上一步创建的list中
- 根据dependsOnMethod找到依赖方法
- 根据dependsOnGroup找到依赖方法
- 将上一步修改后的list添加到graph中,通过addPredecessor方法
- 待所有的ITestNGMethod对象都被处理完毕后,调用Graph对象的拓扑排序方法
- 如果拓扑排序没有出现错误,获取结果,分别添加到Sequential和Parallel list中
在上面的分析中,出现了SequentialList以及Parallel List这两个集合,它们分别用于顺序执行和并发执行。并发执行是TestNG中一个很重要,同时也十分新颖的功能。我们总是希望最大限度的提高程序的并发度,对于测试用例的运行,也不例外。由于硬件的发展,并发/并行计算是未来的趋势之一。TestNG中对于并发运行功能的实现,以后会有介绍。
在上一篇文章中,介绍了Graph类的工作原理,但是对于其中数据的来源和准备,当时我们暂时忽略了,那么现在我们可以详细探究一下,Graph中的数据是如何准备的:
主要通过两个方法:
addNode以及addPredecessor
由于Graph是一个泛型类,这里的参数都用T来表示类型,为了方便理解,不妨把这个T就当成TestNG中的用来表示方法的ITestNGMethod接口类型。
该方法的实现十分简单,就是向m_nodes集合中添加一个entry,注意这个entry的类型是<Method,Node<Method>>
然后我们再看看上面方法的调用者
MethodHelper.sortMethods方法
因此,在TestNG对于依赖关系检测的拓扑排序中,主要有两个功能:
- 检测依赖关系的正确性,即不存在任何形式的循环依赖
- 在保证正确性的前提下,将方法分类,分成只能顺序运行的方法以及可以并发运行的方法
以上,就是对TestNG中依赖关系相关核心代码的分析。其核心思想还是使用拓扑排序来建立依赖关系。在以后的系列文章中,还会介绍TestNG是如何实现并发运行测试方法,以及一些其他内容,比如,TestNG的几个常用的扩展点,Method Selector机制,各种Listener等等。
- TestNG源代码分析 --- 依赖管理的实现(二)
- TestNG源代码分析 --- 依赖管理的实现(二)
- TestNG源代码分析 --- 依赖管理的实现(一)
- TestNG源代码分析 --- 依赖管理的实现(一)
- 改进TestNG的测试方法依赖管理
- Struts2源代码分析(二)类ContainerImpl的实现分析
- maven的依赖分析管理
- TestNg依赖高级用法之强制依赖与顺序依赖------TestNg依赖详解(二)
- TestNG的依赖测试代码
- Android ActionBar的源代码分析(二)
- 频道管理的依赖实现
- B树的实现与源代码二(删除源代码)
- 在testng.xml文件中配置TestNG 的依赖关系
- TCPMP源代码分析(二)
- Iperf 源代码分析(二)
- Hadoop源代码分析(二)
- yaffs2源代码分析(二)
- Iperf 源代码分析(二)
- C++ 简单的 Tcp 实现[socket] 服务器端与客户端通信
- NSNotification的理解
- spring框架学习(五)注解
- 关于测试一个接口的面试题
- epoll 指向的d对象导致的gc释放问题,使用手动释放gc引用的对象
- TestNG源代码分析 --- 依赖管理的实现(二)
- Java内部类的使用小结
- Ceilometr: 8、Devstack下修改ceilometer的pipeline.yaml文件中采样频率和publisher的方法
- sybase sql 创建临时表
- 移动端的 jquery——移动端滚动条插件iScroll.js API文档
- linux系统下修改网络配置
- Android studio 打包 signauture version v2安装失败
- slice 和 substring 用法总结
- Ubuntu配置任意版本的apt-get镜像源