package cucumber.runtime;
import gherkin.formatter.Reporter;
import gherkin.formatter.model.Background;
import gherkin.formatter.model.Examples;
import gherkin.formatter.model.Feature;
import gherkin.formatter.model.Match;
import gherkin.formatter.model.Result;
import gherkin.formatter.model.ScenarioOutline;
import gherkin.formatter.model.Step;
import cucumber.runtime.formatter.FormatterSpy;
import cucumber.api.SnippetType;
import cucumber.runtime.formatter.ColorAware;
import cucumber.runtime.formatter.PluginFactory;
import cucumber.runtime.formatter.StrictAware;
import cucumber.runtime.io.Resource;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.model.CucumberFeature;
import gherkin.formatter.Formatter;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
public class RuntimeOptionsTest {
@Test
public void has_version_from_properties_file() {
assertTrue(RuntimeOptions.VERSION.startsWith("1.2"));
}
@Test
public void has_usage() {
RuntimeOptions.loadUsageTextIfNeeded();
assertTrue(RuntimeOptions.usageText.startsWith("Usage"));
}
@Test
public void assigns_feature_paths() {
RuntimeOptions options = new RuntimeOptions("--glue somewhere somewhere_else");
assertEquals(asList("somewhere_else"), options.getFeaturePaths());
}
@Test
public void keep_line_filters_on_feature_paths() {
RuntimeOptions options = new RuntimeOptions("--glue somewhere somewhere_else:3");
assertEquals(asList("somewhere_else:3"), options.getFeaturePaths());
assertEquals(Collections.<Object>emptyList(), options.getFilters());
}
@Test
public void assigns_filters_from_tags() {
RuntimeOptions options = new RuntimeOptions("--tags @keep_this somewhere_else:3");
assertEquals(asList("somewhere_else:3"), options.getFeaturePaths());
assertEquals(Arrays.<Object>asList("@keep_this"), options.getFilters());
}
@Test
public void strips_options() {
RuntimeOptions options = new RuntimeOptions(" --glue somewhere somewhere_else");
assertEquals(asList("somewhere_else"), options.getFeaturePaths());
}
@Test
public void assigns_glue() {
RuntimeOptions options = new RuntimeOptions("--glue somewhere");
assertEquals(asList("somewhere"), options.getGlue());
}
@Test
public void creates_html_formatter() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "html:some/dir", "--glue", "somewhere"));
assertEquals("cucumber.runtime.formatter.HTMLFormatter", options.getPlugins().get(0).getClass().getName());
}
@Test
public void creates_progress_formatter_as_default() {
RuntimeOptions options = new RuntimeOptions(asList("--glue", "somewhere"));
assertEquals("cucumber.runtime.formatter.ProgressFormatter", options.getPlugins().get(0).getClass().getName());
}
@Test
public void creates_progress_formatter_when_no_formatter_plugin_is_specified() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "cucumber.runtime.formatter.AnyStepDefinitionReporter", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.formatter.ProgressFormatter");
}
@Test
public void creates_default_summary_printer_when_no_summary_printer_plugin_is_specified() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "pretty", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.DefaultSummaryPrinter");
}
@Test
public void creates_null_summary_printer() {
RuntimeOptions options = new RuntimeOptions(asList("--plugin", "null_summary", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.NullSummaryPrinter");
assertPluginNotExists(options.getPlugins(), "cucumber.runtime.DefaultSummaryPrinter");
}
@Test
public void assigns_strict() {
RuntimeOptions options = new RuntimeOptions(asList("--strict", "--glue", "somewhere"));
assertTrue(options.isStrict());
}
@Test
public void assigns_strict_short() {
RuntimeOptions options = new RuntimeOptions(asList("-s", "--glue", "somewhere"));
assertTrue(options.isStrict());
}
@Test
public void default_strict() {
RuntimeOptions options = new RuntimeOptions(asList("--glue", "somewhere"));
assertFalse(options.isStrict());
}
@Test
public void name_without_spaces_is_preserved() {
RuntimeOptions options = new RuntimeOptions(asList("--name", "someName"));
Pattern actualPattern = (Pattern) options.getFilters().iterator().next();
assertEquals("someName", actualPattern.pattern());
}
@Test
public void name_with_spaces_is_preserved() {
RuntimeOptions options = new RuntimeOptions(asList("--name", "some Name"));
Pattern actualPattern = (Pattern) options.getFilters().iterator().next();
assertEquals("some Name", actualPattern.pattern());
}
@Test
public void ensure_name_with_spaces_works_with_cucumber_options() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--name 'some Name'");
RuntimeOptions options = new RuntimeOptions(new Env(properties), Collections.<String>emptyList());
Pattern actualPattern = (Pattern) options.getFilters().iterator().next();
assertEquals("some Name", actualPattern.pattern());
}
@Test
public void ensure_name_with_spaces_works_with_args() {
RuntimeOptions options = new RuntimeOptions("--name 'some Name'");
Pattern actualPattern = (Pattern) options.getFilters().iterator().next();
assertEquals("some Name", actualPattern.pattern());
}
@Test
public void assigns_single_junit_option() {
RuntimeOptions options = new RuntimeOptions(asList("--junit,option"));
assertEquals(asList("option"), options.getJunitOptions());
}
@Test
public void assigns_multiple_junit_options() {
RuntimeOptions options = new RuntimeOptions(asList("--junit,option1,option2=value"));
assertEquals(asList("option1", "option2=value"), options.getJunitOptions());
}
@Test
public void clobbers_junit_options_from_cli_if_junit_options_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--junit,option_from_property");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--junit,option_to_be_clobbered"));
assertEquals(asList("option_from_property"), runtimeOptions.getJunitOptions());
}
@Test
public void overrides_options_with_system_properties_without_clobbering_non_overridden_ones() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--glue lookatme this_clobbers_feature_paths");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--strict", "--glue", "somewhere", "somewhere_else"));
assertEquals(asList("this_clobbers_feature_paths"), options.getFeaturePaths());
assertEquals(asList("lookatme"), options.getGlue());
assertTrue(options.isStrict());
}
@Test
public void ensure_cli_glue_is_preserved_when_cucumber_options_property_defined() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--tags @foo");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--glue", "somewhere"));
assertEquals(asList("somewhere"), runtimeOptions.getGlue());
}
@Test
public void clobbers_filters_from_cli_if_filters_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--tags @clobber_with_this");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--tags", "@should_be_clobbered"));
assertEquals(asList("@clobber_with_this"), runtimeOptions.getFilters());
}
@Test
public void clobbers_tag_and_name_filters_from_cli_if_line_filters_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "path/file.feature:3");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--tags", "@should_be_clobbered", "--name", "should_be_clobbered"));
assertEquals(Collections.<Object>emptyList(), runtimeOptions.getFilters());
}
@Test
public void clobbers_tag_and_name_filters_from_cli_if_rerun_file_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "@rerun.txt");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--tags", "@should_be_clobbered", "--name", "should_be_clobbered"));
assertEquals(Collections.<Object>emptyList(), runtimeOptions.getFilters());
}
@Test
public void preserves_filters_from_cli_if_filters_not_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--strict");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--tags", "@keep_this"));
assertEquals(asList("@keep_this"), runtimeOptions.getFilters());
}
@Test
public void clobbers_features_from_cli_if_features_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "new newer");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("old", "older"));
assertEquals(asList("new", "newer"), runtimeOptions.getFeaturePaths());
}
@Test
public void strips_lines_from_features_from_cli_if_filters_are_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--tags @Tag");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("path/file.feature:3"));
assertEquals(asList("path/file.feature"), runtimeOptions.getFeaturePaths());
}
@Test
public void preserves_features_from_cli_if_features_not_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--plugin pretty");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("old", "older"));
assertEquals(asList("old", "older"), runtimeOptions.getFeaturePaths());
}
@Test
public void clobbers_line_filters_from_cli_if_features_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "new newer");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--tags", "@keep_this", "path/file1.feature:1"));
assertEquals(asList("new", "newer"), runtimeOptions.getFeaturePaths());
assertEquals(asList("@keep_this"), runtimeOptions.getFilters());
}
@Test
public void clobbers_formatter_plugins_from_cli_if_formatters_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--plugin pretty");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "html:some/dir", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.formatter.CucumberPrettyFormatter");
assertPluginNotExists(options.getPlugins(), "cucumber.runtime.formatter.HTMLFormatter");
}
@Test
public void adds_to_formatter_plugins_with_add_plugin_option() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--add-plugin pretty");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "html:some/dir", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.formatter.HTMLFormatter");
assertPluginExists(options.getPlugins(), "cucumber.runtime.formatter.CucumberPrettyFormatter");
}
@Test
public void clobbers_summary_plugins_from_cli_if_summary_printer_specified_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "null_summary", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.DefaultSummaryPrinter");
assertPluginNotExists(options.getPlugins(), "cucumber.runtime.NullSummaryPrinter");
}
@Test
public void adds_to_summary_plugins_with_add_plugin_option() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--add-plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "null_summary", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.NullSummaryPrinter");
assertPluginExists(options.getPlugins(), "cucumber.runtime.DefaultSummaryPrinter");
}
@Test
public void does_not_clobber_plugins_of_different_type_when_specifying_plugins_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--plugin default_summary");
RuntimeOptions options = new RuntimeOptions(new Env(properties), asList("--plugin", "pretty", "--glue", "somewhere"));
assertPluginExists(options.getPlugins(), "cucumber.runtime.formatter.CucumberPrettyFormatter");
assertPluginExists(options.getPlugins(), "cucumber.runtime.DefaultSummaryPrinter");
}
@Test
public void allows_removal_of_strict_in_cucumber_options_property() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--no-strict");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), asList("--strict"));
assertFalse(runtimeOptions.isStrict());
}
@Test
public void fail_on_unsupported_options() {
try {
new RuntimeOptions(asList("-concreteUnsupportedOption", "somewhere", "somewhere_else"));
fail();
} catch (CucumberException e) {
assertEquals("Unknown option: -concreteUnsupportedOption", e.getMessage());
}
}
@Test
public void set_monochrome_on_color_aware_formatters() throws Exception {
PluginFactory factory = mock(PluginFactory.class);
Formatter colorAwareFormatter = mock(Formatter.class, withSettings().extraInterfaces(ColorAware.class));
when(factory.create("progress")).thenReturn(colorAwareFormatter);
RuntimeOptions options = new RuntimeOptions(new Env(), factory, asList("--monochrome", "--plugin", "progress"));
options.getPlugins();
verify((ColorAware) colorAwareFormatter).setMonochrome(true);
}
@Test
public void set_strict_on_strict_aware_formatters() throws Exception {
PluginFactory factory = mock(PluginFactory.class);
Formatter strictAwareFormatter = mock(Formatter.class, withSettings().extraInterfaces(StrictAware.class));
when(factory.create("junit:out/dir")).thenReturn(strictAwareFormatter);
RuntimeOptions options = new RuntimeOptions(new Env(), factory, asList("--strict", "--plugin", "junit:out/dir"));
options.getPlugins();
verify((StrictAware) strictAwareFormatter).setStrict(true);
}
@Test
public void ensure_default_snippet_type_is_underscore() {
Properties properties = new Properties();
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), Collections.<String>emptyList());
assertEquals(SnippetType.UNDERSCORE, runtimeOptions.getSnippetType());
}
@Test
public void set_snippet_type() {
Properties properties = new Properties();
properties.setProperty("cucumber.options", "--snippets camelcase");
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env(properties), Collections.<String>emptyList());
assertEquals(SnippetType.CAMELCASE, runtimeOptions.getSnippetType());
}
@Test
public void applies_line_filters_only_to_own_feature() throws Exception {
String featurePath1 = "path/bar.feature";
String feature1 = "" +
"Feature: bar\n" +
" Scenario: scenario_1_1\n" +
" * step\n" +
" Scenario: scenario_1_2\n" +
" * step\n";
String featurePath2 = "path/foo.feature";
String feature2 = "" +
"Feature: foo\n" +
" Scenario: scenario_2_1\n" +
" * step\n" +
" Scenario: scenario_2_2\n" +
" * step\n";
ResourceLoader resourceLoader = mock(ResourceLoader.class);
mockResource(resourceLoader, featurePath1, feature1);
mockResource(resourceLoader, featurePath2, feature2);
RuntimeOptions options = new RuntimeOptions(featurePath1 + ":2 " + featurePath2 + ":4");
List<CucumberFeature> features = options.cucumberFeatures(resourceLoader);
assertEquals(2, features.size());
assertOnlyScenarioName(features.get(0), "scenario_1_1");
assertOnlyScenarioName(features.get(1), "scenario_2_2");
}
@Test
public void handles_formatters_missing_startOfScenarioLifeCycle_endOfScenarioLifeCycle() throws Throwable {
CucumberFeature feature = TestHelper.feature("path/test.feature", "" +
"Feature: feature name\n" +
" Scenario: scenario name\n" +
" Given step\n");
FormatterSpy formatterSpy = new FormatterSpy();
RuntimeOptions runtimeOptions = new RuntimeOptions("");
runtimeOptions.addPlugin(new FormatterMissingLifecycleMethods());
runtimeOptions.addPlugin(formatterSpy);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
TestHelper.runFeatureWithFormatter(feature, new HashMap<String, String>(),
runtimeOptions.formatter(classLoader), runtimeOptions.reporter(classLoader));
assertEquals("" +
"uri\n" +
"feature\n" +
" startOfScenarioLifeCycle\n" +
" scenario\n" +
" step\n" +
" match\n" +
" result\n" +
" endOfScenarioLifeCycle\n" +
"eof\n" +
"done\n" +
"close\n", formatterSpy.toString());
}
private void assertOnlyScenarioName(CucumberFeature feature, String scenarioName) {
assertEquals("Wrong number of scenarios loaded for feature", 1, feature.getFeatureElements().size());
assertEquals("Scenario: " + scenarioName, feature.getFeatureElements().get(0).getVisualName());
}
private void mockResource(ResourceLoader resourceLoader, String featurePath, String feature)
throws IOException, UnsupportedEncodingException {
Resource resource1 = mock(Resource.class);
when(resource1.getPath()).thenReturn(featurePath);
when(resource1.getInputStream()).thenReturn(new ByteArrayInputStream(feature.getBytes("UTF-8")));
when(resourceLoader.resources(featurePath, ".feature")).thenReturn(asList(resource1));
}
private void assertPluginExists(List<Object> plugins, String pluginName) {
assertTrue(pluginName + " not found among the plugins", pluginExists(plugins, pluginName));
}
private void assertPluginNotExists(List<Object> plugins, String pluginName) {
assertFalse(pluginName + " found among the plugins", pluginExists(plugins, pluginName));
}
private boolean pluginExists(List<Object> plugins, String pluginName) {
boolean found = false;
for (Object plugin : plugins) {
if (plugin.getClass().getName() == pluginName) {
found = true;
}
}
return found;
}
}
class FormatterMissingLifecycleMethods implements Formatter, Reporter {
@Override
public void startOfScenarioLifeCycle(gherkin.formatter.model.Scenario arg0) {
throw new NoSuchMethodError(); // simulate that this method is not implemented
}
@Override
public void endOfScenarioLifeCycle(gherkin.formatter.model.Scenario arg0) {
throw new NoSuchMethodError(); // simulate that this method is not implemented
}
@Override
public void after(Match arg0, Result arg1) {
}
@Override
public void before(Match arg0, Result arg1) {
}
@Override
public void embedding(String arg0, byte[] arg1) {
}
@Override
public void match(Match arg0) {
}
@Override
public void result(Result arg0) {
}
@Override
public void write(String arg0) {
}
@Override
public void background(Background arg0) {
}
@Override
public void close() {
}
@Override
public void done() {
}
@Override
public void eof() {
}
@Override
public void examples(Examples arg0) {
}
@Override
public void feature(Feature arg0) {
}
@Override
public void scenario(gherkin.formatter.model.Scenario arg0) {
}
@Override
public void scenarioOutline(ScenarioOutline arg0) {
}
@Override
public void step(Step arg0) {
}
@Override
public void syntaxError(String arg0, String arg1, List<String> arg2, String arg3, Integer arg4) {
}
@Override
public void uri(String arg0) {
}
}