featureFiles)
17 | throws MojoExecutionException;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/CucumberITGeneratorFactory.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | import com.github.timm.cucumber.generate.name.ClassNamingScheme;
4 | import org.apache.maven.plugin.MojoExecutionException;
5 |
6 | public class CucumberITGeneratorFactory {
7 |
8 | private final OverriddenCucumberOptionsParameters overriddenParameters;
9 | private final ClassNamingScheme classNamingScheme;
10 | private final FileGeneratorConfig config;
11 |
12 | /**
13 | * Constructor.
14 | * @param config generator config.
15 | * @param overriddenParameters cucumber options params
16 | * @param classNamingScheme the class naming scheme to use
17 | */
18 | public CucumberITGeneratorFactory(final FileGeneratorConfig config,
19 | final OverriddenCucumberOptionsParameters overriddenParameters,
20 | final ClassNamingScheme classNamingScheme) {
21 | this.overriddenParameters = overriddenParameters;
22 | this.classNamingScheme = classNamingScheme;
23 | this.config = config;
24 | }
25 |
26 | /**
27 | * Create a CucumberITGenerator based on the given parallel scheme.
28 | * @param parallelScheme The scheme to use
29 | * @return CucumberITGenerator
30 | * @throws MojoExecutionException
31 | */
32 | public CucumberITGenerator create(final ParallelScheme parallelScheme) throws MojoExecutionException {
33 | if (ParallelScheme.FEATURE.equals(parallelScheme)) {
34 |
35 | return createFileGeneratorByFeature();
36 | } else {
37 | return createFileGeneratorByScenario();
38 | }
39 | }
40 |
41 | @SuppressWarnings("deprecation")
42 | private CucumberITGenerator createFileGeneratorByFeature() throws MojoExecutionException {
43 | return new CucumberITGeneratorByFeature(config, overriddenParameters, classNamingScheme);
44 | }
45 |
46 | private CucumberITGenerator createFileGeneratorByScenario() throws MojoExecutionException {
47 | return new CucumberITGeneratorByScenario(config, overriddenParameters, classNamingScheme);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/FileGeneratorConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | import org.apache.maven.plugin.logging.Log;
4 |
5 | import java.io.File;
6 |
7 | interface FileGeneratorConfig {
8 |
9 | Log getLog();
10 |
11 | String getEncoding();
12 |
13 | File getCucumberOutputDir();
14 |
15 | boolean useTestNG();
16 |
17 | String getCustomVmTemplate();
18 |
19 | String getPackageName();
20 |
21 | File getProjectBasedir();
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/ParallelScheme.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | public enum ParallelScheme {
4 | FEATURE, SCENARIO
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/ScenarioAndLocation.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | import gherkin.ast.Location;
4 | import gherkin.ast.ScenarioDefinition;
5 |
6 | /**
7 | * A single test to create within a test run.
8 | */
9 | public class ScenarioAndLocation {
10 |
11 | /**
12 | * The scenario this test case belongs to.
13 | */
14 | private final ScenarioDefinition scenarioDefinition;
15 |
16 | /**
17 | * Where this test case came from - Either the scenario, or the table
18 | * row in a scenario outline's examples block.
19 | */
20 | private final Location location;
21 |
22 | public ScenarioAndLocation(ScenarioDefinition scenarioDefinition, Location location) {
23 | this.scenarioDefinition = scenarioDefinition;
24 | this.location = location;
25 | }
26 |
27 | public ScenarioDefinition getScenario() {
28 | return scenarioDefinition;
29 | }
30 |
31 | public Location getLocation() {
32 | return location;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/name/ClassNamingScheme.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | public interface ClassNamingScheme {
4 |
5 | String generate(final String featureFileName);
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/name/ClassNamingSchemeFactory.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | import org.apache.maven.plugin.MojoExecutionException;
4 |
5 | /**
6 | * Factory for {@link ClassNamingScheme}based on a name.
7 | *
8 | *
9 | * The following naming schemes are supported:
10 | *
11 | *
12 | * - simple
13 | * - feature-title
14 | * - pattern
15 | *
16 | */
17 | public class ClassNamingSchemeFactory {
18 |
19 | private final Counter counter;
20 | private final ClassNamingScheme featureFileNamingScheme;
21 |
22 | /**
23 | * Constructor.
24 | * @param counter Counter for adding 1-up numbers to generated class names.
25 | */
26 | public ClassNamingSchemeFactory(final Counter counter) {
27 | this.counter = counter;
28 | featureFileNamingScheme = new FeatureFileClassNamingScheme();
29 | }
30 |
31 | /**
32 | * Create a {@link ClassNamingScheme} based on the given name.
33 | *
34 | * @param namingScheme The naming scheme to use
35 | * @param namingPattern Only required if pattern
naming scheme is used. The pattern to use when
36 | * generating the classname. See {@link PatternNamingScheme} for more details.
37 | */
38 | public ClassNamingScheme create(final String namingScheme, final String namingPattern)
39 | throws MojoExecutionException {
40 |
41 | if (namingScheme.equals("simple")) {
42 | return new PatternNamingScheme("Parallel{c}IT", counter, featureFileNamingScheme);
43 | } else if (namingScheme.equals("feature-title")) {
44 | return new PatternNamingScheme("{f}{c}IT", counter, featureFileNamingScheme);
45 | // return new FeatureFileClassNamingScheme(counter);
46 | } else if (namingScheme.equals("pattern")) {
47 |
48 | if (namingPattern == null) {
49 | throw new MojoExecutionException("namingPattern tag is required");
50 | }
51 |
52 | return new PatternNamingScheme(namingPattern, counter, featureFileNamingScheme);
53 | } else {
54 | throw new MojoExecutionException("Error in configuration ; accepted value for tag "
55 | + "'namingScheme' are 'simple' or 'feature-title' or 'pattern'");
56 | }
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/name/Counter.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | public interface Counter {
4 |
5 | int next();
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/name/FeatureFileClassNamingScheme.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | import com.google.common.base.CaseFormat;
4 | import org.apache.commons.io.FilenameUtils;
5 |
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | /**
10 | * Generates a class name based on the feature file filename.
11 | *
12 | *
13 | * The following rules are used to ensure class names are valid:
14 | *
15 | *
16 | * - The file extension is removed.
17 | * - Spaces and '-' are removed, converting to CamelCase.
18 | * - If the filename starts with a digit, the classname is pre-pended with '_'
19 | *
20 | */
21 | public class FeatureFileClassNamingScheme implements ClassNamingScheme {
22 |
23 | private final Pattern startsWithDigit = Pattern.compile("^\\d.*");
24 |
25 | public FeatureFileClassNamingScheme() {}
26 |
27 | /**
28 | * Generate a class name based on the supplied feature file.
29 | */
30 | public String generate(final String featureFileName) {
31 | String fileNameWithNoExtension = FilenameUtils.removeExtension(featureFileName);
32 |
33 | fileNameWithNoExtension = fileNameWithNoExtension.replaceAll("_", "-");
34 | fileNameWithNoExtension = fileNameWithNoExtension.replaceAll(" ", "");
35 | fileNameWithNoExtension = fileNameWithNoExtension.replaceAll("\\.", "-");
36 |
37 | String className =
38 | CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, fileNameWithNoExtension);
39 |
40 | final Matcher startsWithDigitCheck = startsWithDigit.matcher(className);
41 |
42 | if (startsWithDigitCheck.matches()) {
43 | className = "_" + className;
44 | }
45 |
46 | return className;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/generate/name/OneUpCounter.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | public class OneUpCounter implements Counter {
4 |
5 | private static int counter = 1;
6 |
7 | public int next() {
8 | return counter++;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/options/Shellwords.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.options;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * Copyright (c) 2008-2014 The Cucumber Organisation
10 | *
11 | * Copy of Cucumber Shellwords
12 | */
13 | public class Shellwords {
14 | private static final Pattern SHELLWORDS_PATTERN = Pattern.compile("[^\\s']+|'([^']*)'");
15 |
16 | public static List parse(final String cmdline) {
17 | final List matchList = new ArrayList();
18 | final Matcher shellwordsMatcher = SHELLWORDS_PATTERN.matcher(cmdline);
19 | while (shellwordsMatcher.find()) {
20 | if (shellwordsMatcher.group(1) != null) {
21 | matchList.add(shellwordsMatcher.group(1));
22 | } else {
23 | matchList.add(shellwordsMatcher.group());
24 | }
25 | }
26 | return matchList;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/github/timm/cucumber/runtime/TagPredicate.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.runtime;
2 |
3 | import static java.util.Arrays.asList;
4 |
5 | import gherkin.events.PickleEvent;
6 | import gherkin.pickles.PickleTag;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Collection;
10 | import java.util.List;
11 |
12 | import io.cucumber.tagexpressions.Expression;
13 | import io.cucumber.tagexpressions.TagExpressionParser;
14 |
15 | /**
16 | * This file is copied from Cucumber-runtime library
17 | *
18 | */
19 | public class TagPredicate {
20 | private final List expressions = new ArrayList();
21 | private final List oldStyleExpressions = new ArrayList();
22 |
23 | public TagPredicate(List tagExpressions) {
24 | if (tagExpressions == null) {
25 | return;
26 | }
27 | TagExpressionParser parser = new TagExpressionParser();
28 | for (String tagExpression : tagExpressions) {
29 | if (TagExpressionOld.isOldTagExpression(tagExpression)) {
30 | oldStyleExpressions.add(new TagExpressionOld(asList(tagExpression)));
31 | } else {
32 | expressions.add(parser.parse(tagExpression));
33 | }
34 | }
35 | }
36 |
37 | public boolean apply(PickleEvent pickleEvent) {
38 | return apply(pickleEvent.pickle.getTags());
39 | }
40 |
41 | /**
42 | *
43 | * @param pickleTags
44 | * @return
45 | */
46 | public boolean apply(Collection pickleTags) {
47 | for (TagExpressionOld oldStyleExpression : oldStyleExpressions) {
48 | if (!oldStyleExpression.evaluate(pickleTags)) {
49 | return false;
50 | }
51 | }
52 | List tags = new ArrayList();
53 | for (PickleTag pickleTag : pickleTags) {
54 | tags.add(pickleTag.getName());
55 | }
56 | for (Expression expression : expressions) {
57 | if (!expression.evaluate(tags)) {
58 | return false;
59 | }
60 | }
61 | return true;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/resources/array.java.vm:
--------------------------------------------------------------------------------
1 | #macro( stringArray $array ){#foreach( $element in $array )"$element"#if( $foreach.hasNext ), #end#end}#end
--------------------------------------------------------------------------------
/src/main/resources/cucumber-junit-runner.java.vm:
--------------------------------------------------------------------------------
1 | #parse("/array.java.vm")
2 | #if ($packageName)
3 | package $packageName;
4 |
5 | #end##
6 | import org.junit.runner.RunWith;
7 |
8 | import cucumber.api.CucumberOptions;
9 | import cucumber.api.junit.Cucumber;
10 |
11 | @RunWith(Cucumber.class)
12 | @CucumberOptions(
13 | strict = $strict,
14 | features = {"$featureFile"},
15 | plugin = #stringArray($plugins),
16 | monochrome = $monochrome,
17 | #if(!$featureFile.contains(".feature:") && $tags)
18 | tags = #stringArray($tags),
19 | #end
20 | glue = #stringArray($glue))
21 | public class $className {
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/cucumber-testng-runner.java.vm:
--------------------------------------------------------------------------------
1 | #parse("/array.java.vm")
2 | #if ($packageName)
3 | package $packageName;
4 |
5 | #end##
6 | import cucumber.api.CucumberOptions;
7 | import cucumber.api.testng.AbstractTestNGCucumberTests;
8 |
9 | @CucumberOptions(
10 | strict = $strict,
11 | features = {"$featureFile"},
12 | plugin = #stringArray($plugins),
13 | monochrome = ${monochrome},
14 | #if(!$featureFile.contains(".feature:") && $tags)
15 | tags = #stringArray($tags),
16 | #end
17 | glue = #stringArray($glue))
18 | public class $className extends AbstractTestNGCucumberTests {
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/github/timm/cucumber/generate/InstanceCounter.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | import com.github.timm.cucumber.generate.name.Counter;
4 |
5 | public class InstanceCounter implements Counter {
6 |
7 | private int counter = 1;
8 |
9 | public int next() {
10 | return counter++;
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/timm/cucumber/generate/TestFileGeneratorConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate;
2 |
3 | import org.apache.maven.plugin.logging.Log;
4 |
5 | import java.io.File;
6 |
7 | class TestFileGeneratorConfig implements FileGeneratorConfig {
8 |
9 | private Log log;
10 | private File featuresDirectory;
11 | private File outputDir;
12 | private final boolean useTestNg = false;
13 | private final String namingScheme = "simple";
14 | private final String namingPattern = null;
15 | private final String customVmTemplate = "";
16 |
17 | TestFileGeneratorConfig setFeaturesDirectory(final File directory) {
18 | this.featuresDirectory = directory;
19 | return this;
20 | }
21 |
22 | TestFileGeneratorConfig setCucumberOutputDir(final Class> classUnderTest) {
23 | this.outputDir = new File("target", classUnderTest.getSimpleName());
24 | return this;
25 | }
26 |
27 | public Log getLog() {
28 | return log;
29 | }
30 |
31 | public String getEncoding() {
32 | return "UTF-8";
33 | }
34 |
35 | public File getCucumberOutputDir() {
36 | return outputDir;
37 | }
38 |
39 | public boolean useTestNG() {
40 | return useTestNg;
41 | }
42 |
43 | public String getCustomVmTemplate() {
44 | return customVmTemplate;
45 | }
46 |
47 | public String getPackageName() {
48 | return null;
49 | }
50 |
51 | public File getProjectBasedir() {
52 | return new File(".");
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/java/com/github/timm/cucumber/generate/name/ClassNamingSchemeFactoryTest.java:
--------------------------------------------------------------------------------
1 | package com.github.timm.cucumber.generate.name;
2 |
3 | import static org.fest.assertions.Assertions.assertThat;
4 | import static org.mockito.BDDMockito.given;
5 | import static org.mockito.Mockito.mock;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.junit.runners.Parameterized;
10 | import org.junit.runners.Parameterized.Parameter;
11 | import org.junit.runners.Parameterized.Parameters;
12 |
13 | import java.util.Arrays;
14 | import java.util.Collection;
15 |
16 | @RunWith(Parameterized.class)
17 | public class ClassNamingSchemeFactoryTest {
18 |
19 | @Parameter(0)
20 | public String namingScheme;
21 | @Parameter(1)
22 | public String pattern;
23 | @Parameter(2)
24 | public String expectedResult;
25 | @Parameter(3)
26 | public Integer nextCount;
27 |
28 | Counter mockCounter = mock(Counter.class);
29 | ClassNamingSchemeFactory factory = new ClassNamingSchemeFactory(mockCounter);
30 |
31 | /**
32 | * Create params.
33 | */
34 | @Parameters
35 | public static Collection