繼上邊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);
}