继上边6.4 执行用例
上一篇讲到了runSuitesSequentially这个方法会去调用SuiteRunnerWorker.run方法,那么run方法的具体实现又是什么样的呢?
走读本段代码后发现run方法中又继续调用了runSuite方法,该方法主要作用:执行suite然后将结果存到suiteRunnerMap中。执行suite的方法则是调用suiteRunner.run()方法,继续细看suiteRunner.run()方法
SuiteRunnerWorker srw = new SuiteRunnerWorker(suiteRunnerMap.get(xmlSuite), suiteRunnerMap,
verbose, defaultSuiteName);
srw.run();
@Override
public void run() {
runSuite(m_suiteRunnerMap, m_suiteRunner.getXmlSuite());
}
/**
* Runs a suite
* @param suiteRunnerMap map of suiteRunners that are updated with test results
* @param xmlSuite XML suites to run
*/
private void runSuite(SuiteRunnerMap suiteRunnerMap /* OUT */, XmlSuite xmlSuite)
{
//日志级别大于0时,在控制台中输出要执行的tetsng.xml的路径,如下图一
if (m_verbose > 0) {
StringBuffer allFiles = new StringBuffer();
allFiles.append(" ").append(xmlSuite.getFileName() != null
? xmlSuite.getFileName() : m_defaultSuiteName).append('\n');
Utils.log("TestNG", 0, "Running:\n" + allFiles.toString());
}
SuiteRunner suiteRunner = (SuiteRunner) suiteRunnerMap.get(xmlSuite);
suiteRunner.run();
//
// Display the final statistics
// 显示最终的统计,输出总个数,失败的个数,skip的个数,如图二
//
if (xmlSuite.getVerbose() > 0) {
SuiteResultCounts counts = new SuiteResultCounts();
synchronized (suiteRunnerMap) {
counts.calculateResultCounts(xmlSuite, suiteRunnerMap);
}
StringBuffer bufLog = new StringBuffer("\n===============================================\n")
.append(xmlSuite.getName());
bufLog.append("\nTotal tests run: ")
.append(counts.m_total).append(", Failures: ").append(counts.m_failed)
.append(", Skips: ").append(counts.m_skipped);
if(counts.m_confFailures > 0 || counts.m_confSkips > 0) {
bufLog.append("\nConfiguration Failures: ").append(counts.m_confFailures)
.append(", Skips: ").append(counts.m_confSkips);
}
bufLog.append("\n===============================================\n");
System.out.println(bufLog.toString());
}
}

图一
图二
suiteRunner.run()方法又调用了同类中的privateRun()方法,该方法主要作用是先执行beforeSuiteMethods方法然后执行所有test最后在执行afterSuiteMethods,其核心还是执行所有test的runSequentially()方法,runSequentially()方法又继续调用runTest方法,而runTest方法就是执行每一个<test>用例然后将执行结果put到m_suiteResults中
@Override
public void run() {
invokeListeners(true /* start */);
try {
privateRun();
}
finally {
invokeListeners(false /* stop */);
}
}
private void privateRun() {
// Map for unicity, Linked for guaranteed order
Map<Method, ITestNGMethod> beforeSuiteMethods= new LinkedHashMap<>();
Map<Method, ITestNGMethod> afterSuiteMethods = new LinkedHashMap<>();
IInvoker invoker = null;
// Get the invoker and find all the suite level methods
for (TestRunner tr: m_testRunners) {
// TODO: Code smell. Invoker should belong to SuiteRunner, not TestRunner
// -- cbeust
invoker = tr.getInvoker();
for (ITestNGMethod m : tr.getBeforeSuiteMethods()) {
beforeSuiteMethods.put(m.getConstructorOrMethod().getMethod(), m);
}
for (ITestNGMethod m : tr.getAfterSuiteMethods()) {
afterSuiteMethods.put(m.getConstructorOrMethod().getMethod(), m);
}
}
//
// Invoke beforeSuite methods (the invoker can be null
// if the suite we are currently running only contains
// a <file-suite> tag and no real tests)
//
if (invoker != null) {
if(beforeSuiteMethods.values().size() > 0) {
invoker.invokeConfigurations(null,
beforeSuiteMethods.values().toArray(new ITestNGMethod[beforeSuiteMethods.size()]),
m_suite, m_suite.getParameters(), null, /* no parameter values */
null /* instance */
);
}
Utils.log("SuiteRunner", 3, "Created " + m_testRunners.size() + " TestRunners");
//
// Run all the test runners
//
boolean testsInParallel = XmlSuite.ParallelMode.TESTS.equals(m_suite.getParallel());
if (!testsInParallel) {
runSequentially();
}
else {
runInParallelTestMode();
}
//
// Invoke afterSuite methods
//
if (afterSuiteMethods.values().size() > 0) {
invoker.invokeConfigurations(null,
afterSuiteMethods.values().toArray(new ITestNGMethod[afterSuiteMethods.size()]),
m_suite, m_suite.getAllParameters(), null, /* no parameter values */
null /* instance */);
}
}
}
private void runSequentially() {
for (TestRunner tr : m_testRunners) {
runTest(tr);
}
}
private void runTest(TestRunner tr) {
tr.run();
ISuiteResult sr = new SuiteResult(m_suite, tr);
m_suiteResults.put(tr.getName(), sr);
}