Skip to content

Commit

Permalink
Adding Configuration by Annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt License committed Jan 30, 2019
1 parent 3c929a4 commit 47c9860
Show file tree
Hide file tree
Showing 38 changed files with 971 additions and 383 deletions.
143 changes: 0 additions & 143 deletions config/fix/protocol.xml

This file was deleted.

@@ -0,0 +1,47 @@
package com.neueda.etiqet.core;

import cucumber.api.CucumberOptions;

import java.lang.annotation.*;

/**
* Annotation used to configure Etiqet
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface EtiqetOptions {

/**
* @return a path to the Etiqet Configuration file
*/
String configFile() default "";

/**
* @return the class used to configure Etiqet
*/
Class<?> configClass() default NullConfiguration.class;

/**
* @return the paths to the feature(s)
*/
String[] features() default {};

/**
* @return the paths to any addition Fixtures to configure test steps
*/
String[] additionalFixtures() default {};

/**
* @return what plugins(s) to pass on to Cucumber
* @see CucumberOptions#plugin()
*/
String[] plugin() default {};

/**
* Class that represents that a configClass has not been specified
*/
final class NullConfiguration {
}

}
142 changes: 142 additions & 0 deletions etiqet-core/src/main/java/com/neueda/etiqet/core/EtiqetTestRunner.java
@@ -0,0 +1,142 @@
package com.neueda.etiqet.core;

import com.neueda.etiqet.core.common.Environment;
import com.neueda.etiqet.core.common.exceptions.EtiqetException;
import com.neueda.etiqet.core.config.GlobalConfig;
import com.neueda.etiqet.core.util.StringUtils;
import cucumber.api.junit.Cucumber;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.Runtime;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.io.ResourceLoaderClassFinder;
import cucumber.runtime.junit.FeatureRunner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.InitializationError;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.neueda.etiqet.core.common.ConfigConstants.DEFAULT_CONFIG_VARIABLE;

