Skip to content

Commit

Permalink
test: Added cucumber sample app for testing #1118 (#1174)
Browse files Browse the repository at this point in the history
* test: Added cucumber sample app for testing

* test: Added cucumber sample app for testing

* remove unused files
  • Loading branch information
piotradamczyk5 authored Oct 1, 2020
1 parent 256147f commit 5d129af
Show file tree
Hide file tree
Showing 73 changed files with 3,897 additions and 1 deletion.
5 changes: 4 additions & 1 deletion test_projects/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ buildscript {
repositories {
google()
jcenter()

mavenLocal()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
maven { url 'https://jitpack.io' }
}
dependencies {
// https://dl.google.com/dl/android/maven2/index.html
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.jaredsburrows:gradle-spoon-plugin:1.5.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gen/
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import java.time.Duration

apply plugin: 'com.android.library'
apply plugin: 'signing'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 29
buildToolsVersion '29.0.3'

defaultConfig {
minSdkVersion 14
targetSdkVersion 29
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

lintOptions {
abortOnError false
}

testOptions {
unitTests {
includeAndroidResources = true
}
}
}

configurations.all {
// check for updates every build
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}


dependencies {
api "io.cucumber:cucumber-java:4.8.1"
api "io.cucumber:cucumber-junit:4.8.1"
api 'junit:junit:4.13'
api "androidx.test:runner:1.2.0"
testImplementation "org.robolectric:robolectric:4.3.1"
testImplementation "org.powermock:powermock-api-mockito2:2.0.2"
testImplementation "org.powermock:powermock-module-junit4:2.0.2"
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

task("generateJavadoc", type: Javadoc, group: 'documentation') {
source = android.sourceSets.main.java.srcDirs
destinationDir = new File("${project.buildDir}/javadoc")
options.addStringOption('Xdoclint:none', '-quiet')
}

task javadocJar(type: Jar, dependsOn: generateJavadoc) {
archiveClassifier.set 'javadoc'
from generateJavadoc.destinationDir
}

task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
archiveClassifier.set 'sources'
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="io.cucumber.android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cucumber.runtime.java;

import cucumber.api.java.ObjectFactory;
import cucumber.runtime.BackendSupplier;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.DefaultTypeRegistryConfiguration;
import cucumber.runtime.Env;
import cucumber.runtime.Reflections;
import io.cucumber.core.api.TypeRegistryConfigurer;
import io.cucumber.core.options.RuntimeOptions;
import io.cucumber.stepexpression.TypeRegistry;

import static java.util.Collections.singletonList;

/**
* This factory is responsible for creating the {@see JavaBackend} with dex class finder.
*/
public class AndroidJavaBackendFactory {
public static BackendSupplier createBackend(RuntimeOptions runtimeOptions, ClassFinder classFinder) {
return () -> {
final Reflections reflections = new Reflections(classFinder);
final ObjectFactory delegateObjectFactory = ObjectFactoryLoader.loadObjectFactory(classFinder,
JavaBackend.getObjectFactoryClassName(Env.INSTANCE), JavaBackend.getDeprecatedObjectFactoryClassName(Env.INSTANCE));
final TypeRegistryConfigurer typeRegistryConfigurer = reflections.instantiateExactlyOneSubclass(TypeRegistryConfigurer.class,
runtimeOptions.getGlue(), new Class[0], new Object[0], new DefaultTypeRegistryConfiguration());
final TypeRegistry typeRegistry = new TypeRegistry(typeRegistryConfigurer.locale());
typeRegistryConfigurer.configureTypeRegistry(typeRegistry);
return singletonList(new JavaBackend(delegateObjectFactory, classFinder, typeRegistry));
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.cucumber.android.runner;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.test.runner.AndroidJUnitRunner;

import io.cucumber.junit.CucumberArgumentsProvider;
import io.cucumber.junit.CucumberAndroidJUnitArguments;

/**
* {@link AndroidJUnitRunner} for cucumber tests. It supports running tests from Android Tests Orchestrator
*/
public class CucumberAndroidJUnitRunner extends AndroidJUnitRunner implements CucumberArgumentsProvider {

private CucumberAndroidJUnitArguments cucumberJUnitRunnerCore;

@Override
public void onCreate(final Bundle bundle) {
cucumberJUnitRunnerCore = new CucumberAndroidJUnitArguments(bundle);
super.onCreate(cucumberJUnitRunnerCore.processArgs());
}

@NonNull
@Override
public CucumberAndroidJUnitArguments getArguments() {
return cucumberJUnitRunnerCore;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.cucumber.cucumberexpressions;

import java.util.regex.Pattern;

public class AndroidPatternCompiler implements PatternCompiler {

@Override
public Pattern compile(String regexp, int flags) {
return Pattern.compile(regexp,flags& ~Pattern.UNICODE_CHARACTER_CLASS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.cucumber.junit;

import cucumber.runtime.model.CucumberFeature;
import gherkin.ast.Feature;
import io.cucumber.junit.AndroidPickleRunner;

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

import java.util.List;

public class AndroidFeatureRunner extends ParentRunner<AndroidPickleRunner> {

private final List<AndroidPickleRunner> children;
private final CucumberFeature cucumberFeature;

public AndroidFeatureRunner(Class<?> testClass, CucumberFeature cucumberFeature, List<AndroidPickleRunner> children) throws InitializationError {
super(testClass);
this.cucumberFeature = cucumberFeature;
this.children = children;
}

@Override
public String getName() {
Feature feature = cucumberFeature.getGherkinFeature().getFeature();
return feature.getKeyword() + ": " + feature.getName();
}

@Override
protected List<AndroidPickleRunner> getChildren() {
return children;
}

@Override
protected Description describeChild(AndroidPickleRunner child) {
return child.getDescription();
}

@Override
protected void runChild(AndroidPickleRunner child, RunNotifier notifier) {
child.run(notifier);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.cucumber.junit;

import android.content.Context;
import android.util.Log;

import cucumber.runtime.ClassFinder;
import cucumber.runtime.CucumberException;
import cucumber.runtime.Env;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoader;
import io.cucumber.core.model.GluePath;
import io.cucumber.core.options.CucumberOptionsAnnotationParser;
import io.cucumber.core.options.EnvironmentOptionsParser;
import io.cucumber.core.options.RuntimeOptions;

class AndroidJunitRuntimeOptionsFactory {
private static final String TAG = "cucumber-android";

static class Options {
final RuntimeOptions runtimeOptions;
final JUnitOptions jUnitOptions;

Options(RuntimeOptions runtimeOptions, JUnitOptions jUnitOptions) {
this.runtimeOptions = runtimeOptions;
this.jUnitOptions = jUnitOptions;
}
}

static Options createRuntimeOptions(Context context, ClassFinder classFinder, ClassLoader classLoader) {
for (final Class<?> clazz : classFinder.getDescendants(Object.class, GluePath.parse(context.getPackageName()))) {
if (clazz.isAnnotationPresent(CucumberOptions.class)) {
Log.d(TAG, "Found CucumberOptions in class " + clazz.getName());
ResourceLoader resourceLoader = new MultiLoader(classLoader);

RuntimeOptions runtimeOptions = new EnvironmentOptionsParser(resourceLoader)
.parse(Env.INSTANCE)
.build(new CucumberOptionsAnnotationParser(resourceLoader)
.withOptionsProvider(new JUnitCucumberOptionsProvider())
.parse(clazz)
.build()
);

JUnitOptions junitOptions = new JUnitOptionsParser()
.parse(runtimeOptions.getJunitOptions())
.setStrict(runtimeOptions.isStrict())
.build(new JUnitOptionsParser()
.parse(clazz)
.build()
);

return new Options(runtimeOptions, junitOptions);
}
}

throw new CucumberException("No CucumberOptions annotation");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package io.cucumber.junit;

import android.util.Log;
import cucumber.api.PickleStepTestStep;
import cucumber.api.event.ConcurrentEventListener;
import cucumber.api.event.EventHandler;
import cucumber.api.event.EventPublisher;
import cucumber.api.event.TestCaseStarted;
import cucumber.api.event.TestRunFinished;
import cucumber.api.event.TestStepStarted;
import cucumber.runtime.UndefinedStepsTracker;
import cucumber.runtime.formatter.Stats;

/**
* Logs information about the currently executed statements to androids logcat.
*/
public final class AndroidLogcatReporter implements ConcurrentEventListener {

/**
* The log tag to be used when logging to logcat.
*/
private final String logTag;

/**
* The event handler that logs the {@link TestCaseStarted} events.
*/
private final EventHandler<TestCaseStarted> testCaseStartedHandler = new EventHandler<TestCaseStarted>() {
@Override
public void receive(TestCaseStarted event) {
Log.d(logTag, String.format("%s", event.testCase.getName()));
}
};

private final Stats stats;

private final UndefinedStepsTracker undefinedStepsTracker;

/**
* The event handler that logs the {@link TestStepStarted} events.
*/
private final EventHandler<TestStepStarted> testStepStartedHandler = new EventHandler<TestStepStarted>() {
@Override
public void receive(TestStepStarted event) {
if (event.testStep instanceof PickleStepTestStep) {
PickleStepTestStep testStep = (PickleStepTestStep) event.testStep;
Log.d(logTag, String.format("%s", testStep.getStepText()));
}
}
};

/**
* The event handler that logs the {@link TestRunFinished} events.
*/
private EventHandler<TestRunFinished> runFinishHandler = new EventHandler<TestRunFinished>() {

@Override
public void receive(TestRunFinished event) {
for (final Throwable throwable : stats.getErrors()) {
Log.e(logTag, throwable.toString());
}

for (final String snippet : undefinedStepsTracker.getSnippets()) {
Log.w(logTag, snippet);
}
}
};

/**
* Creates a new instance for the given parameters.
*
* @param undefinedStepsTracker
* @param logTag the tag to use for logging to logcat
*/
public AndroidLogcatReporter(Stats stats, UndefinedStepsTracker undefinedStepsTracker, final String logTag) {
this.stats = stats;
this.undefinedStepsTracker = undefinedStepsTracker;
this.logTag = logTag;
}

@Override
public void setEventPublisher(final EventPublisher publisher) {
publisher.registerHandlerFor(TestCaseStarted.class, testCaseStartedHandler);
publisher.registerHandlerFor(TestStepStarted.class, testStepStartedHandler);
publisher.registerHandlerFor(TestRunFinished.class, runFinishHandler);
}
}
Loading

0 comments on commit 5d129af

Please sign in to comment.