testng源码阅读之二
来源:互联网 发布:linux关闭selinux命令 编辑:程序博客网 时间:2024/05/12 22:33
最近一直没有时间写博客。在做一个相当于外包的项目。因为项目终于卖出去了,忽悠到人用了。而且最近释放了一个资源。
最近一直忙于测试。
testng执行核心的几个类:
xxxWorker、xxxRunner是配套的。runner的类,定义执行的上下文。Worker就是实际的执行器。
testng定义了两个层次的执行。一层是suite这个层面的。一层是每个@Test层面的。从图中可以看到。其中,testRunner,实际是跟testMethodWorker配套使用的。
我们来看一下最底层的testRunner的privateRun()
private void privateRun(XmlTest xmlTest) { String parallelMode = xmlTest.getParallel(); boolean parallel = XmlSuite.PARALLEL_METHODS.equals(parallelMode) || "true".equalsIgnoreCase(parallelMode) || XmlSuite.PARALLEL_CLASSES.equals(parallelMode) || XmlSuite.PARALLEL_INSTANCES.equals(parallelMode); { // parallel int threadCount = parallel ? xmlTest.getThreadCount() : 1; // Make sure we create a graph based on the intercepted methods, otherwise an interceptor // removing methods would cause the graph never to terminate (because it would expect // termination from methods that never get invoked). DynamicGraph<ITestNGMethod> graph = createDynamicGraph(intercept(m_allTestMethods)); if (parallel) { if (graph.getNodeCount() > 0) { GraphThreadPoolExecutor<ITestNGMethod> executor = new GraphThreadPoolExecutor<ITestNGMethod>(graph, this, threadCount, threadCount, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); executor.run(); try { long timeOut = m_xmlTest.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS); Utils.log("TestRunner", 2, "Starting executor for test " + m_xmlTest.getName() + " with time out:" + timeOut + " milliseconds."); executor.awaitTermination(timeOut, TimeUnit.MILLISECONDS); executor.shutdownNow(); } catch (InterruptedException handled) { handled.printStackTrace(); Thread.currentThread().interrupt(); } } } else { boolean debug = false; List<ITestNGMethod> freeNodes = graph.getFreeNodes(); if (debug) { System.out.println("Free nodes:" + freeNodes); } if (graph.getNodeCount() > 0 && freeNodes.isEmpty()) { throw new TestNGException("No free nodes found in:" + graph); } while (! freeNodes.isEmpty()) { List<IWorker<ITestNGMethod>> runnables = createWorkers(freeNodes); for (IWorker<ITestNGMethod> r : runnables) { r.run(); } graph.setStatus(freeNodes, Status.FINISHED); freeNodes = graph.getFreeNodes(); if (debug) { System.out.println("Free nodes:" + freeNodes); } } } } }
可以看到,对于多线程跟普通单线程是有不同的处理的。先来简单说说单线程的处理。重点在于 freenodes的获取。获取到所有的freenodes,并根据freenodes,得到对应的testmethods, 然后执行 .反复递归执行,直到所有xmltest的nodes执行完。 所以先来看看freenodes是如何得来的:
DynamicGraph<ITestNGMethod> graph = createDynamicGraph(intercept(m_allTestMethods));
第一步,先得到动态的节点图:
private DynamicGraph<ITestNGMethod> createDynamicGraph(ITestNGMethod[] methods) { DynamicGraph<ITestNGMethod> result = new DynamicGraph<ITestNGMethod>(); result.setComparator(new Comparator<ITestNGMethod>() { @Override public int compare(ITestNGMethod o1, ITestNGMethod o2) { return o1.getPriority() - o2.getPriority(); } }); DependencyMap dependencyMap = new DependencyMap(methods); // Keep track of whether we have group dependencies. If we do, preserve-order needs // to be ignored since group dependencies create inter-class dependencies which can // end up creating cycles when combined with preserve-order. boolean hasDependencies = false; for (ITestNGMethod m : methods) { result.addNode(m); @retinder-->这里先把所有的测试方法加载进来。然后按照指定的规则计算 // Dependent methods //@retinder-->保存测试方法,对应的依赖方法 { String[] dependentMethods = m.getMethodsDependedUpon(); if (dependentMethods != null) { for (String d : dependentMethods) { ITestNGMethod dm = dependencyMap.getMethodDependingOn(d, m); if (m != dm){ result.addEdge(m, dm); } } } } // Dependent groups //如果是所属的测试集(class)存在依赖的测试集,那么把依赖的测试集的多有的测试方法,加入到当前方法的依赖方法。 { String[] dependentGroups = m.getGroupsDependedUpon(); for (String d : dependentGroups) { hasDependencies = true; List<ITestNGMethod> dg = dependencyMap.getMethodsThatBelongTo(d, m); if (dg == null) { throw new TestNGException("Method \"" + m + "\" depends on nonexistent group \"" + d + "\""); } for (ITestNGMethod ddm : dg) { result.addEdge(m, ddm); } } } } // Preserve order // Don't preserve the ordering if we're running in parallel, otherwise the suite will // create multiple threads but these threads will be created one after the other, // giving the impression of parallelism (multiple thread id's) while still running // sequentially. @retinder-->这里的注释提到,如果在多线程模式下,设置Preserve order是会使人感觉是跟单线程一样的。因为 必须先启动线程执行依赖的方法,然后启动另外的线程执行后边的测试方法。 @retinder-->这里实际上就是这样。如果是单线程模式下,指定了Preserve order,按照A-B这种顺序执行,实际上会 转化为depency的方式,即B中所有的测试方法,都会依赖A中的测试方法。这样在执行的时候,就会确保A执行完了,才执行B。 同理如果在注释里边进行了分组 if (! hasDependencies && ! XmlSuite.isParallel(getCurrentXmlTest().getParallel()) && "true".equalsIgnoreCase(getCurrentXmlTest().getPreserveOrder())) { // If preserve-order was specified and the class order is A, B // create a new set of dependencies where each method of B depends // on all the methods of A ListMultiMap<ITestNGMethod, ITestNGMethod> classDependencies = createClassDependencies(methods, getCurrentXmlTest()); for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : classDependencies.getEntrySet()) { for (ITestNGMethod dm : es.getValue()) { result.addEdge(dm, es.getKey()); } } } // Group by instances @retinder-->如果设置了group-by-instances. if (getCurrentXmlTest().getGroupByInstances()) { ListMultiMap<ITestNGMethod, ITestNGMethod> instanceDependencies = createInstanceDependencies(methods, getCurrentXmlTest()); for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : instanceDependencies.getEntrySet()) { for (ITestNGMethod dm : es.getValue()) { result.addEdge(dm, es.getKey()); } } } return result; }
PS:这里其实有个问题,我看代码,所谓的group-by-instance,跟普通的depency并没有太大的区别。感觉的得到的是一样的执行顺序。这里实在看不下去。先挖个坑,以后慢慢填。
最后得到一个像上边这个一样的图。
然后不被依赖的,都会先执行,递归,直到所有的方法被执行完。
关于privateMain的具体流程,我打算在之三写,虽然这个博客也并没有人在看,哈哈。不过既然开了头,那就把它完成了。
阅读全文
0 0
- testng源码阅读之二
- testng源码阅读之三
- testng源码阅读之四
- testng源码阅读之5
- testng源码阅读之6
- testng源码阅读之读后感
- testng源码阅读之入口在哪
- testng源码阅读之多线程包
- JDK源码阅读之二-----String
- Okhttp源码阅读之旅(二)
- kubernetes源码阅读之kubelet(二)
- JDK8源码阅读之File(二)
- testng翻译之二--注解
- Xwork2 源码阅读(二)
- live555源码阅读二
- 源码阅读(二)
- OSCache源码阅读(二)
- Log4j源码阅读二
- 使用RxPermissions(基于RxJava2) 处理安卓权限(转载的不好意思)
- jQuery字符串替换(全部)
- 20171107
- JAVA异常之异常处理
- SQL语句查询最近几天,几个小时的数据的写法
- testng源码阅读之二
- List / Map / Collections方法
- oracle创建用户、表空间、授权
- 2.live555源码分析----服务端doEventLoop()函数分析
- 如何清除页面的图片缓存
- java缓存技术
- git-note
- Retrofit 网络请求
- error installing apk