surefire 拉起 junit 单元测试类 源码阅读(三)

本文分析了一次Java单元测试中出现的NullPointerException异常及其堆栈跟踪,深入探讨了异常产生的原因,并涉及了反射调用和测试框架的具体实现。

java.lang.reflect.InvocationTargetException
	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 ut.com.suning.common.UnitTestHelper.invokPrivate(UnitTestHelper.java:36)
	at ut.com.suning.scus.common.rule.PublicRuleUtilsTest.testTransToMdmCityCode(PublicRuleUtilsTest.java:632)
	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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:63)
	at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)
	at org.junit.rules.RunRules.evaluate(RunRules.java:18)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
	at org.testng.junit.JUnit4TestRunner.start(JUnit4TestRunner.java:81)
	at org.testng.junit.JUnit4TestRunner.run(JUnit4TestRunner.java:69)
	at org.testng.TestRunner$1.run(TestRunner.java:682)
	at org.testng.TestRunner.runWorkers(TestRunner.java:1005)
	at org.testng.TestRunner.privateRunJUnit(TestRunner.java:713)
	at org.testng.TestRunner.run(TestRunner.java:614)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
	at org.testng.SuiteRunner.run(SuiteRunner.java:254)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
	at org.testng.TestNG.run(TestNG.java:1057)
	at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)
	at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:212)
	at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
	at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
	at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.lang.NullPointerException
	at com.suning.scus.common.rule.PublicRuleUtils.transToMdmCityCode(PublicRuleUtils.java:161)
	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.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl$1.invoke(MockitoMethodInvocationControl.java:242)
	at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
	at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:192)
	at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:124)
	at org.powermock.core.MockGateway.methodCall(MockGateway.java:63)
	at com.suning.scus.common.rule.PublicRuleUtils.transToMdmCityCode(PublicRuleUtils.java)
	... 51 more

-> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
-> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
-> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
-> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
-> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
-> org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:63)
-> org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)
-> org.junit.rules.RunRules.evaluate(RunRules.java:18)
-> org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
-> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
-> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
-> org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
-> org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
-> org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
-> org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
-> org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
-> org.junit.runners.ParentRunner.run(ParentRunner.java:300)
-> org.junit.runner.JUnitCore.run(JUnitCore.java:157)
-> org.junit.runner.JUnitCore.run(JUnitCore.java:136)
-> org.testng.junit.JUnit4TestRunner.start(JUnit4TestRunner.java:81)
-> org.testng.junit.JUnit4TestRunner.run(JUnit4TestRunner.java:69)
-> org.testng.TestRunner$1.run(TestRunner.java:682)
-> org.testng.TestRunner.runWorkers(TestRunner.java:1005)
-> org.testng.TestRunner.privateRunJUnit(TestRunner.java:713)
-> org.testng.TestRunner.run(TestRunner.java:614)

 -> org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)

 -> org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:212)
 -> org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
 -> org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
 -> org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
 -> org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
 -> org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)

ForkedBooter.invokeProviderInSameClassLoader 很关键的识别 testng 和junit

  private static SurefireProvider createProviderInCurrentClassloader( StartupConfiguration startupConfiguration1,
                                                                       boolean isInsideFork,
                                                                       ProviderConfiguration providerConfiguration,
                                                                       Object reporterManagerFactory1 )
    {
        BaseProviderFactory bpf = new BaseProviderFactory( (ReporterFactory) reporterManagerFactory1, isInsideFork );
        bpf.setTestRequest( providerConfiguration.getTestSuiteDefinition() );
        bpf.setReporterConfiguration( providerConfiguration.getReporterConfiguration() );
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        bpf.setClassLoaders( classLoader );
        bpf.setTestArtifactInfo( providerConfiguration.getTestArtifact() );
        bpf.setProviderProperties( providerConfiguration.getProviderProperties() );
        bpf.setRunOrderParameters( providerConfiguration.getRunOrderParameters() );
        bpf.setDirectoryScannerParameters( providerConfiguration.getDirScannerParams() );
        bpf.setMainCliOptions( providerConfiguration.getMainCliOptions() );
        bpf.setSkipAfterFailureCount( providerConfiguration.getSkipAfterFailureCount() );
        bpf.setShutdown( providerConfiguration.getShutdown() );
        String providerClass = startupConfiguration1.getActualClassName();
        return (SurefireProvider) instantiateOneArg( classLoader, providerClass, ProviderParameters.class, bpf );
    }

