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

org.specrunner.junit.SpecRunnerStatement Maven / Gradle / Ivy

package org.specrunner.junit;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
import org.specrunner.ISpecRunner;
import org.specrunner.SRServices;
import org.specrunner.configuration.IConfiguration;
import org.specrunner.configuration.IConfigurationFactory;
import org.specrunner.core.SpecRunnerPipelineUtils;
import org.specrunner.dumper.core.AbstractSourceDumperFile;
import org.specrunner.plugins.core.elements.PluginHtml;
import org.specrunner.result.IResultSet;
import org.specrunner.source.ISourceFactoryManager;
import org.specrunner.util.UtilLog;

/**
 * Generic statement for SpecRunner Junit extensions.
 * 
 * @author Thiago Santos
 * 
 */
public class SpecRunnerStatement extends Statement {
    /**
     * Output path.
     */
    public static final String PATH = System.getProperty("sr.output", "target/output/");

    /**
     * The test class.
     */
    private TestClass test;
    /**
     * The test instance.
     */
    private Object instance;

    /**
     * The input file.
     */
    private File input;

    /**
     * The output file.
     */
    private File output;

    /**
     * The testing object.
     * 
     * @param test
     *            The test meta-data.
     * @param instance
     *            The test instance.
     */
    public SpecRunnerStatement(TestClass test, Object instance) {
        this.test = test;
        this.instance = instance;
        Class clazz = test.getJavaClass();
        input = getFile(clazz);
        output = getOutput(clazz, input);
    }

    /**
     * Get the HTML file corresponding to the Java.
     * 
     * @param clazz
     *            The test class.
     * 
     * @return The input HTML file.
     */
    protected File getFile(Class clazz) {
        URL location = clazz.getProtectionDomain().getCodeSource().getLocation();
        String str = location.toString();
        str = str.replace("file:\\\\", "").replace("file:///", "").replace("file:\\", "").replace("file:/", "");
        Package pkg = clazz.getPackage();
        if (pkg == null) {
            throw new RuntimeException("Test classe must be in a package.");
        }
        // exact match
        String prefix = str + pkg.getName().replace(".", File.separator) + File.separator + clazz.getSimpleName();
        Set extensions = SRServices.get(ISourceFactoryManager.class).keySet();
        for (String s : extensions) {
            File tmp = new File(prefix + "." + s);
            if (tmp.exists()) {
                return tmp;
            }
        }
        // remove 'Test' part.
        prefix = str + pkg.getName().replace(".", File.separator) + File.separator + clazz.getSimpleName().replace("Test", "");
        for (String s : extensions) {
            File tmp = new File(prefix + "." + s);
            if (tmp.exists()) {
                return tmp;
            }
        }
        throw new RuntimeException("File with one of extensions '" + extensions + "' to " + prefix + " not found!");
    }

    /**
     * Get the output file.
     * 
     * @param clazz
     *            The test class.
     * @param input
     *            The input file.
     * @return The output file.
     */
    public File getOutput(Class clazz, File input) {
        return new File(new File(PATH + clazz.getPackage().getName().replace('.', File.separatorChar)).getAbsoluteFile(), input.getName());
    }

    @Override
    public void evaluate() throws Throwable {
        IConfiguration cfg = SRServices.get(IConfigurationFactory.class).newConfiguration();
        ISpecRunner srunner = SRServices.getSpecRunner();
        IResultSet result = srunner.run(input.getPath(), configure(cfg));
        if (result.getStatus().isError()) {
            throw new Exception("OUTPUT: " + output.getAbsoluteFile() + "\n" + result.asString());
        }
    }

    /**
     * Get expected messages if any.
     * 
     * @return The list of error messages.
     */
    protected ExpectedMessages getMessages() {
        Annotation[] ans = test.getAnnotations();
        for (Annotation an : ans) {
            if (an instanceof ExpectedMessages) {
                return (ExpectedMessages) an;
            }
        }
        return null;
    }

    /**
     * Set configuration.
     * 
     * @param cfg
     *            The configuration.
     * @return The configuration itself.
     * @throws Throwable
     *             On configuration errors.
     */
    protected IConfiguration configure(IConfiguration cfg) throws Throwable {
        Annotation[] ans = instance.getClass().getAnnotations();
        for (Annotation a : ans) {
            if (a instanceof SRRunnerOptions) {
                SRRunnerOptions options = (SRRunnerOptions) a;
                cfg.add(SpecRunnerPipelineUtils.PIPELINE_FILENAME, options.pipeline());
            }
        }
        cfg.add(PluginHtml.BEAN_NAME, instance);
        cfg.add(AbstractSourceDumperFile.FEATURE_OUTPUT_DIRECTORY, output.getParentFile());
        cfg.add(AbstractSourceDumperFile.FEATURE_OUTPUT_NAME, getOutputName(output.getName()));
        ExpectedMessages expected = getMessages();
        if (expected != null) {
            cfg.add(IResultSet.FEATURE_EXPECTED_MESSAGES, expected.value());
            cfg.add(IResultSet.FEATURE_EXPECTED_SORTED, expected.sorted());
        }
        Method[] ms = instance.getClass().getMethods();
        List candidates = new LinkedList();
        for (Method m : ms) {
            Configuration c = m.getAnnotation(Configuration.class);
            if (c != null) {
                candidates.add(m);
            }
        }
        for (Method m : candidates) {
            Class[] types = m.getParameterTypes();
            if (types.length == 1 && types[0] == IConfiguration.class) {
                m.invoke(instance, new Object[] { cfg });
            } else {
                if (UtilLog.LOG.isInfoEnabled()) {
                    UtilLog.LOG.info("Invalid @Configuration method '" + m + "'");
                }
            }
        }
        return cfg;
    }

    /**
     * Get the output name adjusted.
     * 
     * @param name
     *            The original name.
     * @return The adjusted name. ie. Excel (.xls,.xlsx) test files are
     *         transformed to HTML (.html).
     */
    public String getOutputName(String name) {
        if (name != null && name.contains(".") && !name.endsWith(".html")) {
            return name.substring(0, name.lastIndexOf('.')) + ".html";
        } else {
            return name;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy