TestNG源码解读(二十三)

本文深入探讨TestNG源码,详细解析如何生成xml文件。从FailedReporter.java的generateFailureSuite方法开始,逐步分析writeUtf8File方法,生成指定目录下的xml文件。内容包括suiteXml、group、tests、package、classes以及IncludeXml等标签的xml生成逻辑,揭示它们之间的生成关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接着上一篇继续走查整个xml文件生成的过程

1.在FailedReporter.java中的方法generateFailureSuite最后是生成xml文件,这里的三个入参分别是输出路径,文件名,及SuiteXml

  if(null != failedSuite.getTests() && failedSuite.getTests().size() > 0) {
      Utils.writeUtf8File(outputDir, TESTNG_FAILED_XML, failedSuite.toXml();
    }

那么,方法writeUtf8File的具体实现又是什么呢?简单来说就是在目录下outputDir下生成一个内容是sb且文件名是fileName的文件

  /**
   * Writes the content of the sb string to the file named filename in outDir encoding the output as UTF-8.
   * If outDir does not exist, it is created.
   *
   * @param outputDir the output directory (may not exist). If is null then current directory is used.
   * @param fileName the filename
   * @param sb the file content
   */
  public static void writeUtf8File(@Nullable String outputDir, String fileName, String sb) 
  {
    final String outDirPath= outputDir != null ? outputDir : "";
    final File outDir= new File(outDirPath);
    writeFile(outDir, fileName, escapeUnicode(sb), "UTF-8", false /* don't append */);
  }

还是回到上一步,文件内容是怎么生成的呢?利用方法 failedSuite.toXml(),走读一下该方法的具体实现:

  /**
   * @return A String representation of this XML suite.
   */
  public String toXml() {
    XMLStringBuffer xsb = new XMLStringBuffer();
    //TESTNG_DTD
    xsb.setDocType("suite SYSTEM \"" + Parser.TESTNG_DTD_URL + '\"');
    Properties p = new Properties();
    //suiteName
    p.setProperty("name", getName());
    //suiteVerbose
    if (getVerbose() != null) {
      XmlUtils.setProperty(p, "verbose", getVerbose().toString(), DEFAULT_VERBOSE.toString());
    }
    //parallel
    final ParallelMode parallel= getParallel();
    if(parallel != null && !DEFAULT_PARALLEL.equals(parallel)) {
      p.setProperty("parallel", parallel.toString());
    }
    //thread-count
    XmlUtils.setProperty(p, "thread-count", String.valueOf(getThreadCount()),
        DEFAULT_THREAD_COUNT.toString());
    //data-provider-thread-count
    XmlUtils.setProperty(p, "data-provider-thread-count", String.valueOf(getDataProviderThreadCount()),
        DEFAULT_DATA_PROVIDER_THREAD_COUNT.toString());
    //skipfailedinvocationcounts
    XmlUtils.setProperty(p, "skipfailedinvocationcounts", m_skipFailedInvocationCounts.toString(),
        DEFAULT_SKIP_FAILED_INVOCATION_COUNTS.toString());
    //push properties
    xsb.push("suite", p);
    //配置参数,如dataProvider等
    XmlUtils.dumpParameters(xsb, m_parameters);

    //监听器
    if (hasElements(m_listeners)) {
      xsb.push("listeners");
      for (String listenerName: m_listeners) {
        Properties listenerProps = new Properties();
        listenerProps.setProperty("class-name", listenerName);
        xsb.addEmptyElement("listener", listenerProps);
      }
      xsb.pop("listeners");
    }

    //package标签
    if (hasElements(getXmlPackages())) {
      xsb.push("packages");

      for (XmlPackage pack : getXmlPackages()) {
        xsb.getStringBuffer().append(pack.toXml("    "));
      }

      xsb.pop("packages");
    }

    //groups(包括include及exclude)
    List<String> included = getIncludedGroups();
    List<String> excluded = getExcludedGroups();
    if (hasElements(included) || hasElements(excluded)) {
      xsb.push("groups");
      xsb.push("run");
      for (String g : included) {
        xsb.addEmptyElement("include", "name", g);
      }
      for (String g : excluded) {
        xsb.addEmptyElement("exclude", "name", g);
      }
      xsb.pop("run");
      xsb.pop("groups");
    }
    //生成group标签的Xml
    if (m_xmlGroups != null) {
      xsb.getStringBuffer().append(m_xmlGroups.toXml("  "));
    }
    //生成testscXml
    for (XmlTest test : getTests()) {
      xsb.getStringBuffer().append(test.toXml("  "));
    }

    xsb.pop("suite");

    return xsb.toXML();
  }

在生成suiteXml的时候会调用成功group及tests标签的xml方法,

而在test.toxml方法中又有生成<package>标签及classes标签xml的方法,

继续在生成classesXml的方法中又有生成IncludeXml的方法。

他们之间的生成关系图如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值