6.4 执行用例
查看常规模式regular mode的执行过程:
suiteRunners = runSuitesLocally();1.首先就是判断suite的个数是否大于0,只有不为空的时候才会进行用例等一系列操作,否则报错"No test suite found. Nothing to run"
2.然后判断第一个suite的berbose的级别是否大于2,如果大于2则在控制台中输出版本信息
3. 第三步就是初始化suiteRunners,以确保没有配置问题
4.执行suite:又分为单线程按顺序执行和多线程执行
5.生成套件suite报告
具体来看一看初始化套件执行器都做了些什么工作?
主要工作就是首先先将父suite的配置信息put到suiteRunnerMap中,然后依次递归将子suite的信息put到suiteRunnerMap中
suite的配置更新主要有:setJUnit,setSkipFailedInvocationCounts,setVerbose,setConfigFailurePolicy,addMethodSelectors
for (XmlSuite xmlSuite : m_suites) { createSuiteRunners(suiteRunnerMap, xmlSuite); } /** * Creates the {@code SuiteRunner}s and populates the suite runner map with * this information * @param suiteRunnerMap Map with XMLSuite as key and it's respective * SuiteRunner as value. This is updated as part of this method call * @param xmlSuite Xml Suite (and its children) for which {@code SuiteRunner}s are created */ 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 precedence if (null != m_skipFailedInvocationCounts) { xmlSuite.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts); } // Override the XmlSuite verbose value with the one from TestNG if (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); } }再来看一看单线程执行套件的具体代码:
runSuitesSequentially这个方法的四个参数依次是xmlsuite(testng.xml),suiteRunnerMap,Verbose级别,m_defaultSuiteName,该方法主要核心是新建SuiteRunnerWorker对象然后,执行run方法
if (m_suiteThreadPoolSize == 1 && !m_randomizeSuites) { // Single threaded and not randomized: run the suites in order for (XmlSuite xmlSuite : m_suites) { runSuitesSequentially(xmlSuite, suiteRunnerMap, getVerbose(xmlSuite), getDefaultSuiteName()); } } /** * Recursively runs suites. Runs the children suites before running the parent * suite. This is done so that the results for parent suite can reflect the * combined results of the children suites. * 递归运行套件。 * 先运行子套件再运行父套件。 * 目的是为了使父套件的结果可以反映子套件的结果。 * * @param xmlSuite XML Suite to be executed * @param suiteRunnerMap Maps {@code XmlSuite}s to respective {@code ISuite} * @param verbose verbose level * @param defaultSuiteName default suite name */ 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(); }
