自动化测试之路-TestNG源码分析之启动参数(1)

TestNG的启动有两种方式:

1、命令行模式,在IDEA中也是通过该方式执行的

java org.testng.TestNg ***.xml

2、new TestNG() 的实例,通过run()方法执行,使用该方式执行需要注意并不会执行configure方法,所以要求在run之前设置好参数,有些是私有参数就需要通过反射等方式进行设置,此方式扩展性更高,需要对TestNG做扩展或二次开发时,可以有效控制TestNG

TestNG的启动

 /**
   * The TestNG entry point for command line execution.
   *
   * @param argv the TestNG command line parameters.
   */
  public static void main(String[] argv) {
    TestNG testng = privateMain(argv, null);
    System.exit(testng.getStatus());
  }

命令行启动会找到org.testng.TestNg类中的main方法启动。

在main方法中调用了privateMain方法。

/**
   * <B>Note</B>: 此方法不是公共 API 的一部分,仅供内部使用.
   */
  public static TestNG privateMain(String[] argv, ITestListener listener){
    ....
    
    //
    // Parse the arguments
    //
    try {
      CommandLineArgs cla = new CommandLineArgs();

      m_jCommander = new JCommander(cla);
      m_jCommander.parse(argv);
      validateCommandLineParameters(cla);
      result.configure(cla);
    } catch (ParameterException ex) {
      exitWithError(ex.getMessage());
    }
    ....
}

privateMain方法中主要做的一个事情就是使用了jcommander对命令行的解析校验和配置。

在这里从CommandLineArgs类中罗列一下Testng支持的命令行参数:

  /**
    testng 启动suite的文件,可填写多个
  */
  @Parameter(description = "The XML suite files to run")
  public List<String> suiteFiles = Lists.newArrayList();

常见命令如:java org.testng.TestNG testng1.xml [testng2.xml testng3.xml ...] 

继续跟踪suiteFiles发现只有两处在使用

1652行是在privateMain方法中 validateCommandLineParameters(cla);执行的。

用来校验在命令行中我们是否设置了可执行用例

(可执行用例的文件有4种设置方式:-testcalass,-testjar,-methods 和上面的***.xml的方式,4种方式是如何执行的,我们后面讲)

1463行和1464行是在privateMain方法中 result.configure(cla);执行的。

设置TestNG需要执行的suite文件

  public static final String LOG = "-log";
  public static final String VERBOSE = "-verbose";
  
/**
    其实就是日志的冗余级别。官方文档中解释数字越大,表示日志打的越详细。
*/
  @Parameter(
      names = {LOG, VERBOSE},
      description = "Level of verbosity")
  public Integer verbose;

这个值可以指定-1~10的范围。10为最详细模式,默认为1.

注意:可以从下面代码可以看出,在命令行中使用-log/-verbose会将testng.xml中设置的verbose参数给覆盖

/**
   * @return the verbose level, checking in order: the verbose level on the suite, the verbose level
   *     on the TestNG object, or 1.
   */
  private int getVerbose(XmlSuite xmlSuite) {
    return xmlSuite.getVerbose() != null
        ? xmlSuite.getVerbose()
        : (m_verbose != null ? m_verbose : DEFAULT_VERBOSE);
  }

一般在扩展TestNG时用的较多,平时编写自动化用例更多的还是关注在业务层面,想要看的话调试时在idea中设置启动参数即可。

命令行中可以使用:

java org.testng.TestNg ***.xml -log 10
java org.testng.TestNg ***.xml -verbose 8
  @Parameter(names = GROUPS, description = "Comma-separated list of group names to be run")
  public String groups;

 看名称可以看出就是我们设置的组名称。

1541行是已标记为废弃的方法,可以忽略。

1664行也是privateMain方法中 validateCommandLineParameters(cla);执行的,主要还是用于校验是否为空。

1338行是用来设置我们需要执行的组。可以看代码是吧字符串根据','split为数组存储的

/**
   * Define which groups will be included from this run.
   *
   * @param groups A list of group names separated by a comma.
   */
  public void setGroups(String groups) {
    m_includedGroups = Utils.split(groups, ",");
  }

命令行中可使用

java org.testng.TestNg ***.xml -groups myGroup1,myGroup2
  public static final String EXCLUDED_GROUPS = "-excludegroups";

  /**
   不执行的组
  */
  @Parameter(
      names = EXCLUDED_GROUPS,
      description = "Comma-separated list of group names to " + " exclude")
  public String excludedGroups;
-excludegroups和-groups正好相反,TestNG执行时会排除这些组的测试用例。

在这里就会有个测试用例出现:-groups和-excludegroups填写了相同的组,是执行呢还是不执行呢。通过追查源码路径:

TestNG.runSuitesLocally 方法中初始化了SuiteRunners, 初始化SuiteRunner时又初始化了TestRunner,在TestRunner初始化时执行了initMethods方法,该方法中对

-beforeClassMethods,testMethods,afterClassMethods,

-beforSuiteMethods,afterSuiteMethods,

-beforXmlTestMethods,afterXmlTestMethods.

7个生命周期中需要执行的用例进行了统计。

 可以从代码中看出,他们都是调用了MethodHelper.collectAndOrderMethods方法,但此时的m_excludedMethods还是一个空列表。

在MethodHelper.collectAndOrderMethods中直接调用了MethodGroupsHelper.collectMethodsByGroup方法,

可以从源码中看到,排序的方法都是includedMethods的对象,没有用到outExcludedMethods,此时只需要知道included里有没有排除组的方法就知道了。

通过跟踪代码

MethodGroupsHelper.collectMethodsByGroup -> MethodGroupsHelper.includeMethod -> 
runInfo.includeMethod

一直追到XmlMethodSelector类中includeMethodFromIncludeExclude方法中有一段源码

在这可以看到有个判断,必须在includedGroups并且不在excludedGroups中才会返回true,

所以可以得出结论:

 -groups和-excludegroups填写了相同的组,会被排除,不被执行。

  public static final String OUTPUT_DIRECTORY = "-d";

  @Parameter(names = OUTPUT_DIRECTORY, description = "Output directory")
  public String outputDirectory;

-d 就是输出测试报告的目录,不填写会默认:test-output

  

  public static final String JUNIT = "-junit";

  @Parameter(names = JUNIT, description = "JUnit mode")
  public Boolean junit = Boolean.FALSE;

  public static final String MIXED = "-mixed";

  @Parameter(
      names = MIXED,
      description =
          "Mixed mode - autodetect the type of current test"
              + " and run it with appropriate runner")
  public Boolean mixed = Boolean.FALSE;

-junit 默认为false, 开启会强制走Junit执行测试用例

-mixed 默认为false,开启会判断当前用例是否是Junit用例,是则走Junit执行,否则TestNG执行

在JUnitTestFinder中可以看到TestNG支持Junit3/4,根据包名判断是调用哪个Junit的方法。

在判断是否是Junit3测试用例中:

1、 类是否是junit.framework.Test或它的子类,并且其中有1个方法是以test开头的。

2、类中是否有suite方法,并且该方法返回的类是junit.framework.Test或它的子类。

 在判断是否是Junit4测试用例中:

1、测试类有org.junit.runner.RunWith的注解或继承它的注解。

2、类中有测试方法的注解有org.junit.Test的注解或继承它的注解

先说到这,下篇再继续!! 


版权声明:本文为g877502087原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。