初识TestNG
TestNG框架的核心类就是org.testng.TestNG这个类,从类的注释中我们可以很清楚的了解到如下内容:
This class is the main entry point for running tests in the TestNG framework. Users can create their own TestNG object and invoke it in many different ways:
On an existing testng.xml
On a synthetic testng.xml, created entirely from Java
By directly setting the test classes
You can also define which groups to include or exclude, assign parameters, etc…
The command line parameters are:
-d outputdir: specify the output directory
-testclass class_name: specifies one or several class names
-testjar jar_name: specifies the jar containing the tests
-sourcedir src1;src2: ; separated list of source directories (used only when javadoc annotations are used)
-target
-groups
-testrunfactory
-listener
Please consult documentation for more details.
FIXME: should support more than simple paths for suite xmls
See Also:usage()
大致内容就是:
org.testng.TestNG这个类是TestNG框架中运行的主要入口,我们可以通过如下方式创建并执行TestNG对象
- 通过已经存在的testng.xml
- 通过Java程序手工构造一个testng.xml
- 直接设置测试类
也可以定义要包含和排除的组、指定参数等等.
从 The command line parameters are 这行开始,介绍了命令行的参数,命令行参数可以参考上文官方文档链接中的内容
比较有趣的是最后一行usage()这个方法,调用此方法可以打印出所有命令行参数内容
由于usage()这个方法是私有的,不能够直接调用,我们可以通过反射调用看下具体效果
public static void main(String[] args) throws Exception {
Method method = TestNG.class.getDeclaredMethod("usage");
method.setAccessible(true);
method.invoke(null);
}
最终控制台会打印出如下内容
CommandLineArgs
通过usage()代码分析我们可以清晰的知道,这些打印出来的内容指向一个类org.testng.CommandLineArgs
TestNG所有的命令行参数由这个类定义,这个类中大部分属性都有一个@Parameter注解,这个注解来源于另一个开源框架 JCommander 有兴趣的同学可以了解下,每个注解对应的name参数就是命令行参数的格式,命令行输入的参数会自动转换到对应的属性上面
main与 run方法
想要了解TestNG的运行,需要从上面两个方法着手,
- 相同点:二者都是运行TestNG的一个入口
- 不同点:main方法是命令行运行的入口,main方法最终也会调用run方法
可以通过代码验证下
public static void main(String[] args){
TestNG.main(new String[]{"-testclass","org.example.MyTest"});
}
public class MyTest {
@Test
public void hello(){
System.out.println("Hello World");//此处要打个断点
}
}
看下图最后几行,我们可以很清晰的知道TestNG main方法先调用了preMain 最后调用了run方法
“main@1” prio=5 tid=0x1 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at org.example.MyTest.hello(MyTest.java:9)
//此处省略部分堆栈信息
at org.testng.TestNG.runSuitesLocally(TestNG.java:1109)
at org.testng.TestNG.runSuites(TestNG.java:1039)
at org.testng.TestNG.run(TestNG.java:1007)
at org.testng.TestNG.privateMain(TestNG.java:1336)
at org.testng.TestNG.main(TestNG.java:1304)
at org.example.App.main(App.java:18)
下面是对源码的分析
//main方法
public static void main(String[] argv) {
TestNG testng = privateMain(argv, null);//调用privateMain方法
System.exit(testng.getStatus());
}
//privateMain
public static TestNG privateMain(String[] argv, ITestListener listener) {
TestNG result = new TestNG();
if (null != listener) {
result.addListener(listener);
}
/**
* 1.先通过JCommander框架解析命令行参数
* 2.校验命令行参数是否合法
* 3.调用configure方法为TestNG对象的属性赋值
* 4.调用run方法运行
*/
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());
}
try {
result.run();//运行
} catch (TestNGException ex) {
if (TestRunner.getVerbose() > 1) {
ex.printStackTrace(System.out);
} else {
error(ex.getMessage());
}
result.exitCode = ExitCode.newExitCodeRepresentingFailure();
}
return result;
}