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

fitnesse.junit.FitNesseRunner Maven / Gradle / Ivy

There is a newer version: 20181217
Show newest version
package fitnesse.junit;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import fitnesse.ConfigurationParameter;
import fitnesse.ContextConfigurator;
import fitnesse.FitNesseContext;
import fitnesse.plugins.PluginException;
import fitnesse.slim.instructions.SystemExitSecurityManager;
import fitnesse.testrunner.MultipleTestsRunner;
import fitnesse.testrunner.PagesByTestSystem;
import fitnesse.testrunner.SuiteContentsFinder;
import fitnesse.testsystems.ConsoleExecutionLogListener;
import fitnesse.testsystems.TestExecutionException;
import fitnesse.testsystems.TestSummary;
import fitnesse.wiki.PageCrawler;
import fitnesse.wiki.PathParser;
import fitnesse.wiki.WikiPage;
import fitnesse.wiki.WikiPagePath;

import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.InitializationError;

import static org.junit.Assert.*;

public class FitNesseRunner extends ParentRunner {
  /**
   * The Suite annotation specifies the name of the Fitnesse suite
   * (or single page) to be run, e.g.: MySuite.MySubSuite
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface Suite {

    String value() default "";
    String systemProperty() default "";
  }
  /**
   * The DebugMode annotation specifies whether the test is run
   * with the REST debug option. Default is true
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface DebugMode {

    boolean value();
  }

  /**
   * The PreventSystemExit annotation specifies whether the {@link SystemExitSecurityManager} must be to prevent {@link System#exit(int)} calls. Default is false
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface PreventSystemExit {

    boolean value() default true;
  }

  /**
   * The SuiteFilter annotation specifies the suite filter of the Fitnesse suite
   * to be run, e.g.: fasttests
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface SuiteFilter {

    String value() default "";
    String systemProperty() default "";
    boolean andStrategy() default false;
  }
  /**
   * The ExcludeSuiteFilter annotation specifies a filter for excluding tests from the Fitnesse suite
   * to be run, e.g.: slowtests
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface ExcludeSuiteFilter {

    String value();
    String systemProperty() default "";
  }
  /**
   * The FitnesseDir annotation specifies the absolute or relative
   * path to the directory in which FitNesseRoot can be found. You can either specify
   * 
    *
  • a relative or absolute path directly, e.g.: @FitnesseDir("/parentOfFitNesseRoot"), * or you can specify *
  • a system property the content of which will be taken as base dir and * optionally give a path extension, e.g.: * @FitnesseDir(systemProperty = "fitnesse.root.dir.parent")
  • *
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FitnesseDir { String value() default ""; String systemProperty() default ""; String fitNesseRoot() default ContextConfigurator.DEFAULT_ROOT; } /** * The OutputDir annotation specifies where the html reports of * run suites and tests will be found after running them. You can either specify *
    *
  • a relative or absolute path directly, e.g.: @OutputDir("/tmp/trinidad-results"), * or you can specify *
  • a system property the content of which will be taken as base dir and * optionally give a path extension, e.g.: * @OutputDir(systemProperty = "java.io.tmpdir", pathExtension = "trinidad-results")
  • *
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface OutputDir { String value() default ""; String systemProperty() default ""; String pathExtension() default ""; } /** * The Port annotation specifies the port used by the FitNesse * server. Default is the standard FitNesse port. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Deprecated public @interface Port { int value() default 0; String systemProperty() default ""; } /** * The ConfigFile annotation specifies the configuration file to load. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ConfigFile { String value(); } private Class suiteClass; private String suiteName; private String outputDir; private String suiteFilter; private boolean suiteFilterAndStrategy; private String excludeSuiteFilter; private boolean debugMode; private boolean preventSystemExit; private FitNesseContext context; private DescriptionFactory descriptionFactory; private List children; public FitNesseRunner(Class suiteClass) throws InitializationError { super(suiteClass); descriptionFactory = new DescriptionFactory(); } @Override protected void collectInitializationErrors(List errors) { // called by superclass' constructor super.collectInitializationErrors(errors); this.suiteClass = getTestClass().getJavaClass(); try { this.suiteName = getSuiteName(suiteClass); } catch (Exception e) { errors.add(e); } try { this.outputDir = getOutputDir(suiteClass); } catch (Exception e) { errors.add(e); } try { this.suiteFilter = getSuiteFilter(suiteClass); } catch (Exception e) { errors.add(e); } try { this.suiteFilterAndStrategy = getSuiteFilterAndStrategy(suiteClass); } catch (Exception e) { errors.add(e); } try { this.excludeSuiteFilter = getExcludeSuiteFilter(suiteClass); } catch (Exception e) { errors.add(e); } try { this.debugMode = useDebugMode(suiteClass); } catch (Exception e) { errors.add(e); } try { this.preventSystemExit = shouldPreventSystemExit(suiteClass); } catch (Exception e) { errors.add(e); } try { this.context = createContext(suiteClass); } catch (Exception e) { errors.add(e); } } protected FitNesseContext createContext(Class suiteClass) throws Exception { return initContextConfigurator().makeFitNesseContext(); } protected String getSuiteName(Class klass) throws InitializationError { Suite suiteAnnotation = klass.getAnnotation(Suite.class); if (suiteAnnotation == null) { throw new InitializationError("There must be a @Suite annotation"); } if (!"".equals(suiteAnnotation.value())) { return suiteAnnotation.value(); } if (!"".equals(suiteAnnotation.systemProperty())) { return System.getProperty(suiteAnnotation.systemProperty()); } throw new InitializationError( "In annotation @Suite you have to specify either 'value' or 'systemProperty'"); } protected String getOutputDir(Class klass) throws InitializationError { OutputDir outputDirAnnotation = klass.getAnnotation(OutputDir.class); if (outputDirAnnotation == null) { throw new InitializationError("There must be a @OutputDir annotation"); } if (!"".equals(outputDirAnnotation.value())) { return outputDirAnnotation.value(); } if (!"".equals(outputDirAnnotation.systemProperty())) { String baseDir = System.getProperty(outputDirAnnotation.systemProperty()); File outputDir = new File(baseDir, outputDirAnnotation.pathExtension()); return outputDir.getAbsolutePath(); } throw new InitializationError( "In annotation @OutputDir you have to specify either 'value' or 'systemProperty'"); } protected String getSuiteFilter(Class klass) throws Exception { SuiteFilter suiteFilterAnnotation = klass.getAnnotation(SuiteFilter.class); if (suiteFilterAnnotation == null) { return null; } if (!"".equals(suiteFilterAnnotation.value())) { return suiteFilterAnnotation.value(); } if (!"".equals(suiteFilterAnnotation.systemProperty())) { return System.getProperty(suiteFilterAnnotation.systemProperty()); } throw new InitializationError( "In annotation @SuiteFilter you have to specify either 'value' or 'systemProperty'"); } protected boolean getSuiteFilterAndStrategy(Class klass) throws Exception { SuiteFilter suiteFilterAnnotation = klass.getAnnotation(SuiteFilter.class); if (suiteFilterAnnotation == null) { return false; } return suiteFilterAnnotation.andStrategy(); } protected String getExcludeSuiteFilter(Class klass) throws Exception { ExcludeSuiteFilter excludeSuiteFilterAnnotation = klass.getAnnotation(ExcludeSuiteFilter.class); if (excludeSuiteFilterAnnotation == null) { return null; } if (!"".equals(excludeSuiteFilterAnnotation.value())) { return excludeSuiteFilterAnnotation.value(); } if (!"".equals(excludeSuiteFilterAnnotation.systemProperty())) { return System.getProperty(excludeSuiteFilterAnnotation.systemProperty()); } throw new InitializationError( "In annotation @ExcludeSuiteFilter you have to specify either 'value' or 'systemProperty'"); } protected boolean useDebugMode(Class klass) throws Exception { DebugMode debugModeAnnotation = klass.getAnnotation(DebugMode.class); if (null == debugModeAnnotation) { return true; } return debugModeAnnotation.value(); } protected boolean shouldPreventSystemExit(Class klass) throws Exception { PreventSystemExit preventSystemExitAnnotation = klass.getAnnotation(PreventSystemExit.class); if (null == preventSystemExitAnnotation) { return true; } return preventSystemExitAnnotation.value(); } protected String getFitNesseDir(Class klass) throws InitializationError { FitnesseDir fitnesseDirAnnotation = klass.getAnnotation(FitnesseDir.class); if (fitnesseDirAnnotation == null) { throw new InitializationError("There must be a @FitnesseDir annotation"); } if (!"".equals(fitnesseDirAnnotation.value())) { return fitnesseDirAnnotation.value(); } if (!"".equals(fitnesseDirAnnotation.systemProperty())) { String baseDir = System.getProperty(fitnesseDirAnnotation.systemProperty()); File outputDir = new File(baseDir); return outputDir.getAbsolutePath(); } throw new InitializationError( "In annotation @FitnesseDir you have to specify either 'value' or 'systemProperty'"); } protected String getFitNesseRoot(Class klass) { FitnesseDir fitnesseDirAnnotation = klass.getAnnotation(FitnesseDir.class); return fitnesseDirAnnotation.fitNesseRoot(); } public int getPort(Class klass) { Port portAnnotation = klass.getAnnotation(Port.class); if (null == portAnnotation) { return 0; } int lport = portAnnotation.value(); if (!"".equals(portAnnotation.systemProperty())) { lport = Integer.getInteger(portAnnotation.systemProperty(), lport); } return lport; } protected File getConfigFile(String rootPath, Class klass) { ConfigFile configFileAnnotation = klass.getAnnotation(ConfigFile.class); if (null == configFileAnnotation) { return new File(rootPath, ContextConfigurator.DEFAULT_CONFIG_FILE); } return new File(configFileAnnotation.value()); } @Override protected Description describeChild(WikiPage child) { return getDescriptionFactory().createDescription(suiteClass, child); } @Override protected List getChildren() { if (this.children == null) { this.children = initChildren(); } return this.children; } @Override public void run(final RunNotifier notifier) { if (isFilteredForChildTest()) { super.run(notifier); } else { runPages(children, notifier); } } private boolean isFilteredForChildTest() { return getDescription().getChildren().size() < getChildren().size(); } @Override protected void runChild(WikiPage page, RunNotifier notifier) { runPages(listOf(page), notifier); } protected void runPages(Listpages, final RunNotifier notifier) { MultipleTestsRunner testRunner = createTestRunner(pages); addTestSystemListeners(notifier, testRunner, suiteClass, getDescriptionFactory()); addExecutionLogListener(notifier, testRunner, suiteClass); System.setProperty(SystemExitSecurityManager.PREVENT_SYSTEM_EXIT, String.valueOf(preventSystemExit)); try { executeTests(testRunner); } catch (AssertionError | Exception e) { Description description = getDescriptionFactory().createSuiteDescription(suiteClass); notifier.fireTestFailure(new Failure(description, e)); } } protected void addTestSystemListeners(RunNotifier notifier, MultipleTestsRunner testRunner, Class suiteClass, DescriptionFactory descriptionFactory) { testRunner.addTestSystemListener(new JUnitRunNotifierResultsListener(notifier, suiteClass, descriptionFactory)); } protected void addExecutionLogListener(RunNotifier notifier, MultipleTestsRunner testRunner, Class suiteClass) { testRunner.addExecutionLogListener(new ConsoleExecutionLogListener()); } protected List initChildren() { WikiPage suiteRoot = getSuiteRootPage(); if (suiteRoot == null) { throw new IllegalArgumentException("No page " + this.suiteName); } List children; if (suiteRoot.getData().hasAttribute("Suite")) { children = new SuiteContentsFinder(suiteRoot, getSuiteFilter(), context.getRootPage()).getAllPagesToRunForThisSuite(); } else { children = Collections.singletonList(suiteRoot); } return children; } private fitnesse.testrunner.SuiteFilter getSuiteFilter() { return new fitnesse.testrunner.SuiteFilter(getOrSuiteFilter(), excludeSuiteFilter, getAndSuiteFilter(), null); } private String getOrSuiteFilter() { return suiteFilterAndStrategy ? null : suiteFilter; } private String getAndSuiteFilter() { return suiteFilterAndStrategy ? suiteFilter : null; } protected ContextConfigurator initContextConfigurator() throws InitializationError { String rootPath = getFitNesseDir(suiteClass); String fitNesseRoot = getFitNesseRoot(suiteClass); int port = getPort(suiteClass); File configFile = getConfigFile(rootPath, suiteClass); return ContextConfigurator.systemDefaults() .updatedWith(System.getProperties()) .updatedWith(ConfigurationParameter.loadProperties(configFile)) .updatedWith(ConfigurationParameter.makeProperties( ConfigurationParameter.PORT, port, ConfigurationParameter.ROOT_PATH, rootPath, ConfigurationParameter.ROOT_DIRECTORY, fitNesseRoot, ConfigurationParameter.OMITTING_UPDATES, true)); } private WikiPage getSuiteRootPage() { WikiPagePath path = PathParser.parse(this.suiteName); PageCrawler crawler = context.getRootPage().getPageCrawler(); return crawler.getPage(path); } private MultipleTestsRunner createTestRunner(List pages) { final PagesByTestSystem pagesByTestSystem = new PagesByTestSystem(pages, context.getRootPage()); MultipleTestsRunner runner = new MultipleTestsRunner(pagesByTestSystem, context.testSystemFactory); runner.setRunInProcess(debugMode); return runner; } private void executeTests(MultipleTestsRunner testRunner) throws IOException, TestExecutionException { JavaFormatter testFormatter = new JavaFormatter(suiteName); testFormatter.setResultsRepository(new JavaFormatter.FolderResultsRepository(outputDir)); testRunner.addTestSystemListener(testFormatter); testRunner.executeTestPages(); TestSummary summary = testFormatter.getTotalSummary(); assertTrue(msgAtLeastOneTest(suiteName, summary), summary.getRight() > 0 || summary.getWrong() > 0 || summary.getExceptions() > 0); } private String msgAtLeastOneTest(String pageName, TestSummary summary) { return MessageFormat.format("at least one test executed in {0}\n{1}", pageName, summary.toString()); } private List listOf(WikiPage page) { List list = new ArrayList<>(1); list.add(page); return list; } public DescriptionFactory getDescriptionFactory() { return descriptionFactory; } public void setDescriptionFactory(DescriptionFactory descriptionFactory) { this.descriptionFactory = descriptionFactory; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy