Android Open Source - CucumberAndroidGradle Cucumber Instrumentation






From Project

Back to project page CucumberAndroidGradle.

License

The source code is released under:

Apache License

If you think the Android project CucumberAndroidGradle listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package cucumber.api.android;
/*from  w ww .jav  a  2 s. co m*/
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import cucumber.runtime.android.AndroidBackend;
import cucumber.runtime.android.AndroidClasspathMethodScanner;
import cucumber.runtime.android.AndroidFormatter;
import cucumber.runtime.android.AndroidResourceLoader;
import cucumber.runtime.Backend;
import cucumber.runtime.Runtime;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.model.*;
import ext.android.test.ClassPathPackageInfoSource;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class CucumberInstrumentation extends Instrumentation {
    public static final String ARGUMENT_TEST_CLASS = "class";
    public static final String ARGUMENT_TEST_PACKAGE = "package";
    public static final String REPORT_VALUE_ID = "InstrumentationTestRunner";
    public static final String REPORT_KEY_NUM_TOTAL = "numtests";
    public static final String REPORT_KEY_NUM_CURRENT = "current";
    public static final String REPORT_KEY_NAME_CLASS = "class";
    public static final String REPORT_KEY_NAME_TEST = "test";
    public static final int REPORT_VALUE_RESULT_START = 1;
    public static final int REPORT_VALUE_RESULT_ERROR = -1;
    public static final int REPORT_VALUE_RESULT_FAILURE = -2;
    public static final String REPORT_KEY_STACK = "stack";
    public static final String TAG = "cucumber-android";
    private RuntimeOptions mRuntimeOptions;
    private ResourceLoader mResourceLoader;
    private ClassLoader mClassLoader;
    private Runtime mRuntime;
    private String mPackageOfTests;
    private String mFeatures;

    @Override
    public void onCreate(Bundle arguments) {
        super.onCreate(arguments);

        Context context = getContext();
        mClassLoader = context.getClassLoader();

        // For glue and features either use the provided arguments or try to find a RunWithCucumber annotated class.
        // If nothing works, default values will be used instead.
        if (arguments != null &&
                (arguments.containsKey(ARGUMENT_TEST_CLASS) || arguments.containsKey(ARGUMENT_TEST_PACKAGE))) {

            String testClass = arguments.getString(ARGUMENT_TEST_CLASS);
            testClass = testClass != null ? testClass : "null";
            mPackageOfTests = arguments.getString(ARGUMENT_TEST_PACKAGE);

            try {
                Class<?> clazz = mClassLoader.loadClass(testClass);
                boolean annotationWasPresent = readRunWithCucumberAnnotation(clazz);

                // If the class is not RunWithCucumber annotated, maybe it's Cucumber annotated?
                if (!annotationWasPresent) {
                    SEARCH_ANNOTATION:
                    for (Method m : clazz.getMethods()) {
                        for (Annotation a : m.getAnnotations()) {
                            if (a.annotationType().getName().startsWith("cucumber") && mPackageOfTests == null) {
                                mPackageOfTests = testClass.substring(0, testClass.lastIndexOf("."));
                                break SEARCH_ANNOTATION;
                            }
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                Log.w(TAG, e.toString());
            }
        } else {
            ClassPathPackageInfoSource source = AndroidClasspathMethodScanner.classPathPackageInfoSource(context);
            for (Class<?> clazz : source.getPackageInfo(context.getPackageName()).getTopLevelClassesRecursive()) {
                if (readRunWithCucumberAnnotation(clazz)) break;
            }
        }

        Properties properties = new Properties();
        mPackageOfTests = mPackageOfTests != null ? mPackageOfTests : defaultGlue();
        mFeatures = mFeatures != null ? mFeatures : defaultFeatures();

        properties.setProperty("cucumber.options", String.format("-g %s %s", mPackageOfTests, mFeatures));
        mRuntimeOptions = new RuntimeOptions(properties);

        mResourceLoader = new AndroidResourceLoader(context);
        List<Backend> backends = new ArrayList<Backend>();
        backends.add(new AndroidBackend(this));
        mRuntime = new Runtime(mResourceLoader, mClassLoader, backends, mRuntimeOptions);

        start();
    }

    /**
     * @return true if the class is RunWithCucumber annotated, false otherwise
     */
    private boolean readRunWithCucumberAnnotation(Class<?> clazz) {
        RunWithCucumber annotation = clazz.getAnnotation(RunWithCucumber.class);
        if (annotation != null) {
            // isEmpty() only available in Android API 9+
            mPackageOfTests = annotation.glue().equals("") ? defaultGlue() : annotation.glue();
            mFeatures = annotation.features().equals("") ? defaultFeatures() : annotation.features();
            return true;
        }
        return false;
    }

    private String defaultFeatures() {
        return "features";
    }

    private String defaultGlue() {
        return getContext().getPackageName();
    }

    @Override
    public void onStart() {
        Looper.prepare();

        List<CucumberFeature> cucumberFeatures = mRuntimeOptions.cucumberFeatures(mResourceLoader);
        int numScenarios = 0;

        for (CucumberFeature feature : cucumberFeatures) {
            for (CucumberTagStatement statement : feature.getFeatureElements()) {
                if (statement instanceof CucumberScenario) {
                    numScenarios++;
                } else if (statement instanceof CucumberScenarioOutline) {
                    for (CucumberExamples examples : ((CucumberScenarioOutline) statement).getCucumberExamplesList()) {
                        for (ExamplesTableRow row : examples.getExamples().getRows()) {
                            numScenarios++;
                        }
                    }
                    numScenarios--; // subtract table header
                }
            }
        }

        AndroidReporter reporter = new AndroidReporter(numScenarios);
        mRuntimeOptions.formatters.clear();
        mRuntimeOptions.formatters.add(reporter);

        for (CucumberFeature cucumberFeature : cucumberFeatures) {
            Formatter formatter = mRuntimeOptions.formatter(mClassLoader);
            cucumberFeature.run(formatter, reporter, mRuntime);
        }
        Formatter formatter = mRuntimeOptions.formatter(mClassLoader);

        formatter.done();
        printSummary();
        formatter.close();

        finish(Activity.RESULT_OK, new Bundle());
    }

    private void printSummary() {
        for (Throwable t : mRuntime.getErrors()) {
            Log.e(TAG, t.toString());
        }
        for (String s : mRuntime.getSnippets()) {
            Log.w(TAG, s);
        }
    }

    /**
     * This class reports the current test-state back to the framework.
     * It also wraps the AndroidFormatter to intercept important callbacks.
     */
    private class AndroidReporter implements Formatter, Reporter {
        private final AndroidFormatter mFormatter;
        private final Bundle mResultTemplate;
        private Bundle mTestResult;
        private int mScenarioNum;
        private int mTestResultCode;
        private Feature mFeature;
        private Step mStep;

        public AndroidReporter(int numTests) {
            mFormatter = new AndroidFormatter(TAG);
            mResultTemplate = new Bundle();
            mResultTemplate.putString(Instrumentation.REPORT_KEY_IDENTIFIER, REPORT_VALUE_ID);
            mResultTemplate.putInt(REPORT_KEY_NUM_TOTAL, numTests);
        }

        @Override
        public void uri(String uri) {
            mFormatter.uri(uri);
        }

        @Override
        public void feature(Feature feature) {
            mFeature = feature;
            mFormatter.feature(feature);
        }

        @Override
        public void background(Background background) {
            mFormatter.background(background);
        }

        @Override
        public void scenario(Scenario scenario) {
            reportLastResult();
            mFormatter.scenario(scenario);
            beginScenario(scenario);
        }

        @Override
        public void scenarioOutline(ScenarioOutline scenarioOutline) {
            reportLastResult();
            mFormatter.scenarioOutline(scenarioOutline);
            beginScenario(scenarioOutline);
        }

        @Override
        public void examples(Examples examples) {
            mFormatter.examples(examples);
        }

        @Override
        public void step(Step step) {
            mStep = step;
            mFormatter.step(step);
        }

        @Override
        public void syntaxError(String state, String event, List<String> legalEvents, String uri, Integer line) {
            mFormatter.syntaxError(state, event, legalEvents, uri, line);
        }

        @Override
        public void eof() {
            reportLastResult();
            mFormatter.eof();
        }

        @Override
        public void done() {
            mFormatter.done();
        }

        @Override
        public void close() {
            mFormatter.close();
        }

        @Override
        public void embedding(String mimeType, byte[] data) {
        }

        @Override
        public void write(String text) {
        }

        @Override
        public void before(Match match, Result result) {
        }

        @Override
        public void after(Match match, Result result) {
        }

        @Override
        public void match(Match match) {
        }

        private void beginScenario(TagStatement scenario) {
            String testClass = String.format("%s %s", mFeature.getKeyword(), mFeature.getName());
            String testName = String.format("%s %s", scenario.getKeyword(), scenario.getName());
            mTestResult = new Bundle(mResultTemplate);
            mTestResult.putString(REPORT_KEY_NAME_CLASS, testClass);
            mTestResult.putString(REPORT_KEY_NAME_TEST, testName);
            mTestResult.putInt(REPORT_KEY_NUM_CURRENT, ++mScenarioNum);

            mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, String.format("\n%s:", testClass));

            sendStatus(REPORT_VALUE_RESULT_START, mTestResult);
            mTestResultCode = 0;
        }

        @Override
        public void result(Result result) {
            if (result.getError() != null) {
                // If the result contains an error, report a failure.
                mTestResult.putString(REPORT_KEY_STACK, result.getErrorMessage());
                mTestResultCode = REPORT_VALUE_RESULT_FAILURE;
                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, result.getErrorMessage());
            } else if (result.getStatus().equals("undefined")) {
                // There was a missing step definition, report an error.
                List<String> snippets = mRuntime.getSnippets();
                String report = String.format("Missing step-definition\n\n%s\nfor step '%s'",
                        snippets.get(snippets.size() - 1),
                        mStep.getName());
                mTestResult.putString(REPORT_KEY_STACK, report);
                mTestResultCode = REPORT_VALUE_RESULT_ERROR;
                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
                        String.format("Missing step-definition: %s", mStep.getName()));
            }
        }

        private void reportLastResult() {
            if (mScenarioNum != 0) {
                if (mTestResultCode == 0) {
                    mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, ".");
                }
                sendStatus(mTestResultCode, mTestResult);
            }
        }
    }
}




Java Source Code List

com.example.cucumberandroid.MainActivity.java
cucumber.api.android.CucumberInstrumentationTestRunner.java
cucumber.api.android.CucumberInstrumentation.java
cucumber.api.android.RunWithCucumber.java
cucumber.runtime.android.AndroidBackend.java
cucumber.runtime.android.AndroidClasspathMethodScanner.java
cucumber.runtime.android.AndroidFormatter.java
cucumber.runtime.android.AndroidJavaStepDefinition.java
cucumber.runtime.android.AndroidMethodFormat.java
cucumber.runtime.android.AndroidObjectFactory.java
cucumber.runtime.android.AndroidResourceLoader.java
cucumber.runtime.android.AndroidResource.java
cucumber.runtime.android.JavaHookDefinition.java
cucumber.runtime.android.JavaSnippet.java
ext.com.android.internal.os.LoggingPrintStream.java
ext.com.google.android.collect.Maps.java
ext.com.google.android.collect.Sets.java