/**
* EtiqetTestRunner uses {@link Cucumber} as a delegate test runner. Before instantiating the Cucumber Test Runner,
* we first configure the Etiqet Configuration based on the {@link EtiqetOptions} specified on the test class
*/
public class EtiqetTestRunner extends ParentRunner<FeatureRunner> {

static final String FIXTURE_PACKAGE = "com.neueda.etiqet.fixture";
private static final Logger LOG = LogManager.getLogger(EtiqetTestRunner.class);
private Cucumber cucumberDelegate;
private EtiqetOptions etiqetOptions;

/**
* Constructor called by JUnit.
*
* @param clazz the class with the @RunWith annotation.
* @throws IOException if there is a problem initialising Cucumber
* @throws InitializationError if a class or resource could not be loaded for the tests
* @throws EtiqetException if there is a problem configuring Etiqet
*/
public EtiqetTestRunner(Class<?> clazz) throws InitializationError, IOException, EtiqetException {
super(clazz);
if (!clazz.isAnnotationPresent(EtiqetOptions.class)) {
throw new InitializationError("EtiqetTestRunner requires the @EtiqetOptions annotation");
}

etiqetOptions = clazz.getAnnotation(EtiqetOptions.class);
if (StringUtils.isNullOrEmpty(etiqetOptions.configFile())
&& etiqetOptions.configClass().equals(EtiqetOptions.NullConfiguration.class)
&& !Environment.isEnvVarSet(DEFAULT_CONFIG_VARIABLE)) {
throw new InitializationError("EtiqetTestRunner requires one of the following configuration "
+ "options to be specified:"
+ System.lineSeparator()
+ "\t1. Specifying a configuration class via the configClass option"
+ System.lineSeparator()
+ "\t2. Specifying a configuration file using the configFile option"
+ System.lineSeparator()
+ "\t3. Setting the Environment / System variable " + DEFAULT_CONFIG_VARIABLE + " with the path "
+ "to a configuration file");
}

GlobalConfig globalConfig;
if (!etiqetOptions.configClass().equals(EtiqetOptions.NullConfiguration.class)) {
LOG.info("Initialising EtiqetTestRunner with configuration class " + etiqetOptions.configClass());
globalConfig = GlobalConfig.getInstance(clazz);
} else if (!StringUtils.isNullOrEmpty(etiqetOptions.configFile())) {
LOG.info("Initialising EtiqetTestRunner with configuration file " + etiqetOptions.configFile());
globalConfig = GlobalConfig.getInstance(etiqetOptions.configFile());
} else {
LOG.info("Initialising EtiqetTestRunner with configuration file from System Variable " +
DEFAULT_CONFIG_VARIABLE + ": " + Environment.resolveEnvVars(DEFAULT_CONFIG_VARIABLE));
globalConfig = GlobalConfig.getInstance();
}

cucumberDelegate = getCucumberDelegate(clazz);
}

/**
* Returns the Cucumber instance that is to be used as the delegate test runner.
*
* @param clazz the class with the @RunWith annotation
* @return Cucumber test runner
* @throws InitializationError if there is a problem initialising Cucumber
* @throws IOException if a class or resource could not be loaded for the tests
*/
Cucumber getCucumberDelegate(Class clazz) throws InitializationError, IOException {
return new Cucumber(clazz) {
protected Runtime createRuntime(ResourceLoader resourceLoader,
ClassLoader classLoader,
RuntimeOptions runtimeOptions) {
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);

if (!runtimeOptions.getGlue().contains(FIXTURE_PACKAGE)) {
runtimeOptions.getGlue().add(FIXTURE_PACKAGE);
}
for (String additionalGlue : etiqetOptions.additionalFixtures()) {
if (!runtimeOptions.getGlue().contains(additionalGlue)) {
runtimeOptions.getGlue().add(additionalGlue);
}
}

// ensure that list of features we provide Cucumber is unique
Set<String> uniqueFeatures = new HashSet<>(etiqetOptions.features().length
+ runtimeOptions.getFeaturePaths().size());
uniqueFeatures.addAll(Arrays.asList(etiqetOptions.features()));
uniqueFeatures.addAll(runtimeOptions.getFeaturePaths());

runtimeOptions.getFeaturePaths().clear();
runtimeOptions.getFeaturePaths().addAll(uniqueFeatures);

return new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
}
};
}

@Override
protected List<FeatureRunner> getChildren() {
return cucumberDelegate.getChildren();
}

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

@Override
protected void runChild(FeatureRunner child, RunNotifier notifier) {
child.run(notifier);
}

@Override
public void run(RunNotifier notifier) {
cucumberDelegate.run(notifier);
}
}
Expand Up @@ -21,7 +21,7 @@ public class ClientDelegateFactory<U, M> {

public ClientDelegateFactory(ProtocolConfig protocolConfig) {
delegatesUriFromAction = new HashMap<>();
if(protocolConfig.getClientDelegates() != null) {
if (protocolConfig.getClientDelegates() != null && protocolConfig.getClientDelegates().getDelegate() != null) {
for(Delegate del: protocolConfig.getClientDelegates().getDelegate()) {
delegatesUriFromAction.put(del.getKey(), del.getImpl());
}
Expand Down
Expand Up @@ -14,6 +14,7 @@
import com.neueda.etiqet.core.message.config.ProtocolConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.InvocationTargetException;

/**
Expand Down Expand Up @@ -147,7 +148,7 @@ public static Client create(
private static void setClientDelegates(Client client, ProtocolConfig protocolConfig) throws EtiqetException {
ClientDelegateFactory cdf = new ClientDelegateFactory(protocolConfig);
Delegates clientDelegates = protocolConfig.getClientDelegates();
if(clientDelegates != null) {
if (clientDelegates != null && clientDelegates.getDelegate() != null) {
Delegate[] delegates = clientDelegates.getDelegate();
ClientDelegate del = new SinkClientDelegate<>();
for(int i = delegates.length - 1; i >= 0; i--) {
Expand Down

0 comments on commit 47c9860

Please sign in to comment.