testng的分析一

本文详细剖析了TestNG的执行流程,从设置监听器、初始化配置到运行测试类的过程。核心在于`initializeCommandLineSuites()`方法,此处将testclass加入suite中。通过创建线程并运行suite,实现测试执行。对于理解TestNG的工作机制非常有帮助。
摘要由CSDN通过智能技术生成

运行的代码是 自己设置listener, test class 设置是.class, 看看这个是testng run的路线

	TestListenerAdapter testListenerAdapter = new TestListenerAdapter();
    TestNG testNG = new TestNG();
    testNG.setTestClasses(new Class[]{test2.class});
    testNG.addListener(testListenerAdapter);
    testNG.run();
    List<ITestResult> testresults =testListenerAdapter.getPassedTests();
    System.out.println(testresults.get(0).getStatus());

testNG.ru()
then we will enter TestNG 的方法,进入 这个方法之前,我们已经将testclass传入了testng对像,但是未设置testsuite。
问题,testclass什么时候会被testng使用,并且会传给什么对象去处理。

public void run() {
    initializeSuitesAndJarFile();
    initializeConfiguration();
    initializeDefaultListeners();
    initializeCommandLineSuites();
    initializeCommandLineSuitesParams();
    initializeCommandLineSuitesGroups();
    sanityCheck();
    List<ISuite> suiteRunners = null;

    runExecutionListeners(true /* start */);
    //
    // Regular mode
    //
    else if (m_masterfileName == null) {
      suiteRunners = runSuitesLocally();
    }
    //
    // Master mode
    //  

initializeSuitesAndJarFile() 主要是设置 m_jatPath ,m_suites.。 在我们的例子中,没有suite,也未设置jar path , 所以两个都是0.
initializeConfiguration()

  • Install the listeners found in ServiceLoader (or use the class
    loader for tests, if specified).
  • Install the listeners found in the suites
  • Install the method selectors ???
  • Find if we have an object factory
    下面是设置一些其他的
m_configuration.setAnnotationFinder(new JDK15AnnotationFinder(getAnnotationTransformer()));
m_configuration.setHookable(m_hookable);
m_configuration.setConfigurable(m_configurable);
m_configuration.setObjectFactory(factory);

接下来是进入runseiteslocally, 我们知道之前返回的m_suite是空的,至少在initialsuiteandjar时候是空的。

 public List<ISuite> runSuitesLocally() {
    SuiteRunnerMap suiteRunnerMap = new SuiteRunnerMap();
    if (m_suites.size() > 0) {
      if (m_suites.get(0).getVerbose() >= 2) {
        Version.displayBanner();
      }

运行到这里,我发现这个m_suites并不为空,说明前面那个步骤必然是将test.class加入了testsuite中。我们发现,执行到 initializeCommandLineSuitesParams();这时候 suite就不为0了,可见suute的初始化在这个函数中做掉了。

private void initializeCommandLineSuites() {
    if (m_commandLineTestClasses != null || m_commandLineMethods != null) {
      if (null != m_commandLineMethods) {
        m_cmdlineSuites = createCommandLineSuitesForMethods(m_commandLineMethods);
      }
      else {
        m_cmdlineSuites = createCommandLineSuitesForClasses(m_commandLineTestClasses);
      }

      for (XmlSuite s : m_cmdlineSuites) {
        for (XmlTest t : s.getTests()) {
          t.setPreserveOrder(m_preserveOrder ? "true " : "false");
        }
        m_suites.add(s);
        if (m_groupByInstances != null) {
          s.setGroupByInstances(m_groupByInstances);
        }
      }
    }
  }

发现,m_commandLineTestClasses 就是 com.test.test2, 因此会仅需执行,这里我们的m_commandLineMethods 是为null的,
所以最终会调用,
m_cmdlineSuites = createCommandLineSuitesForClasses(m_commandLineTestClasses);
接着会被m_suites加入到list中。

有了suite之后,我们再回到runsuitelocally()
加下来就是创建线程去run这些worker.

public List<ISuite> runSuitesLocally() {
    SuiteRunnerMap suiteRunnerMap = new SuiteRunnerMap();
    if (m_suites.size() > 0) {
      if (m_suites.get(0).getVerbose() >= 2) {
        Version.displayBanner();
      }

      // First initialize the suite runners to ensure there are no configuration issues.
      // Create a map with XmlSuite as key and corresponding SuiteRunner as value
      for (XmlSuite xmlSuite : m_suites) {
        createSuiteRunners(suiteRunnerMap, xmlSuite);
      }

      //
      // Run suites
      //
      if (m_suiteThreadPoolSize == 1 && !m_randomizeSuites) {
        // Single threaded and not randomized: run the suites in order
        for (XmlSuite xmlSuite : m_suites) {
          runSuitesSequentially(xmlSuite, suiteRunnerMap, getVerbose(xmlSuite),
              getDefaultSuiteName());
        }
      } else {
        // Multithreaded: generate a dynamic graph that stores the suite hierarchy. This is then
        // used to run related suites in specific order. Parent suites are run only
        // once all the child suites have completed execution
        DynamicGraph<ISuite> suiteGraph = new DynamicGraph<ISuite>();
        for (XmlSuite xmlSuite : m_suites) {
          populateSuiteGraph(suiteGraph, suiteRunnerMap, xmlSuite);
        }

        IThreadWorkerFactory<ISuite> factory = new SuiteWorkerFactory(suiteRunnerMap,
          0 /* verbose hasn't been set yet */, getDefaultSuiteName());
        GraphThreadPoolExecutor<ISuite> pooledExecutor =
          new GraphThreadPoolExecutor<ISuite>(suiteGraph, factory, m_suiteThreadPoolSize,
          m_suiteThreadPoolSize, Integer.MAX_VALUE, TimeUnit.MILLISECONDS,
          new LinkedBlockingQueue<Runnable>());

        Utils.log("TestNG", 2, "Starting executor for all suites");
        // Run all suites in parallel
        pooledExecutor.run();
        try {
          pooledExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
          pooledExecutor.shutdownNow();
        }
        catch (InterruptedException handled) {
          Thread.currentThread().interrupt();
          error("Error waiting for concurrent executors to finish " + handled.getMessage());
        }
      }
    }
    e

    //
    // Generate the suites report
    //
    return Lists.newArrayList(suiteRunnerMap.values());
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值