ReflectionUtils类代码:

public final class ReflectionUtils
{
  private static final Class[] NO_ARGS = new Class[0];
  private static final Object[] NO_ARGS_VALUES = new Object[0];
  
  private ReflectionUtils()
  {
    throw new IllegalStateException("no instantiable constructor");
  }
  
  public static Method getMethod(Object instance, String methodName, Class<?>... parameters)
  {
    return getMethod(instance.getClass(), methodName, parameters);
  }
  
  public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameters)
  {
    try
    {
      return clazz.getMethod(methodName, parameters);
    }
    catch (NoSuchMethodException e)
    {
      throw new RuntimeException("When finding method " + methodName, e);
    }
  }
  
  public static Method tryGetMethod(Class<?> clazz, String methodName, Class<?>... parameters)
  {
    try
    {
      return clazz.getMethod(methodName, parameters);
    }
    catch (NoSuchMethodException e) {}
    return null;
  }
  
  public static Object invokeGetter(Object instance, String methodName)
  {
    Method method = getMethod(instance, methodName, NO_ARGS);
    return invokeMethodWithArray(instance, method, NO_ARGS_VALUES);
  }
  
  public static Constructor getConstructor(Class<?> clazz, Class<?>... arguments)
  {
    try
    {
      return clazz.getConstructor(arguments);
    }
    catch (NoSuchMethodException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static Object newInstance(Constructor constructor, Object... params)
  {
    try
    {
      return constructor.newInstance(params);
    }
    catch (InvocationTargetException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (InstantiationException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static <T> T instantiate(ClassLoader classLoader, String classname, Class<T> returnType)
  {
    try
    {
      Class<?> clazz = loadClass(classLoader, classname);
      return returnType.cast(clazz.newInstance());
    }
    catch (InstantiationException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static Object instantiateOneArg(ClassLoader classLoader, String className, Class<?> param1Class, Object param1)
  {
    try
    {
      Class<?> aClass = loadClass(classLoader, className);
      Constructor constructor = getConstructor(aClass, new Class[] { param1Class });
      return constructor.newInstance(new Object[] { param1 });
    }
    catch (InvocationTargetException e)
    {
      throw new SurefireReflectionException(e.getTargetException());
    }
    catch (InstantiationException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static Object instantiateTwoArgs(ClassLoader classLoader, String className, Class<?> param1Class, Object param1, Class param2Class, Object param2)
  {
    try
    {
      Class<?> aClass = loadClass(classLoader, className);
      Constructor constructor = getConstructor(aClass, new Class[] { param1Class, param2Class });
      return constructor.newInstance(new Object[] { param1, param2 });
    }
    catch (InvocationTargetException e)
    {
      throw new SurefireReflectionException(e.getTargetException());
    }
    catch (InstantiationException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static void invokeSetter(Object o, String name, Class<?> value1clazz, Object value)
  {
    Method setter = getMethod(o, name, new Class[] { value1clazz });
    invokeSetter(o, setter, value);
  }
  
  public static Object invokeSetter(Object target, Method method, Object value)
  {
    return invokeMethodWithArray(target, method, new Object[] { value });
  }
  
  public static Object invokeMethodWithArray(Object target, Method method, Object... args)
  {
    try
    {
      return method.invoke(target, args);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (InvocationTargetException e)
    {
      throw new SurefireReflectionException(e.getTargetException());
    }
  }
  
  public static Object invokeMethodWithArray2(Object target, Method method, Object... args)
    throws InvocationTargetException
  {
    try
    {
      return method.invoke(target, args);
    }
    catch (IllegalAccessException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
  
  public static Object instantiateObject(String className, Class[] types, Object[] params, ClassLoader classLoader)
  {
    Class<?> clazz = loadClass(classLoader, className);
    Constructor constructor = getConstructor(clazz, types);
    return newInstance(constructor, params);
  }
  
  public static Class<?> tryLoadClass(ClassLoader classLoader, String className)
  {
    try
    {
      return classLoader.loadClass(className);
    }
    catch (NoClassDefFoundError localNoClassDefFoundError) {}catch (ClassNotFoundException localClassNotFoundException) {}
    return null;
  }
  
  public static Class<?> loadClass(ClassLoader classLoader, String className)
  {
    try
    {
      return classLoader.loadClass(className);
    }
    catch (NoClassDefFoundError e)
    {
      throw new SurefireReflectionException(e);
    }
    catch (ClassNotFoundException e)
    {
      throw new SurefireReflectionException(e);
    }
  }
}

BaseProviderFactory代码类:

public class BaseProviderFactory
  implements DirectoryScannerParametersAware, ReporterConfigurationAware, SurefireClassLoadersAware, TestRequestAware, ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware, FailFastAware, ShutdownAware
{
  private static final int ROOT_CHANNEL = 0;
  private final ReporterFactory reporterFactory;
  private final boolean insideFork;
  private List<CommandLineOption> mainCliOptions = Collections.emptyList();
  private Map<String, String> providerProperties;
  private DirectoryScannerParameters directoryScannerParameters;
  private ReporterConfiguration reporterConfiguration;
  private RunOrderParameters runOrderParameters;
  private ClassLoader testClassLoader;
  private TestRequest testRequest;
  private TestArtifactInfo testArtifactInfo;
  private int skipAfterFailureCount;
  private Shutdown shutdown;
  
  public BaseProviderFactory(ReporterFactory reporterFactory, boolean insideFork)
  {
    this.reporterFactory = reporterFactory;
    this.insideFork = insideFork;
  }
  
  public DirectoryScanner getDirectoryScanner()
  {
    return this.directoryScannerParameters == null ? null : new DefaultDirectoryScanner(this.directoryScannerParameters.getTestClassesDirectory(), this.directoryScannerParameters.getIncludes(), this.directoryScannerParameters.getExcludes(), this.directoryScannerParameters.getSpecificTests());
  }
  
  public ScanResult getScanResult()
  {
    return DefaultScanResult.from(this.providerProperties);
  }
  
  private int getThreadCount()
  {
    String threadcount = (String)this.providerProperties.get("threadcount");
    return threadcount == null ? 1 : Math.max(Integer.parseInt(threadcount), 1);
  }
  
  public RunOrderCalculator getRunOrderCalculator()
  {
    return this.directoryScannerParameters == null ? null : new DefaultRunOrderCalculator(this.runOrderParameters, getThreadCount());
  }
  
  public ReporterFactory getReporterFactory()
  {
    return this.reporterFactory;
  }
  
  public void setDirectoryScannerParameters(DirectoryScannerParameters directoryScannerParameters)
  {
    this.directoryScannerParameters = directoryScannerParameters;
  }
  
  public void setReporterConfiguration(ReporterConfiguration reporterConfiguration)
  {
    this.reporterConfiguration = reporterConfiguration;
  }
  
  public void setClassLoaders(ClassLoader testClassLoader)
  {
    this.testClassLoader = testClassLoader;
  }
  
  public ConsoleLogger getConsoleLogger()
  {
    return this.insideFork ? new ForkingRunListener(this.reporterConfiguration.getOriginalSystemOut(), 0, this.reporterConfiguration.isTrimStackTrace()) : new DefaultDirectConsoleReporter(this.reporterConfiguration.getOriginalSystemOut());
  }
  
  public void setTestRequest(TestRequest testRequest)
  {
    this.testRequest = testRequest;
  }
  
  public DirectoryScannerParameters getDirectoryScannerParameters()
  {
    return this.directoryScannerParameters;
  }
  
  public ReporterConfiguration getReporterConfiguration()
  {
    return this.reporterConfiguration;
  }
  
  public TestRequest getTestRequest()
  {
    return this.testRequest;
  }
  
  public ClassLoader getTestClassLoader()
  {
    return this.testClassLoader;
  }
  
  public void setProviderProperties(Map<String, String> providerProperties)
  {
    this.providerProperties = providerProperties;
  }
  
  public Map<String, String> getProviderProperties()
  {
    return this.providerProperties;
  }
  
  public TestArtifactInfo getTestArtifactInfo()
  {
    return this.testArtifactInfo;
  }
  
  public void setTestArtifactInfo(TestArtifactInfo testArtifactInfo)
  {
    this.testArtifactInfo = testArtifactInfo;
  }
  
  public void setRunOrderParameters(RunOrderParameters runOrderParameters)
  {
    this.runOrderParameters = runOrderParameters;
  }
  
  public List<CommandLineOption> getMainCliOptions()
  {
    return this.mainCliOptions;
  }
  
  public void setMainCliOptions(List<CommandLineOption> mainCliOptions)
  {
    this.mainCliOptions = (mainCliOptions == null ? Collections.emptyList() : mainCliOptions);
  }
  
  public int getSkipAfterFailureCount()
  {
    return this.skipAfterFailureCount;
  }
  
  public void setSkipAfterFailureCount(int skipAfterFailureCount)
  {
    this.skipAfterFailureCount = skipAfterFailureCount;
  }
  
  public boolean isInsideFork()
  {
    return this.insideFork;
  }
  
  public Shutdown getShutdown()
  {
    return this.shutdown;
  }
  
  public void setShutdown(Shutdown shutdown)
  {
    this.shutdown = shutdown;
  }
RunResult 类:
public class RunResult
{
  private final int completedCount;
  private final int errors;
  private final int failures;
  private final int skipped;
  private final int flakes;
  private final String failure;
  private final boolean timeout;
  public static final int SUCCESS = 0;
  private static final int FAILURE = 255;
  private static final int NO_TESTS = 254;
  
  public static RunResult timeout(RunResult accumulatedAtTimeout)
  {
    return errorCode(accumulatedAtTimeout, accumulatedAtTimeout.getFailure(), true);
  }
  
  public static RunResult failure(RunResult accumulatedAtTimeout, Exception cause)
  {
    return errorCode(accumulatedAtTimeout, getStackTrace(cause), accumulatedAtTimeout.isTimeout());
  }
  
  private static RunResult errorCode(RunResult other, String failure, boolean timeout)
  {
    return new RunResult(other.getCompletedCount(), other.getErrors(), other.getFailures(), other.getSkipped(), failure, timeout);
  }
  
  public RunResult(int completedCount, int errors, int failures, int skipped)
  {
    this(completedCount, errors, failures, skipped, null, false);
  }
  
  public RunResult(int completedCount, int errors, int failures, int skipped, int flakes)
  {
    this(completedCount, errors, failures, skipped, flakes, null, false);
  }
  
  public RunResult(int completedCount, int errors, int failures, int skipped, String failure, boolean timeout)
  {
    this(completedCount, errors, failures, skipped, 0, failure, timeout);
  }
  
  public RunResult(int completedCount, int errors, int failures, int skipped, int flakes, String failure, boolean timeout)
  {
    this.completedCount = completedCount;
    this.errors = errors;
    this.failures = failures;
    this.skipped = skipped;
    this.failure = failure;
    this.timeout = timeout;
    this.flakes = flakes;
  }
  
  private static String getStackTrace(Exception e)
  {
    if (e == null) {
      return null;
    }
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PrintWriter pw = new PrintWriter(out);
    try
    {
      e.printStackTrace(pw);
    }
    finally
    {
      pw.close();
    }
    return new String(out.toByteArray());
  }
  
  public int getCompletedCount()
  {
    return this.completedCount;
  }
  
  public int getErrors()
  {
    return this.errors;
  }
  
  public int getFlakes()
  {
    return this.flakes;
  }
  
  public int getFailures()
  {
    return this.failures;
  }
  
  public int getSkipped()
  {
    return this.skipped;
  }
  
  public Integer getFailsafeCode()
  {
    if (this.completedCount == 0) {
      return Integer.valueOf(254);
    }
    if (!isErrorFree()) {
      return Integer.valueOf(255);
    }
    return null;
  }
  
  public boolean isErrorFree()
  {
    return (getFailures() == 0) && (getErrors() == 0);
  }
  
  public boolean isFailureOrTimeout()
  {
    return (this.timeout) || (isFailure());
  }
  
  public boolean isFailure()
  {
    return this.failure != null;
  }
  
  public String getFailure()
  {
    return this.failure;
  }
  
  public boolean isTimeout()
  {
    return this.timeout;
  }
  
  public RunResult aggregate(RunResult other)
  {
    String failureMessage = getFailure() != null ? getFailure() : other.getFailure();
    boolean timeout = (isTimeout()) || (other.isTimeout());
    int completed = getCompletedCount() + other.getCompletedCount();
    int fail = getFailures() + other.getFailures();
    int ign = getSkipped() + other.getSkipped();
    int err = getErrors() + other.getErrors();
    int flakes = getFlakes() + other.getFlakes();
    return new RunResult(completed, err, fail, ign, flakes, failureMessage, timeout);
  }
  
  public static RunResult noTestsRun()
  {
    return new RunResult(0, 0, 0, 0);
  }
  
  private Xpp3Dom create(String node, String value)
  {
    Xpp3Dom dom = new Xpp3Dom(node);
    dom.setValue(value);
    return dom;
  }
  
  private Xpp3Dom create(String node, int value)
  {
    return create(node, Integer.toString(value));
  }
  
  Xpp3Dom asXpp3Dom()
  {
    Xpp3Dom dom = new Xpp3Dom("failsafe-summary");
    Integer failsafeCode = getFailsafeCode();
    if (failsafeCode != null) {
      dom.setAttribute("result", Integer.toString(failsafeCode.intValue()));
    }
    dom.setAttribute("timeout", Boolean.toString(this.timeout));
    dom.addChild(create("completed", this.completedCount));
    dom.addChild(create("errors", this.errors));
    dom.addChild(create("failures", this.failures));
    dom.addChild(create("skipped", this.skipped));
    dom.addChild(create("failureMessage", this.failure));
    return dom;
  }
  
  public static RunResult fromInputStream(InputStream inputStream, String encoding)
    throws FileNotFoundException
  {
    Xpp3Dom dom = Xpp3DomBuilder.build(inputStream, encoding);
    boolean timeout = Boolean.parseBoolean(dom.getAttribute("timeout"));
    int completed = Integer.parseInt(dom.getChild("completed").getValue());
    int errors = Integer.parseInt(dom.getChild("errors").getValue());
    int failures = Integer.parseInt(dom.getChild("failures").getValue());
    int skipped = Integer.parseInt(dom.getChild("skipped").getValue());
    String failureMessage1 = dom.getChild("failureMessage").getValue();
    String failureMessage = StringUtils.isEmpty(failureMessage1) ? null : failureMessage1;
    return new RunResult(completed, errors, failures, skipped, failureMessage, timeout);
  }
  
  public void writeSummary(File summaryFile, boolean inProgress, String encoding)
    throws IOException
  {
    if (!summaryFile.getParentFile().isDirectory()) {
      summaryFile.getParentFile().mkdirs();
    }
    FileInputStream fin = null;
    FileWriter writer = null;
    try
    {
      RunResult mergedSummary = this;
      if ((summaryFile.exists()) && (inProgress))
      {
        fin = new FileInputStream(summaryFile);
        
        RunResult runResult = fromInputStream(new BufferedInputStream(fin), encoding);
        mergedSummary = mergedSummary.aggregate(runResult);
      }
      writer = new FileWriter(summaryFile);
      writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
      PrettyPrintXMLWriter prettyPrintXMLWriter = new PrettyPrintXMLWriter(writer);
      Xpp3DomWriter.write(prettyPrintXMLWriter, mergedSummary.asXpp3Dom());
    }
    finally
    {
      IOUtil.close(fin);
      IOUtil.close(writer);
    }
  }
  
  public boolean equals(Object o)
  {
    if (this == o) {
      return true;
    }
    if ((o == null) || (getClass() != o.getClass())) {
      return false;
    }
    RunResult runResult = (RunResult)o;
    if (this.completedCount != runResult.completedCount) {
      return false;
    }
    if (this.errors != runResult.errors) {
      return false;
    }
    if (this.failures != runResult.failures) {
      return false;
    }
    if (this.skipped != runResult.skipped) {
      return false;
    }
    if (this.timeout != runResult.timeout) {
      return false;
    }
    if (this.failure != null ? !this.failure.equals(runResult.failure) : runResult.failure != null) {
      return false;
    }
    return true;
  }
  
  public int hashCode()
  {
    int result = this.completedCount;
    result = 31 * result + this.errors;
    result = 31 * result + this.failures;
    result = 31 * result + this.skipped;
    result = 31 * result + (this.failure != null ? this.failure.hashCode() : 0);
    result = 31 * result + (this.timeout ? 1 : 0);
    return result;
  }
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值