All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fitnesse.testrunner.MultipleTestsRunner Maven / Gradle / Ivy

// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.testrunner;

import fitnesse.testrunner.run.RunCoordinator;
import fitnesse.testrunner.run.TestRun;
import fitnesse.testsystems.Assertion;
import fitnesse.testsystems.ClassPath;
import fitnesse.testsystems.CompositeExecutionLogListener;
import fitnesse.testsystems.Descriptor;
import fitnesse.testsystems.ExceptionResult;
import fitnesse.testsystems.ExecutionLogListener;
import fitnesse.testsystems.TestExecutionException;
import fitnesse.testsystems.TestPage;
import fitnesse.testsystems.TestResult;
import fitnesse.testsystems.TestSummary;
import fitnesse.testsystems.TestSystem;
import fitnesse.testsystems.TestSystemFactory;
import fitnesse.testsystems.TestSystemListener;
import fitnesse.testsystems.slim.TestingInterruptedException;
import util.FileUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class MultipleTestsRunner implements Stoppable {
  private final TestRun run;
  private final CompositeFormatter formatters;

  private final TestSystemFactory testSystemFactory;
  private final CompositeExecutionLogListener executionLogListener;

  private volatile boolean isStopped = false;

  private boolean runInProcess;
  private boolean enableRemoteDebug;

  private final AtomicInteger testsInProgressCount = new AtomicInteger();

  public MultipleTestsRunner(TestRun run, TestSystemFactory testSystemFactory) {
    this.testSystemFactory = testSystemFactory;
    this.formatters = new CompositeFormatter();
    this.executionLogListener = new CompositeExecutionLogListener();
    this.run = run;
  }

  public void setRunInProcess(boolean runInProcess) {
    this.runInProcess = runInProcess;
  }

  public void setEnableRemoteDebug(boolean enableRemoteDebug) {
    this.enableRemoteDebug = enableRemoteDebug;
  }

  public void addTestSystemListener(TestSystemListener listener) {
    this.formatters.addTestSystemListener(listener);
  }

  public void addExecutionLogListener(ExecutionLogListener listener) {
    executionLogListener.addExecutionLogListener(listener);
  }

  public void executeTestPages() throws TestExecutionException {
    MultipleTestsCoordinator coordinator = new MultipleTestsCoordinator();
    try {
      run.executeTestPages(coordinator);
    } catch (Exception e) {
      executionLogListener.exceptionOccurred(e);
      throw new TestingInterruptedException(e);
    } finally {
      allTestingComplete();
    }
  }

  @Override
  public void stop() {
    boolean wasNotStopped = isNotStopped();
    isStopped = true;

    if (wasNotStopped) {
      run.stop();
    }
  }

  private void allTestingComplete() {
    FileUtil.close(formatters);
  }

  private class MultipleTestsCoordinator implements RunCoordinator {

    @Override
    public boolean isNotStopped() {
      return MultipleTestsRunner.this.isNotStopped();
    }

    @Override
    public int announceTestStarted() {
      return testsInProgressCount.getAndIncrement();
    }

    @Override
    public void reportException(Exception e) {
      executionLogListener.exceptionOccurred(e);
    }

    @Override
    public TestSystem startTestSystem(final WikiPageIdentity identity, final List testPages) {
      Descriptor descriptor = new Descriptor() {
        private ClassPath classPath;

        @Override
        public String getTestSystem() {
          return identity.testSystem();
        }

        @Override
        public String getTestSystemType() {
          return getTestSystem().split(":")[0];
        }

        @Override
        public ClassPath getClassPath() {
          if (classPath == null) {
            List paths = new ArrayList<>();
            for (TestPage testPage: testPages) {
              paths.add(testPage.getClassPath());
            }
            classPath = new ClassPath(paths);
          }
          return classPath;
        }

        @Override
        public boolean runInProcess() {
          return runInProcess;
        }

        @Override
        public boolean isDebug() {
          return enableRemoteDebug;
        }

        @Override
        public String getVariable(String name) {
          return identity.getVariable(name);
        }

        @Override
        public ExecutionLogListener getExecutionLogListener() {
          return executionLogListener;
        }
      };

      InternalTestSystemListener internalTestSystemListener = new InternalTestSystemListener();
      try {
        TestSystem testSystem = testSystemFactory.create(descriptor);

        testSystem.addTestSystemListener(internalTestSystemListener);
        testSystem.start();
        return testSystem;
      } catch (Exception e) {
        formatters.unableToStartTestSystem(descriptor.getTestSystem(), e);
        return null;
      }
    }

    @Override
    public void waitForNoTestsInProgress() throws TestingInterruptedException {
      // TODO: use testSystemStopped event to wait for tests to end.
      while (testsInProgressCount.get() > 0 && isNotStopped())
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          throw new TestingInterruptedException("Interrupted while waiting for test results", e);
        }
    }

    @Override
    public void announceTotalTestsToRun(int toRun) {
      formatters.announceNumberTestsToRun(toRun);
    }
  }

  private class InternalTestSystemListener implements TestSystemListener {
    @Override
    public void testSystemStarted(TestSystem testSystem) {
      formatters.testSystemStarted(testSystem);
    }

    @Override
    public void testOutputChunk(TestPage testPage, String output) {
      formatters.testOutputChunk(testPage, output);
    }

    @Override
    public void testStarted(TestPage testPage) {
      formatters.testStarted(testPage);
    }

    @Override
    public void testComplete(TestPage testPage, TestSummary testSummary) {
      formatters.testComplete(testPage, testSummary);
      testsInProgressCount.getAndDecrement();
    }

    @Override
    public void testSystemStopped(TestSystem testSystem, Throwable cause) {
      formatters.testSystemStopped(testSystem, cause);

      if (cause != null) {
        executionLogListener.exceptionOccurred(cause);
        stop();
      }
    }

    @Override
    public void testAssertionVerified(Assertion assertion, TestResult testResult) {
      formatters.testAssertionVerified(assertion, testResult);
    }

    @Override
    public void testExceptionOccurred(Assertion assertion, ExceptionResult exceptionResult) {
      formatters.testExceptionOccurred(assertion, exceptionResult);
    }
  }

  private boolean isNotStopped() {
    return !isStopped;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy