这里分析是基于2.5surefire 版本。
首先拿surefire 拉起单元测试报错日志 分析:
Caused by: java.io.IOException: Error while instrumenting class com/suning/gcps/newutils/string/StringUtils.
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/string/StringUtils 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
11:38:21.536 [main] ERROR c.s.gcps.newutils.string.StringUtils - 数据格式转换错误!3w
java.lang.NumberFormatException: For input string: "3w"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.7.0_75]
at java.lang.Integer.parseInt(Integer.java:492) ~[na:1.7.0_75]
at java.lang.Integer.parseInt(Integer.java:527) ~[na:1.7.0_75]
at com.suning.gcps.newutils.string.StringUtils.isIntString(StringUtils.java:216) ~[classes/:na]
at com.suning.gcps.newutils.string.StringUtilsTest.test(StringUtilsTest.java:33) [test-classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_75]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_75]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_75]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_75]
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100) [testng-6.9.12.jar:na]
at org.testng.internal.Invoker.invokeMethod(Invoker.java:646) [testng-6.9.12.jar:na]
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:811) [testng-6.9.12.jar:na]
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1129) [testng-6.9.12.jar:na]
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129) [testng-6.9.12.jar:na]
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112) [testng-6.9.12.jar:na]
at org.testng.TestRunner.privateRun(TestRunner.java:746) [testng-6.9.12.jar:na]
at org.testng.TestRunner.run(TestRunner.java:600) [testng-6.9.12.jar:na]
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366) [testng-6.9.12.jar:na]
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361) [testng-6.9.12.jar:na]
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319) [testng-6.9.12.jar:na]
at org.testng.SuiteRunner.run(SuiteRunner.java:268) [testng-6.9.12.jar:na]
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) [testng-6.9.12.jar:na]
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) [testng-6.9.12.jar:na]
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1264) [testng-6.9.12.jar:na]
at org.testng.TestNG.runSuitesLocally(TestNG.java:1189) [testng-6.9.12.jar:na]
at org.testng.TestNG.runSuites(TestNG.java:1104) [testng-6.9.12.jar:na]
at org.testng.TestNG.run(TestNG.java:1076) [testng-6.9.12.jar:na]
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:62) [surefire-testng-2.5.jar:2.5]
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:141) [surefire-testng-2.5.jar:2.5]
at org.apache.maven.surefire.Surefire.run(Surefire.java:180) [surefire-api-2.5.jar:2.5]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_75]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_75]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_75]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_75]
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350) [surefire-booter-2.5.jar:2.5]
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021) [surefire-booter-2.5.jar:2.5]
上述报错日志展示 testng使用6.9.12 ,surefire使用的2.5版本。
-> SuiteRunnerWorker.run -> runSuites
-> SuiteRunner.run -> privateRun -> invokeTestMethods
->testng.internal.TestMethodWorker.run -> invokeTestMethods
->testng.internal.Invoker.invokeTestMethods -> invokeMethod
->testng.internal.MethodInvocationHelper.invokeMethod
然后surefire 通过调用 SurefireBooter.main(surefire-booter.jar) -> SurefireBooter.runSuitesInProcess
-> maven.surefire.Surefire.run(surefire-api-2.5.jar)
-> testng.TestNGExecutor.run(surefire-testng-2.5)
-> TestNG.run(testng-6.9.12)
SurefireBooter 代码:
static
{
try
{
assertionStatusMethod = class$java$lang$ClassLoader.getMethod("setDefaultAssertionStatus", new Class[] { Boolean.TYPE });
}
catch (NoSuchMethodException e)
{
assertionStatusMethod = null;
}
}
public SurefireBooter()
{
this.isForked = false;
}
private SurefireBooter(boolean isForked)
{
this.isForked = isForked;
}
public void addReport(String report)
{
addReport(report, null);
}
public void addReport(String report, Object[] constructorParams)
{
this.reports.add(new Object[] { report, constructorParams });
}
public void addTestSuite(String suiteClassName, Object[] constructorParams)
{
this.testSuites.add(new Object[] { suiteClassName, constructorParams });
}
public void addClassPathUrl(String path)
{
if (!this.classPathUrls.contains(path)) {
this.classPathUrls.add(path);
}
}
public void addSurefireClassPathUrl(String path)
{
if (!this.surefireClassPathUrls.contains(path)) {
this.surefireClassPathUrls.add(path);
}
}
public void addSurefireBootClassPathUrl(String path)
{
if (!this.surefireBootClassPathUrls.contains(path)) {
this.surefireBootClassPathUrls.add(path);
}
}
public void setFailIfNoTests(boolean failIfNoTests)
{
this.failIfNoTests = failIfNoTests;
}
public void setRedirectTestOutputToFile(boolean redirectTestOutputToFile)
{
this.redirectTestOutputToFile = redirectTestOutputToFile;
}
public void setReportsDirectory(File reportsDirectory)
{
this.reportsDirectory = reportsDirectory;
}
public File getReportsDirectory()
{
return this.reportsDirectory;
}
public void setForkConfiguration(ForkConfiguration forkConfiguration)
{
this.forkConfiguration = forkConfiguration;
}
public boolean isForking()
{
return this.forkConfiguration.isForking();
}
public int run()
throws SurefireBooterForkException, SurefireExecutionException
{
int result;
if ("never".equals(this.forkConfiguration.getForkMode()))
{
result = runSuitesInProcess();
}
else
{
int result;
if ("once".equals(this.forkConfiguration.getForkMode()))
{
result = runSuitesForkOnce();
}
else
{
int result;
if ("always".equals(this.forkConfiguration.getForkMode())) {
result = runSuitesForkPerTestSet();
} else {
throw new SurefireExecutionException("Unknown forkmode: " + this.forkConfiguration.getForkMode(), null);
}
}
}
int result;
return result;
}
private int runSuitesInProcess(String testSet, Properties results)
throws SurefireExecutionException
{
if (this.testSuites.size() != 1) {
throw new IllegalArgumentException("Cannot only specify testSet for single test suites");
}
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try
{
ClassLoader testsClassLoader = useSystemClassLoader() ? ClassLoader.getSystemClassLoader() : createClassLoader(this.classPathUrls, null, this.childDelegation);
ClassLoader surefireClassLoader = createClassLoader(this.surefireClassPathUrls, testsClassLoader);
Class surefireClass = surefireClassLoader.loadClass(Surefire.class.getName());
Object surefire = surefireClass.newInstance();
Method run = surefireClass.getMethod("run", new Class[] { List.class, new Object[0].getClass(), String.class, ClassLoader.class, ClassLoader.class, Properties.class, Boolean.class });
Thread.currentThread().setContextClassLoader(testsClassLoader);
Integer result = (Integer)run.invoke(surefire, new Object[] { this.reports, this.testSuites.get(0), testSet, surefireClassLoader, testsClassLoader, results, new Boolean(this.failIfNoTests) });
return result.intValue();
}
catch (InvocationTargetException e)
{
throw new SurefireExecutionException(e.getTargetException().getMessage(), e.getTargetException());
}
catch (Exception e)
{
throw new SurefireExecutionException("Unable to instantiate and execute Surefire", e);
}
finally
{
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
}
}
private int runSuitesInProcess()
throws SurefireExecutionException
{
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try
{
String testClassPath = getTestClassPathAsString();
System.setProperty("surefire.test.class.path", testClassPath);
ClassLoader testsClassLoader;
if (useManifestOnlyJar())
{
ClassLoader testsClassLoader = getClass().getClassLoader();
System.setProperty("surefire.real.class.path", System.getProperty("java.class.path"));
System.setProperty("java.class.path", testClassPath);
}
else
{
testsClassLoader = createClassLoader(this.classPathUrls, null, this.childDelegation);
}
ClassLoader surefireClassLoader = createClassLoader(this.surefireClassPathUrls, testsClassLoader);
Class surefireClass = surefireClassLoader.loadClass(Surefire.class.getName());
Object surefire = surefireClass.newInstance();
Method run = surefireClass.getMethod("run", new Class[] { List.class, List.class, ClassLoader.class, ClassLoader.class, Boolean.class });
Thread.currentThread().setContextClassLoader(testsClassLoader);
Integer result = (Integer)run.invoke(surefire, new Object[] { this.reports, this.testSuites, surefireClassLoader, testsClassLoader, new Boolean(this.failIfNoTests) });
return result.intValue();
}
catch (InvocationTargetException e)
{
throw new SurefireExecutionException(e.getTargetException().getMessage(), e.getTargetException());
}
catch (Exception e)
{
throw new SurefireExecutionException("Unable to instantiate and execute Surefire", e);
}
finally
{
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
}
}
private String getTestClassPathAsString()
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < this.classPathUrls.size(); i++) {
sb.append(this.classPathUrls.get(i)).append(File.pathSeparatorChar);
}
return sb.toString();
}
private int runSuitesForkOnce()
throws SurefireBooterForkException
{
return forkSuites(this.testSuites, true, true);
}
private int runSuitesForkPerTestSet()
throws SurefireBooterForkException
{
ClassLoader testsClassLoader;
ClassLoader surefireClassLoader;
try
{
testsClassLoader = createClassLoader(this.classPathUrls, null, false);
surefireClassLoader = createClassLoader(this.surefireClassPathUrls, testsClassLoader, false);
}
catch (MalformedURLException e)
{
throw new SurefireBooterForkException("Unable to create classloader to find test suites", e);
}
int globalResult = 0;
boolean showHeading = true;
Properties properties = new Properties();
for (Iterator i = this.testSuites.iterator(); i.hasNext();)
{
testSuite = (Object[])i.next();
Map testSets = getTestSets(testSuite, testsClassLoader, surefireClassLoader);
for (j = testSets.keySet().iterator(); j.hasNext();)
{
Object testSet = j.next();
boolean showFooter = (!j.hasNext()) && (!i.hasNext());
int result = forkSuite(testSuite, testSet, showHeading, showFooter, properties);
if (result > globalResult) {
globalResult = result;
}
showHeading = false;
}
}
Object[] testSuite;
Iterator j;
return globalResult;
}
private Map getTestSets(Object[] testSuite, ClassLoader testsClassLoader, ClassLoader surefireClassLoader)
throws SurefireBooterForkException
{
String className = (String)testSuite[0];
Object[] params = (Object[])testSuite[1];
Object suite;
try
{
suite = Surefire.instantiateObject(className, params, surefireClassLoader);
}
catch (TestSetFailedException e)
{
throw new SurefireBooterForkException(e.getMessage(), e.getCause());
}
catch (ClassNotFoundException e)
{
throw new SurefireBooterForkException("Unable to find class for test suite '" + className + "'", e);
}
catch (NoSuchMethodException e)
{
throw new SurefireBooterForkException("Unable to find appropriate constructor for test suite '" + className + "': " + e.getMessage(), e);
}
Map testSets;
try
{
Method m = suite.getClass().getMethod("locateTestSets", new Class[] { ClassLoader.class });
testSets = (Map)m.invoke(suite, new Object[] { testsClassLoader });
}
catch (IllegalAccessException e)
{
throw new SurefireBooterForkException("Error obtaining test sets", e);
}
catch (NoSuchMethodException e)
{
throw new SurefireBooterForkException("Error obtaining test sets", e);
}
catch (InvocationTargetException e)
{
throw new SurefireBooterForkException(e.getTargetException().getMessage(), e.getTargetException());
}
return testSets;
}
private int forkSuites(List testSuites, boolean showHeading, boolean showFooter)
throws SurefireBooterForkException
{
Properties properties = new Properties();
setForkProperties(testSuites, properties);
return fork(properties, showHeading, showFooter);
}
private int forkSuite(Object[] testSuite, Object testSet, boolean showHeading, boolean showFooter, Properties properties)
throws SurefireBooterForkException
{
setForkProperties(Collections.singletonList(testSuite), properties);
if ((testSet instanceof String)) {
properties.setProperty("testSet", (String)testSet);
}
return fork(properties, showHeading, showFooter);
}
private void setForkProperties(List testSuites, Properties properties)
{
addPropertiesForTypeHolder(this.reports, properties, "report.");
addPropertiesForTypeHolder(testSuites, properties, "testSuite.");
for (int i = 0; i < this.classPathUrls.size(); i++)
{
String url = (String)this.classPathUrls.get(i);
properties.setProperty("classPathUrl." + i, url);
}
for (int i = 0; i < this.surefireClassPathUrls.size(); i++)
{
String url = (String)this.surefireClassPathUrls.get(i);
properties.setProperty("surefireClassPathUrl." + i, url);
}
properties.setProperty("childDelegation", String.valueOf(this.childDelegation));
properties.setProperty("enableAssertions", String.valueOf(this.enableAssertions));
properties.setProperty("useSystemClassLoader", String.valueOf(useSystemClassLoader()));
properties.setProperty("useManifestOnlyJar", String.valueOf(useManifestOnlyJar()));
properties.setProperty("failIfNoTests", String.valueOf(this.failIfNoTests));
}
private File writePropertiesFile(String name, Properties properties)
throws IOException
{
File file = File.createTempFile(name, "tmp");
if (!this.forkConfiguration.isDebug()) {
file.deleteOnExit();
}
writePropertiesFile(file, name, properties);
return file;
}
private void writePropertiesFile(File file, String name, Properties properties)
throws IOException
{
FileOutputStream out = new FileOutputStream(file);
try
{
properties.store(out, name);
}
finally
{
IOUtil.close(out);
}
}
private void addPropertiesForTypeHolder(List typeHolderList, Properties properties, String propertyPrefix)
{
for (int i = 0; i < typeHolderList.size(); i++)
{
Object[] report = (Object[])typeHolderList.get(i);
String className = (String)report[0];
Object[] params = (Object[])report[1];
properties.setProperty(propertyPrefix + i, className);
if (params != null)
{
String paramProperty = convert(params[0]);
String typeProperty = params[0].getClass().getName();
for (int j = 1; j < params.length; j++)
{
paramProperty = paramProperty + "|";
typeProperty = typeProperty + "|";
if (params[j] != null)
{
paramProperty = paramProperty + convert(params[j]);
typeProperty = typeProperty + params[j].getClass().getName();
}
}
properties.setProperty(propertyPrefix + i + ".params", paramProperty);
properties.setProperty(propertyPrefix + i + ".types", typeProperty);
}
}
}
private static String convert(Object param)
{
if ((param instanceof File[]))
{
File[] files = (File[])param;
return "[" + StringUtils.join(files, ",") + "]";
}
if ((param instanceof Properties))
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try
{
((Properties)param).store(baos, "");
return new String(baos.toByteArray(), "8859_1");
}
catch (Exception e)
{
throw new RuntimeException("bug in property conversion", e);
}
}
return param.toString();
}
private boolean useSystemClassLoader()
{
return (this.forkConfiguration.isUseSystemClassLoader()) && ((this.isForked) || (this.forkConfiguration.isForking()));
}
private boolean useManifestOnlyJar()
{
return (this.forkConfiguration.isUseSystemClassLoader()) && (this.forkConfiguration.isUseManifestOnlyJar());
}
private int fork(Properties properties, boolean showHeading, boolean showFooter)
throws SurefireBooterForkException
{
File systemProperties = null;
File surefireProperties;
try
{
surefireProperties = writePropertiesFile("surefire", properties);
if (this.forkConfiguration.getSystemProperties() != null) {
systemProperties = writePropertiesFile("surefire", this.forkConfiguration.getSystemProperties());
}
}
catch (IOException e)
{
throw new SurefireBooterForkException("Error creating properties files for forking", e);
}
List bootClasspath = new ArrayList(this.surefireBootClassPathUrls.size() + this.classPathUrls.size());
bootClasspath.addAll(this.surefireBootClassPathUrls);
if (useSystemClassLoader()) {
bootClasspath.addAll(this.classPathUrls);
}
Commandline cli = this.forkConfiguration.createCommandLine(bootClasspath, useManifestOnlyJar());
cli.createArg().setFile(surefireProperties);
if (systemProperties != null) {
cli.createArg().setFile(systemProperties);
}
ForkingStreamConsumer out = getForkingStreamConsumer(showHeading, showFooter, this.redirectTestOutputToFile);
StreamConsumer err;
StreamConsumer err;
if (this.redirectTestOutputToFile) {
err = out;
} else {
err = getForkingStreamConsumer(showHeading, showFooter, this.redirectTestOutputToFile);
}
if (this.forkConfiguration.isDebug()) {
System.out.println("Forking command line: " + cli);
}
int returnCode;
try
{
returnCode = CommandLineUtils.executeCommandLine(cli, out, err, this.forkedProcessTimeoutInSeconds);
}
catch (CommandLineException e)
{
throw new SurefireBooterForkException("Error while executing forked tests.", e);
}
if (this.redirectTestOutputToFile) {
try
{
out.getOutputConsumer().testSetCompleted();
}
catch (Exception e) {}
}
if ((surefireProperties != null) && (surefireProperties.exists()))
{
FileInputStream inStream = null;
try
{
inStream = new FileInputStream(surefireProperties);
properties.load(inStream);
}
catch (FileNotFoundException e)
{
throw new SurefireBooterForkException("Unable to reload properties file from forked process", e);
}
catch (IOException e)
{
throw new SurefireBooterForkException("Unable to reload properties file from forked process", e);
}
finally
{
IOUtil.close(inStream);
}
}
return returnCode;
}
private ClassLoader createClassLoader(List classPathUrls, ClassLoader parent)
throws MalformedURLException
{
return createClassLoader(classPathUrls, parent, false);
}
private ClassLoader createClassLoader(List classPathUrls, ClassLoader parent, boolean childDelegation)
throws MalformedURLException
{
List urls = new ArrayList();
for (Iterator i = classPathUrls.iterator(); i.hasNext();)
{
String url = (String)i.next();
if (url != null)
{
File f = new File(url);
urls.add(UrlUtils.getURL(f));
}
}
IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation);
if (assertionStatusMethod != null) {
try
{
Object[] args = { this.enableAssertions ? Boolean.TRUE : Boolean.FALSE };
if (parent != null) {
assertionStatusMethod.invoke(parent, args);
}
assertionStatusMethod.invoke(classLoader, args);
}
catch (IllegalAccessException e)
{
throw new NestedRuntimeException("Unable to access the assertion enablement method", e);
}
catch (InvocationTargetException e)
{
throw new NestedRuntimeException("Unable to invoke the assertion enablement method", e);
}
}
for (Iterator iter = urls.iterator(); iter.hasNext();)
{
URL url = (URL)iter.next();
classLoader.addURL(url);
}
return classLoader;
}
private static List processStringList(String stringList)
{
String sl = stringList;
if ((sl.startsWith("[")) && (sl.endsWith("]"))) {
sl = sl.substring(1, sl.length() - 1);
}
List list = new ArrayList();
String[] stringArray = StringUtils.split(sl, ",");
for (int i = 0; i < stringArray.length; i++) {
list.add(stringArray[i].trim());
}
return list;
}
private static Properties loadProperties(File file)
throws IOException
{
Properties p = new Properties();
if ((file != null) && (file.exists()))
{
FileInputStream inStream = new FileInputStream(file);
try
{
p.load(inStream);
}
finally
{
IOUtil.close(inStream);
}
}
return p;
}
private static void setSystemProperties(File file)
throws IOException
{
Properties p = loadProperties(file);
for (Iterator i = p.keySet().iterator(); i.hasNext();)
{
String key = (String)i.next();
System.setProperty(key, p.getProperty(key));
}
}
private static Object[] constructParamObjects(String paramProperty, String typeProperty)
{
Object[] paramObjects = null;
if (paramProperty != null)
{
String[] params = StringUtils.split(StringUtils.replace(StringUtils.replace(paramProperty, "||", "| |"), "||", "| |"), "|");
String[] types = StringUtils.split(StringUtils.replace(StringUtils.replace(typeProperty, "||", "| |"), "||", "| |"), "|");
paramObjects = new Object[params.length];
for (int i = 0; i < types.length; i++) {
if (types[i].trim().length() == 0)
{
params[i] = null;
}
else if (types[i].equals(String.class.getName()))
{
paramObjects[i] = params[i];
}
else if (types[i].equals(File.class.getName()))
{
paramObjects[i] = new File(params[i]);
}
else if (types[i].equals(new File[0].getClass().getName()))
{
List stringList = processStringList(params[i]);
File[] fileList = new File[stringList.size()];
for (int j = 0; j < stringList.size(); j++) {
fileList[j] = new File((String)stringList.get(j));
}
paramObjects[i] = fileList;
}
else if (types[i].equals(ArrayList.class.getName()))
{
paramObjects[i] = processStringList(params[i]);
}
else if (types[i].equals(Boolean.class.getName()))
{
paramObjects[i] = Boolean.valueOf(params[i]);
}
else if (types[i].equals(Integer.class.getName()))
{
paramObjects[i] = Integer.valueOf(params[i]);
}
else if (types[i].equals(Properties.class.getName()))
{
Properties result = new Properties();
String value = params[i];
try
{
ByteArrayInputStream bais = new ByteArrayInputStream(value.getBytes("8859_1"));
result.load(bais);
}
catch (Exception e)
{
throw new RuntimeException("bug in property conversion", e);
}
paramObjects[i] = result;
}
else
{
throw new IllegalArgumentException("Unknown parameter type: " + types[i]);
}
}
}
return paramObjects;
}
public static void main(String[] args)
throws Throwable
{
try
{
if (args.length > 1) {
setSystemProperties(new File(args[1]));
}
File surefirePropertiesFile = new File(args[0]);
Properties p = loadProperties(surefirePropertiesFile);
SortedMap classPathUrls = new TreeMap();
SortedMap surefireClassPathUrls = new TreeMap();
SurefireBooter surefireBooter = new SurefireBooter(true);
ForkConfiguration forkConfiguration = new ForkConfiguration();
forkConfiguration.setForkMode("never");
surefireBooter.setForkConfiguration(forkConfiguration);
for (Enumeration e = p.propertyNames(); e.hasMoreElements();)
{
String name = (String)e.nextElement();
if ((name.startsWith("report.")) && (!name.endsWith(".params")) && (!name.endsWith(".types")))
{
String className = p.getProperty(name);
String params = p.getProperty(name + ".params");
String types = p.getProperty(name + ".types");
surefireBooter.addReport(className, constructParamObjects(params, types));
}
else if ((name.startsWith("testSuite.")) && (!name.endsWith(".params")) && (!name.endsWith(".types")))
{
String className = p.getProperty(name);
String params = p.getProperty(name + ".params");
String types = p.getProperty(name + ".types");
surefireBooter.addTestSuite(className, constructParamObjects(params, types));
}
else if (name.startsWith("classPathUrl."))
{
classPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 1)), p.getProperty(name));
}
else if (name.startsWith("surefireClassPathUrl."))
{
surefireClassPathUrls.put(Integer.valueOf(name.substring(name.indexOf('.') + 1)), p.getProperty(name));
}
else if (name.startsWith("surefireBootClassPathUrl."))
{
surefireBooter.addSurefireBootClassPathUrl(p.getProperty(name));
}
else if ("childDelegation".equals(name))
{
surefireBooter.childDelegation = Boolean.valueOf(p.getProperty("childDelegation")).booleanValue();
}
else if ("enableAssertions".equals(name))
{
surefireBooter.enableAssertions = Boolean.valueOf(p.getProperty("enableAssertions")).booleanValue();
}
else if ("useSystemClassLoader".equals(name))
{
boolean value = Boolean.valueOf(p.getProperty("useSystemClassLoader")).booleanValue();
surefireBooter.forkConfiguration.setUseSystemClassLoader(value);
}
else if ("useManifestOnlyJar".equals(name))
{
boolean value = Boolean.valueOf(p.getProperty("useManifestOnlyJar")).booleanValue();
surefireBooter.forkConfiguration.setUseManifestOnlyJar(value);
}
else if ("failIfNoTests".equals(name))
{
boolean value = Boolean.valueOf(p.getProperty("failIfNoTests")).booleanValue();
surefireBooter.setFailIfNoTests(value);
}
}
for (Iterator cpi = classPathUrls.keySet().iterator(); cpi.hasNext();)
{
String url = (String)classPathUrls.get(cpi.next());
surefireBooter.addClassPathUrl(url);
}
for (Iterator scpi = surefireClassPathUrls.keySet().iterator(); scpi.hasNext();)
{
String url = (String)surefireClassPathUrls.get(scpi.next());
surefireBooter.addSurefireClassPathUrl(url);
}
String testSet = p.getProperty("testSet");
int result;
int result;
if (testSet != null) {
result = surefireBooter.runSuitesInProcess(testSet, p);
} else {
result = surefireBooter.runSuitesInProcess();
}
surefireBooter.writePropertiesFile(surefirePropertiesFile, "surefire", p);
System.exit(result);
}
catch (Throwable t)
{
t.printStackTrace(System.err);
System.exit(1);
}
}
public void setChildDelegation(boolean childDelegation)
{
this.childDelegation = childDelegation;
}
private ForkingStreamConsumer getForkingStreamConsumer(boolean showHeading, boolean showFooter, boolean redirectTestOutputToFile)
{
OutputConsumer outputConsumer = new StandardOutputConsumer();
if (redirectTestOutputToFile) {
outputConsumer = new FileOutputConsumerProxy(outputConsumer, getReportsDirectory());
}
if (!showHeading) {
outputConsumer = new SupressHeaderOutputConsumerProxy(outputConsumer);
}
if (!showFooter) {
outputConsumer = new SupressFooterOutputConsumerProxy(outputConsumer);
}
return new ForkingStreamConsumer(outputConsumer);
}
public void setEnableAssertions(boolean enableAssertions)
{
this.enableAssertions = enableAssertions;
}
public void setForkedProcessTimeoutInSeconds(int forkedProcessTimeoutInSeconds)
{
this.forkedProcessTimeoutInSeconds = forkedProcessTimeoutInSeconds;
}
TestNGExecutor类代码:
public class TestNGExecutor
{
public static void run(Class[] testClasses, String testSourceDirectory, Map options, ArtifactVersion version, String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory)
throws TestSetFailedException
{
TestNG testng = new TestNG(true);
Configurator configurator = getConfigurator(version);
configurator.configure(testng, options);
postConfigure(testng, testSourceDirectory, classifier, reportManager, suite, reportsDirectory);
testng.setTestClasses(testClasses);
testng.run();
}
public static void run(List suiteFiles, String testSourceDirectory, Map options, ArtifactVersion version, String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory)
throws TestSetFailedException
{
TestNG testng = new TestNG(true);
Configurator configurator = getConfigurator(version);
configurator.configure(testng, options);
postConfigure(testng, testSourceDirectory, classifier, reportManager, suite, reportsDirectory);
testng.setTestSuites(suiteFiles);
testng.run();
}
private static Configurator getConfigurator(ArtifactVersion version)
throws TestSetFailedException
{
try
{
VersionRange range = VersionRange.createFromVersionSpec("[4.7,5.1]");
if (range.containsVersion(version)) {
return new TestNG4751Configurator();
}
range = VersionRange.createFromVersionSpec("[5.2]");
if (range.containsVersion(version)) {
return new TestNG52Configurator();
}
range = VersionRange.createFromVersionSpec("[5.3,)");
if (range.containsVersion(version)) {
return new TestNGMapConfigurator();
}
throw new TestSetFailedException("Unknown TestNG version " + version);
}
catch (InvalidVersionSpecificationException invsex)
{
throw new TestSetFailedException("Bug in plugin. Please report it with the attached stacktrace", invsex);
}
}
private static void postConfigure(TestNG testNG, String sourcePath, String classifier, ReporterManager reportManager, SurefireTestSuite suite, File reportsDirectory)
throws TestSetFailedException
{
testNG.setVerbose(0);
TestNGReporter reporter = createTestNGReporter(reportManager, suite);
testNG.addListener(reporter);
if (sourcePath != null) {
testNG.setSourcePath(sourcePath);
}
testNG.setOutputDirectory(reportsDirectory.getAbsolutePath());
}
private static TestNGReporter createTestNGReporter(ReporterManager reportManager, SurefireTestSuite suite)
{
try
{
Class.forName("org.testng.internal.IResultListener");
Class c = Class.forName("org.apache.maven.surefire.testng.ConfigurationAwareTestNGReporter");
try
{
Constructor ctor = c.getConstructor(new Class[] { ReporterManager.class, SurefireTestSuite.class });
return (TestNGReporter)ctor.newInstance(new Object[] { reportManager, suite });
}
catch (Exception e)
{
throw new RuntimeException("Bug in ConfigurationAwareTestNGReporter", e);
}
return new TestNGReporter(reportManager);
}
catch (ClassNotFoundException e) {}
}
private static void attachNonStandardReporter(TestNG testNG, String className)
{
try
{
Class c = Class.forName(className);
if (IReporter.class.isAssignableFrom(c)) {
testNG.addListener(c.newInstance());
}
}
catch (Exception e) {}
}
}
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();
}
}
}
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 value
for (XmlSuite xmlSuite : m_suites) {
createSuiteRunners(suiteRunnerMap, xmlSuite);
}
//
// Run suites
//
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());
}
} 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 execution
DynamicGraph<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 parallel
pooledExecutor.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();
}