Testng 测试框架源码阅读(一)
生活随笔
收集整理的這篇文章主要介紹了
Testng 测试框架源码阅读(一)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
首先看下 maven-surefire 通過testng拉起單測,執行異常的日志(有助于我們理解testng中調用關系):
java.lang.instrument.IllegalClassFormatException: Error while instrumenting class com/suning/gcps/newutils/invoice/InvoiceSendTypeEnum.at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:93)at sun.instrument.TransformerManager.transform(TransformerManager.java:188)at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)at java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoader.defineClass(ClassLoader.java:800)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)at java.net.URLClassLoader.access$100(URLClassLoader.java:71)at java.net.URLClassLoader$1.run(URLClassLoader.java:361)at java.net.URLClassLoader$1.run(URLClassLoader.java:355)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:354)at java.lang.ClassLoader.loadClass(ClassLoader.java:425)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)at java.lang.ClassLoader.loadClass(ClassLoader.java:358)at com.suning.gcps.newutils.invoice.InvoiceSendTypeEnumTest.test(InvoiceSendTypeEnumTest.java:12)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)at org.testng.internal.Invoker.invokeMethod(Invoker.java:646)at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:811)at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1129)at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)at org.testng.TestRunner.privateRun(TestRunner.java:746)at org.testng.TestRunner.run(TestRunner.java:600)at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)at org.testng.SuiteRunner.run(SuiteRunner.java:268)at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)at org.testng.TestNG.runSuitesSequentially(TestNG.java:1264)at org.testng.TestNG.runSuitesLocally(TestNG.java:1189)at org.testng.TestNG.runSuites(TestNG.java:1104)at org.testng.TestNG.run(TestNG.java:1076)at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:62)at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:141)at org.apache.maven.surefire.Surefire.run(Surefire.java:180)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021) Caused by: java.io.IOException: Error while instrumenting class com/suning/gcps/newutils/invoice/InvoiceSendTypeEnum.at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrumentError(Instrumenter.java:160)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:111)at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:91)... 46 more Caused by: java.lang.IllegalStateException: Class com/suning/gcps/newutils/invoice/InvoiceSendTypeEnum is already instrumented.at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:89)at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)at org.jacoco.agent.rt.internal_6da5971.asm.ClassVisitor.visitField(ClassVisitor.java:272)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.readField(ClassReader.java:768)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:689)at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:506)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:84)at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:108)... 47 more 從日志可以看出surefire.testng中的run 方法調用 surefire.testng.TestNGDirectoryTestSuite中execute方法;execute調用TestNGExecutor run 方法。接著調入testng中的方法,testNG.run -> runSuites -> runSutiesLocally -> runSuitesSequentially
->?SuiteRunnerWorker.run -> runSuites
-> SuiteRunner.run -> privateRun ->?invokeTestMethods?
->testng.internal.TestMethodWorker.run ->?invokeTestMethods
->testng.internal.Invoker.invokeTestMethods ->?invokeMethod
->testng.internal.MethodInvocationHelper.invokeMethod
先看testNG這個類:
/*** Run TestNG.*/public void run() {initializeSuitesAndJarFile();initializeConfiguration();initializeDefaultListeners();initializeCommandLineSuites();initializeCommandLineSuitesParams();initializeCommandLineSuitesGroups();sanityCheck();List<ISuite> suiteRunners = null;runExecutionListeners(true /* start */);m_start = System.currentTimeMillis();//// Slave mode//if (m_slavefileName != null) {SuiteSlave slave = new SuiteSlave( m_slavefileName, this );slave.waitForSuites();}//// Regular mode//else if (m_masterfileName == null) {suiteRunners = runSuitesLocally();}//// Master mode//else {SuiteDispatcher dispatcher = new SuiteDispatcher(m_masterfileName);suiteRunners = dispatcher.dispatch(getConfiguration(),m_suites, getOutputDirectory(),getTestListeners());}m_end = System.currentTimeMillis();runExecutionListeners(false /* finish */);if(null != suiteRunners) {generateReports(suiteRunners);}if(!m_hasTests) {setStatus(HAS_NO_TEST);if (TestRunner.getVerbose() > 1) {System.err.println("[TestNG] No tests found. Nothing was run");usage();}}} /*** This needs to be public for maven2, for now..At least* until an alternative mechanism is found.*/public List<ISuite> runSuitesLocally() {SuiteRunnerMap suiteRunnerMap = new SuiteRunnerMap();if (m_suites.size() > 0) {if (m_suites.get(0).getVerbose() >= 2) {Version.displayBanner();}// First initialize the suite runners to ensure there are no configuration issues.// Create a map with XmlSuite as key and corresponding SuiteRunner as valuefor (XmlSuite xmlSuite : m_suites) {createSuiteRunners(suiteRunnerMap, xmlSuite);}//// Run suites//if (m_suiteThreadPoolSize == 1 && !m_randomizeSuites) {// Single threaded and not randomized: run the suites in orderfor (XmlSuite xmlSuite : m_suites) {runSuitesSequentially(xmlSuite, suiteRunnerMap, getVerbose(xmlSuite),getDefaultSuiteName());}} else {// Multithreaded: generate a dynamic graph that stores the suite hierarchy. This is then// used to run related suites in specific order. Parent suites are run only// once all the child suites have completed executionDynamicGraph<ISuite> suiteGraph = new DynamicGraph<ISuite>();for (XmlSuite xmlSuite : m_suites) {populateSuiteGraph(suiteGraph, suiteRunnerMap, xmlSuite);}IThreadWorkerFactory<ISuite> factory = new SuiteWorkerFactory(suiteRunnerMap,0 /* verbose hasn't been set yet */, getDefaultSuiteName());GraphThreadPoolExecutor<ISuite> pooledExecutor =new GraphThreadPoolExecutor<ISuite>(suiteGraph, factory, m_suiteThreadPoolSize,m_suiteThreadPoolSize, Integer.MAX_VALUE, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());Utils.log("TestNG", 2, "Starting executor for all suites");// Run all suites in parallelpooledExecutor.run();try {pooledExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);pooledExecutor.shutdownNow();}catch (InterruptedException handled) {Thread.currentThread().interrupt();error("Error waiting for concurrent executors to finish " + handled.getMessage());}}}else {setStatus(HAS_NO_TEST);error("No test suite found. Nothing to run");usage();}//// Generate the suites report//return Lists.newArrayList(suiteRunnerMap.values());}private void runSuitesSequentially(XmlSuite xmlSuite,SuiteRunnerMap suiteRunnerMap, int verbose, String defaultSuiteName) {for (XmlSuite childSuite : xmlSuite.getChildSuites()) {runSuitesSequentially(childSuite, suiteRunnerMap, verbose, defaultSuiteName);}SuiteRunnerWorker srw = new SuiteRunnerWorker(suiteRunnerMap.get(xmlSuite), suiteRunnerMap,verbose, defaultSuiteName);srw.run();}/*** Populates the dynamic graph with the reverse hierarchy of suites. Edges are* added pointing from child suite runners to parent suite runners, hence making* parent suite runners dependent on all the child suite runners** @param suiteGraph dynamic graph representing the reverse hierarchy of SuiteRunners* @param suiteRunnerMap Map with XMLSuite as key and its respective SuiteRunner as value* @param xmlSuite XML Suite*/private void populateSuiteGraph(DynamicGraph<ISuite> suiteGraph /* OUT */,SuiteRunnerMap suiteRunnerMap, XmlSuite xmlSuite) {ISuite parentSuiteRunner = suiteRunnerMap.get(xmlSuite);if (xmlSuite.getChildSuites().isEmpty()) {suiteGraph.addNode(parentSuiteRunner);}else {for (XmlSuite childSuite : xmlSuite.getChildSuites()) {suiteGraph.addEdge(parentSuiteRunner, suiteRunnerMap.get(childSuite));populateSuiteGraph(suiteGraph, suiteRunnerMap, childSuite);}}}
private void createSuiteRunners(SuiteRunnerMap suiteRunnerMap /* OUT */, XmlSuite xmlSuite) {if (null != m_isJUnit && ! m_isJUnit.equals(XmlSuite.DEFAULT_JUNIT)) {xmlSuite.setJUnit(m_isJUnit);}// If the skip flag was invoked on the command line, it// takes precedenceif (null != m_skipFailedInvocationCounts) {xmlSuite.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts);}// Override the XmlSuite verbose value with the one from TestNGif (m_verbose != null) {xmlSuite.setVerbose(m_verbose);}if (null != m_configFailurePolicy) {xmlSuite.setConfigFailurePolicy(m_configFailurePolicy);}for (XmlTest t : xmlSuite.getTests()) {for (Map.Entry<String, Integer> ms : m_methodDescriptors.entrySet()) {XmlMethodSelector xms = new XmlMethodSelector();xms.setName(ms.getKey());xms.setPriority(ms.getValue());t.getMethodSelectors().add(xms);}}suiteRunnerMap.put(xmlSuite, createSuiteRunner(xmlSuite));for (XmlSuite childSuite : xmlSuite.getChildSuites()) {createSuiteRunners(suiteRunnerMap, childSuite);}}/*** Creates a suite runner and configures its initial state* @param xmlSuite* @return returns the newly created suite runner*/private SuiteRunner createSuiteRunner(XmlSuite xmlSuite) {SuiteRunner result = new SuiteRunner(getConfiguration(), xmlSuite,m_outputDir,m_testRunnerFactory,m_useDefaultListeners,m_methodInterceptor,m_invokedMethodListeners,m_testListeners);for (ISuiteListener isl : m_suiteListeners) {result.addListener(isl);}for (IReporter r : result.getReporters()) {addListener(r);}for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) {result.addConfigurationListener(cl);}return result;}
public static void main(String[] argv) {TestNG testng = privateMain(argv, null);System.exit(testng.getStatus());}/*** <B>Note</B>: this method is not part of the public API and is meant for internal usage only.*/public static TestNG privateMain(String[] argv, ITestListener listener) {TestNG result = new TestNG();if (null != listener) {result.addListener(listener);}//// Parse the arguments//try {CommandLineArgs cla = new CommandLineArgs();m_jCommander = new JCommander(cla, argv);validateCommandLineParameters(cla);result.configure(cla);}catch(ParameterException ex) {exitWithError(ex.getMessage());}//// Run//try {result.run();}catch(TestNGException ex) {if (TestRunner.getVerbose() > 1) {ex.printStackTrace(System.out);}else {error(ex.getMessage());}result.setStatus(HAS_FAILURE);}return result;}/*** Configure the TestNG instance based on the command line parameters.*/protected void configure(CommandLineArgs cla) {if (cla.verbose != null) {setVerbose(cla.verbose);}setOutputDirectory(cla.outputDirectory);String testClasses = cla.testClass;if (null != testClasses) {String[] strClasses = testClasses.split(",");List<Class> classes = Lists.newArrayList();for (String c : strClasses) {classes.add(ClassHelper.fileToClass(c));}setTestClasses(classes.toArray(new Class[classes.size()]));}setOutputDirectory(cla.outputDirectory);if (cla.testNames != null) {setTestNames(Arrays.asList(cla.testNames.split(",")));}// List<String> testNgXml = (List<String>) cmdLineArgs.get(CommandLineArgs.SUITE_DEF); // if (null != testNgXml) { // setTestSuites(testNgXml); // }// Note: can't use a Boolean field here because we are allowing a boolean// parameter with an arity of 1 ("-usedefaultlisteners false")if (cla.useDefaultListeners != null) {setUseDefaultListeners("true".equalsIgnoreCase(cla.useDefaultListeners));}setGroups(cla.groups);setExcludedGroups(cla.excludedGroups);setTestJar(cla.testJar);setXmlPathInJar(cla.xmlPathInJar);setJUnit(cla.junit);setMixed(cla.mixed);setMaster(cla.master);setSlave(cla.slave);setSkipFailedInvocationCounts(cla.skipFailedInvocationCounts);if (cla.parallelMode != null) {setParallel(cla.parallelMode);}if (cla.configFailurePolicy != null) {setConfigFailurePolicy(cla.configFailurePolicy);}if (cla.threadCount != null) {setThreadCount(cla.threadCount);}if (cla.dataProviderThreadCount != null) {setDataProviderThreadCount(cla.dataProviderThreadCount);}if (cla.suiteName != null) {setDefaultSuiteName(cla.suiteName);}if (cla.testName != null) {setDefaultTestName(cla.testName);}if (cla.listener != null) {String sep = ";";if (cla.listener.indexOf(",") >= 0) {sep = ",";}String[] strs = Utils.split(cla.listener, sep);List<Class> classes = Lists.newArrayList();for (String cls : strs) {classes.add(ClassHelper.fileToClass(cls));}setListenerClasses(classes);}if (null != cla.methodSelectors) {String[] strs = Utils.split(cla.methodSelectors, ",");for (String cls : strs) {String[] sel = Utils.split(cls, ":");try {if (sel.length == 2) {addMethodSelector(sel[0], Integer.valueOf(sel[1]));} else {error("Method selector value was not in the format org.example.Selector:4");}}catch (NumberFormatException nfe) {error("Method selector value was not in the format org.example.Selector:4");}}}if (cla.objectFactory != null) {setObjectFactory(ClassHelper.fileToClass(cla.objectFactory));}if (cla.testRunnerFactory != null) {setTestRunnerFactoryClass(ClassHelper.fileToClass(cla.testRunnerFactory));}if (cla.reporter != null) {ReporterConfig reporterConfig = ReporterConfig.deserialize(cla.reporter);addReporter(reporterConfig);}if (cla.commandLineMethods.size() > 0) {m_commandLineMethods = cla.commandLineMethods;}if (cla.suiteFiles != null) {setTestSuites(cla.suiteFiles);}setSuiteThreadPoolSize(cla.suiteThreadPoolSize);setRandomizeSuites(cla.randomizeSuites);}public void setSuiteThreadPoolSize(Integer suiteThreadPoolSize) {m_suiteThreadPoolSize = suiteThreadPoolSize;}public Integer getSuiteThreadPoolSize() {return m_suiteThreadPoolSize;}public void setRandomizeSuites(boolean randomizeSuites) {m_randomizeSuites = randomizeSuites;}
SuiteRunnerWorker類:
public class SuiteRunnerWorker implements IWorker<ISuite> {private SuiteRunner m_suiteRunner;private Integer m_verbose;private String m_defaultSuiteName;private SuiteRunnerMap m_suiteRunnerMap;public SuiteRunnerWorker(ISuite suiteRunner,SuiteRunnerMap suiteRunnerMap,int verbose,String defaultSuiteName){m_suiteRunnerMap = suiteRunnerMap;m_suiteRunner = (SuiteRunner) suiteRunner;m_verbose = verbose;m_defaultSuiteName = defaultSuiteName;}/*** 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){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();//TODO: this should be handled properly// for (IReporter r : suiteRunner.getReporters()) {// addListener(r);// }// PoolService.getInstance().shutdown();// Display the final statistics//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());}}@Overridepublic void run() {runSuite(m_suiteRunnerMap, m_suiteRunner.getXmlSuite());}@Overridepublic int compareTo(IWorker<ISuite> arg0) {/** Dummy Implementation** Used by IWorkers to prioritize execution in parallel. Not required by* this Worker in current implementation*/return 0;}@Overridepublic List<ISuite> getTasks() {List<ISuite> suiteRunnerList = Lists.newArrayList();suiteRunnerList.add(m_suiteRunner);return suiteRunnerList;}@Overridepublic String toString() {return Objects.toStringHelper(getClass()).add("name", m_suiteRunner.getName()).toString();}@Overridepublic long getTimeOut(){return m_suiteRunner.getXmlSuite().getTimeOut(Long.MAX_VALUE);}@Overridepublic int getPriority(){// this class doesnt support priorities yetreturn 0;} } /*** Class to help calculate result counts for tests run as part of a suite and* its children suites** @author nullin**/ class SuiteResultCounts {int m_total = 0;int m_skipped = 0;int m_failed = 0;int m_confFailures = 0;int m_confSkips = 0;public void calculateResultCounts(XmlSuite xmlSuite, SuiteRunnerMap suiteRunnerMap){ISuite iSuite = suiteRunnerMap.get(xmlSuite);if (iSuite != null) {Map<String, ISuiteResult> results = iSuite.getResults();if (results != null) {Collection<ISuiteResult> tempSuiteResult = results.values();for (ISuiteResult isr : tempSuiteResult) {ITestContext ctx = isr.getTestContext();int skipped = ctx.getSkippedTests().size();int failed = ctx.getFailedTests().size() + ctx.getFailedButWithinSuccessPercentageTests().size();m_skipped += skipped;m_failed += failed;m_confFailures += ctx.getFailedConfigurations().size();m_confSkips += ctx.getSkippedConfigurations().size();m_total += ctx.getPassedTests().size() + failed + skipped;}for (XmlSuite childSuite : xmlSuite.getChildSuites()) {calculateResultCounts(childSuite, suiteRunnerMap);}}}} } SuiteRunner類:
@Overridepublic void run() {invokeListeners(true /* start */);try {privateRun();}finally {invokeListeners(false /* stop */);}}private void privateRun() {// Map for unicity, Linked for guaranteed orderMap<Method, ITestNGMethod> beforeSuiteMethods= new LinkedHashMap<Method, ITestNGMethod>();Map<Method, ITestNGMethod> afterSuiteMethods = new LinkedHashMap<Method, ITestNGMethod>();IInvoker invoker = null;// Get the invoker and find all the suite level methodsfor (TestRunner tr: m_testRunners) {// TODO: Code smell. Invoker should belong to SuiteRunner, not TestRunner// -- cbeustinvoker = tr.getInvoker();for (ITestNGMethod m : tr.getBeforeSuiteMethods()) {beforeSuiteMethods.put(m.getMethod(), m);}for (ITestNGMethod m : tr.getAfterSuiteMethods()) {afterSuiteMethods.put(m.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.PARALLEL_TESTS.equals(m_suite.getParallel());if (!testsInParallel) {runSequentially();}else {runInParallelTestMode();} // SuitePlan sp = new SuitePlan(); // for (TestRunner tr : m_testRunners) { // sp.addTestPlan(tr.getTestPlan()); // } // sp.dump();//// 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 */);}}} @Overridepublic void addListener(ITestNGListener listener) {if (listener instanceof IInvokedMethodListener) {m_invokedMethodListeners.add((IInvokedMethodListener) listener);}if (listener instanceof ISuiteListener) {addListener((ISuiteListener) listener);}if (listener instanceof IReporter) {addReporter((IReporter) listener);}if (listener instanceof IConfigurationListener) {addConfigurationListener((IConfigurationListener) listener);}} @Overridepublic TestRunner newTestRunner(ISuite suite, XmlTest test,List<IInvokedMethodListener> listeners) {boolean skip = m_skipFailedInvocationCounts;if (! skip) {skip = test.skipFailedInvocationCounts();}TestRunner testRunner = new TestRunner(m_configuration, suite, test,suite.getOutputDirectory(), suite.getAnnotationFinder(), skip,listeners);if (m_useDefaultListeners) {testRunner.addListener(new TestHTMLReporter());testRunner.addListener(new JUnitXMLReporter());//TODO: Moved these here because maven2 has output reporters running//already, the output from these causes directories to be created with//files. This is not the desired behaviour of running tests in maven2.//Don't know what to do about this though, are people relying on these//to be added even with defaultListeners set to false?testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose()));}for (ITestListener itl : m_failureGenerators) {testRunner.addListener(itl);}for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) {testRunner.addConfigurationListener(cl);}return testRunner;}}private static class ProxyTestRunnerFactory implements ITestRunnerFactory {private ITestListener[] m_failureGenerators;private ITestRunnerFactory m_target;public ProxyTestRunnerFactory(ITestListener[] failureListeners, ITestRunnerFactory target) {m_failureGenerators = failureListeners;m_target= target;}@Overridepublic TestRunner newTestRunner(ISuite suite, XmlTest test,List<IInvokedMethodListener> listeners) {TestRunner testRunner= m_target.newTestRunner(suite, test, listeners);testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose()));for (ITestListener itl : m_failureGenerators) {testRunner.addListener(itl);}return testRunner;}} @Overridepublic Map<String, Collection<ITestNGMethod>> getMethodsByGroups() {Map<String, Collection<ITestNGMethod>> result = Maps.newHashMap();for (TestRunner tr : m_testRunners) {ITestNGMethod[] methods = tr.getAllTestMethods();for (ITestNGMethod m : methods) {String[] groups = m.getGroups();for (String groupName : groups) {Collection<ITestNGMethod> testMethods = result.get(groupName);if (null == testMethods) {testMethods = Lists.newArrayList();result.put(groupName, testMethods);}testMethods.add(m);}}}return result;}/*** @see org.testng.ISuite#getInvokedMethods()*/@Overridepublic Collection<ITestNGMethod> getInvokedMethods() {return getIncludedOrExcludedMethods(true /* included */);}/*** @see org.testng.ISuite#getExcludedMethods()*/@Overridepublic Collection<ITestNGMethod> getExcludedMethods() {return getIncludedOrExcludedMethods(false/* included */);}private Collection<ITestNGMethod> getIncludedOrExcludedMethods(boolean included) {List<ITestNGMethod> result= Lists.newArrayList();for (TestRunner tr : m_testRunners) {Collection<ITestNGMethod> methods = included ? tr.getInvokedMethods() : tr.getExcludedMethods();for (ITestNGMethod m : methods) {result.add(m);}}return result;}
總結
以上是生活随笔為你收集整理的Testng 测试框架源码阅读(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAN协议详解(Network)
- 下一篇: phpcms如何做关键字