Skip to content

Commit 1f67c2a

Browse files
Regular expression acceptance tests (#35)
* Add acceptance tests for regular expressions * Reformat * Add acceptance tests for RegularExpressions in Java * Fix tests * Remove migration script * Restructure tests and test data * Linting * Simplify
1 parent da28c56 commit 1f67c2a

File tree

132 files changed

+568
-381
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+568
-381
lines changed

go/cucumber_expression_generator_test.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,7 @@ type Currency struct {
1212
ISO4217 string
1313
}
1414

15-
func TestCucumberExpressionGeneratory(t *testing.T) {
16-
t.Run("documents expression generation", func(t *testing.T) {
17-
parameterTypeRegistry := NewParameterTypeRegistry()
18-
19-
/// [generate-expression]
20-
generator := NewCucumberExpressionGenerator(parameterTypeRegistry)
21-
undefinedStepText := "I have 2 cucumbers and 1.5 tomato"
22-
generatedExpression := generator.GenerateExpressions(undefinedStepText)[0]
23-
require.Equal(t, "I have {int} cucumbers and {float} tomato", generatedExpression.Source())
24-
require.Equal(t, "int", generatedExpression.ParameterNames()[0])
25-
require.Equal(t, "float", generatedExpression.ParameterTypes()[1].Name())
26-
/// [generate-expression]
27-
})
28-
15+
func TestCucumberExpressionGenerator(t *testing.T) {
2916
t.Run("generates expression for no args", func(t *testing.T) {
3017
assertExpression(t, "hello", []string{}, "hello")
3118
})

go/cucumber_expression_parser_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"testing"
99
)
1010

11-
type AstExpectation struct {
11+
type ParserExpectation struct {
1212
Expression string `yaml:"expression"`
1313
ExpectedAst node `yaml:"expected_ast"`
1414
Exception string `yaml:"exception"`
@@ -26,15 +26,15 @@ func TestCucumberExpressionParser(t *testing.T) {
2626
require.Equal(t, expected, err.Error())
2727
}
2828

29-
directory := "../testdata/ast/"
29+
directory := "../testdata/cucumber-expression/parser/"
3030
files, err := ioutil.ReadDir(directory)
3131
require.NoError(t, err)
3232

3333
for _, file := range files {
3434
contents, err := ioutil.ReadFile(directory + file.Name())
3535
require.NoError(t, err)
3636
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
37-
var expectation AstExpectation
37+
var expectation ParserExpectation
3838
err = yaml.Unmarshal(contents, &expectation)
3939
require.NoError(t, err)
4040

go/cucumber_expression_test.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@ import (
1010
"testing"
1111
)
1212

13-
type ExpressionExpectation struct {
13+
type CucumberExpressionMatchingExpectation struct {
1414
Expression string `yaml:"expression"`
1515
Text string `yaml:"text"`
1616
ExpectedArgs []interface{} `yaml:"expected_args"`
1717
Exception string `yaml:"exception"`
1818
}
1919

20-
type RegexExpectation struct {
21-
Expression string `yaml:"expression"`
22-
ExpectedRegex string `yaml:"expected_regex"`
23-
}
24-
2520
func TestCucumberExpression(t *testing.T) {
2621

2722
t.Run("acceptance tests pass", func(t *testing.T) {
@@ -49,15 +44,15 @@ func TestCucumberExpression(t *testing.T) {
4944
}
5045
}
5146

52-
directory := "../testdata/expression/"
47+
directory := "../testdata/cucumber-expression/matching/"
5348
files, err := ioutil.ReadDir(directory)
5449
require.NoError(t, err)
5550

5651
for _, file := range files {
5752
contents, err := ioutil.ReadFile(directory + file.Name())
5853
require.NoError(t, err)
5954
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
60-
var expectation ExpressionExpectation
55+
var expectation CucumberExpressionMatchingExpectation
6156
err = yaml.Unmarshal(contents, &expectation)
6257
require.NoError(t, err)
6358
if expectation.Exception == "" {
@@ -67,28 +62,6 @@ func TestCucumberExpression(t *testing.T) {
6762
}
6863
})
6964
}
70-
71-
assertRegex := func(t *testing.T, expected string, expr string) {
72-
parameterTypeRegistry := NewParameterTypeRegistry()
73-
expression, err := NewCucumberExpression(expr, parameterTypeRegistry)
74-
require.NoError(t, err)
75-
require.Equal(t, expected, expression.Regexp().String())
76-
}
77-
78-
directory = "../testdata/regex/"
79-
files, err = ioutil.ReadDir(directory)
80-
require.NoError(t, err)
81-
82-
for _, file := range files {
83-
contents, err := ioutil.ReadFile(directory + file.Name())
84-
require.NoError(t, err)
85-
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
86-
var expectation RegexExpectation
87-
err = yaml.Unmarshal(contents, &expectation)
88-
require.NoError(t, err)
89-
assertRegex(t, expectation.ExpectedRegex, expectation.Expression)
90-
})
91-
}
9265
})
9366

9467
t.Run("documents expression generation", func(t *testing.T) {

go/cucumber_expression_tokenizer_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ import (
88
"testing"
99
)
1010

11-
type TokenExpectation struct {
11+
type TokenizerExpectation struct {
1212
Expression string `yaml:"expression"`
1313
ExpectedTokens []token `yaml:"expected_tokens"`
1414
Exception string `yaml:"exception"`
1515
}
1616

1717
func TestCucumberExpressionTokenizer(t *testing.T) {
1818

19-
directory := "../testdata/tokens/"
19+
directory := "../testdata/cucumber-expression/tokenizer/"
2020
files, err := ioutil.ReadDir(directory)
2121
require.NoError(t, err)
2222

2323
for _, file := range files {
2424
contents, err := ioutil.ReadFile(directory + file.Name())
2525
require.NoError(t, err)
2626
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
27-
var expectation TokenExpectation
27+
var expectation TokenizerExpectation
2828
err = yaml.Unmarshal(contents, &expectation)
2929
require.NoError(t, err)
3030

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package cucumberexpressions
2+
3+
import (
4+
"fmt"
5+
"github.com/stretchr/testify/require"
6+
"gopkg.in/yaml.v3"
7+
"io/ioutil"
8+
"testing"
9+
)
10+
11+
type TransformationExpectation struct {
12+
Expression string `yaml:"expression"`
13+
ExpectedRegex string `yaml:"expected_regex"`
14+
}
15+
16+
func TestCucumberExpressionTransformation(t *testing.T) {
17+
18+
t.Run("acceptance tests pass", func(t *testing.T) {
19+
assertRegex := func(t *testing.T, expected string, expr string) {
20+
parameterTypeRegistry := NewParameterTypeRegistry()
21+
expression, err := NewCucumberExpression(expr, parameterTypeRegistry)
22+
require.NoError(t, err)
23+
require.Equal(t, expected, expression.Regexp().String())
24+
}
25+
26+
directory := "../testdata/cucumber-expression/transformation/"
27+
files, err := ioutil.ReadDir(directory)
28+
require.NoError(t, err)
29+
30+
for _, file := range files {
31+
contents, err := ioutil.ReadFile(directory + file.Name())
32+
require.NoError(t, err)
33+
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
34+
var expectation TransformationExpectation
35+
err = yaml.Unmarshal(contents, &expectation)
36+
require.NoError(t, err)
37+
assertRegex(t, expectation.ExpectedRegex, expectation.Expression)
38+
})
39+
}
40+
})
41+
}

go/regular_expression_test.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,58 @@
11
package cucumberexpressions
22

33
import (
4+
"fmt"
5+
"gopkg.in/yaml.v3"
6+
"io/ioutil"
47
"reflect"
58
"regexp"
69
"testing"
710

811
"github.com/stretchr/testify/require"
912
)
1013

14+
type RegularExpressionMatchingExpectation struct {
15+
Expression string `yaml:"expression"`
16+
Text string `yaml:"text"`
17+
ExpectedArgs []interface{} `yaml:"expected_args"`
18+
}
19+
1120
func TestRegularExpression(t *testing.T) {
21+
directory := "../testdata/regular-expression/matching/"
22+
files, err := ioutil.ReadDir(directory)
23+
require.NoError(t, err)
24+
25+
for _, file := range files {
26+
contents, err := ioutil.ReadFile(directory + file.Name())
27+
require.NoError(t, err)
28+
t.Run(fmt.Sprintf("%s", file.Name()), func(t *testing.T) {
29+
var expectation RegularExpressionMatchingExpectation
30+
err = yaml.Unmarshal(contents, &expectation)
31+
require.NoError(t, err)
32+
33+
parameterTypeRegistry := NewParameterTypeRegistry()
34+
expr := regexp.MustCompile(expectation.Expression)
35+
expression := NewRegularExpression(expr, parameterTypeRegistry)
36+
args, err := expression.Match(expectation.Text)
37+
require.NoError(t, err)
38+
values := make([]interface{}, len(args))
39+
for i, arg := range args {
40+
values[i] = arg.GetValue()
41+
}
42+
43+
require.Equal(t, expectation.ExpectedArgs, values)
44+
})
45+
}
46+
1247
t.Run("documents match arguments", func(t *testing.T) {
1348
parameterTypeRegistry := NewParameterTypeRegistry()
1449

15-
/// [capture-match-arguments]
1650
expr := regexp.MustCompile(`I have (\d+) cukes? in my (\w+) now`)
1751
expression := NewRegularExpression(expr, parameterTypeRegistry)
1852
args, err := expression.Match("I have 7 cukes in my belly now")
1953
require.NoError(t, err)
2054
require.Equal(t, args[0].GetValue(), 7)
2155
require.Equal(t, args[1].GetValue(), "belly")
22-
/// [capture-match-arguments]
2356
})
2457

2558
t.Run("does no transform by default", func(t *testing.T) {

java/src/test/java/io/cucumber/cucumberexpressions/AstExpectation.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionParserTest.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
package io.cucumber.cucumberexpressions;
22

33
import io.cucumber.cucumberexpressions.Ast.Node;
4+
import org.junit.jupiter.api.extension.ParameterContext;
45
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.converter.ArgumentConversionException;
7+
import org.junit.jupiter.params.converter.ArgumentConverter;
58
import org.junit.jupiter.params.converter.ConvertWith;
69
import org.junit.jupiter.params.provider.MethodSource;
10+
import org.yaml.snakeyaml.Yaml;
711

812
import java.io.IOException;
13+
import java.io.InputStream;
914
import java.nio.file.Path;
1015
import java.nio.file.Paths;
1116
import java.util.ArrayList;
1217
import java.util.Comparator;
1318
import java.util.List;
19+
import java.util.stream.Collectors;
1420

1521
import static java.nio.file.Files.newDirectoryStream;
22+
import static java.nio.file.Files.newInputStream;
1623
import static org.hamcrest.MatcherAssert.assertThat;
1724
import static org.hamcrest.Matchers.is;
1825
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -23,14 +30,14 @@ class CucumberExpressionParserTest {
2330

2431
private static List<Path> acceptance_tests_pass() throws IOException {
2532
List<Path> paths = new ArrayList<>();
26-
newDirectoryStream(Paths.get("..", "testdata", "ast")).forEach(paths::add);
33+
newDirectoryStream(Paths.get("..", "testdata", "cucumber-expression", "parser")).forEach(paths::add);
2734
paths.sort(Comparator.naturalOrder());
2835
return paths;
2936
}
3037

3138
@ParameterizedTest
3239
@MethodSource
33-
void acceptance_tests_pass(@ConvertWith(AstExpectation.Converter.class) AstExpectation expectation) {
40+
void acceptance_tests_pass(@ConvertWith(Converter.class) Expectation expectation) {
3441
if (expectation.exception == null) {
3542
Node node = parser.parse(expectation.expression);
3643
assertThat(node, is(expectation.expected_ast.toNode()));
@@ -42,4 +49,40 @@ void acceptance_tests_pass(@ConvertWith(AstExpectation.Converter.class) AstExpec
4249
}
4350
}
4451

52+
static class Expectation {
53+
public String expression;
54+
public YamlableNode expected_ast;
55+
public String exception;
56+
}
57+
58+
static class Converter implements ArgumentConverter {
59+
Yaml yaml = new Yaml();
60+
61+
@Override
62+
public Expectation convert(Object source, ParameterContext context) throws ArgumentConversionException {
63+
try {
64+
Path path = (Path) source;
65+
InputStream inputStream = newInputStream(path);
66+
return yaml.loadAs(inputStream, Expectation.class);
67+
} catch (IOException e) {
68+
throw new ArgumentConversionException("Could not load " + source, e);
69+
}
70+
}
71+
}
72+
73+
static class YamlableNode {
74+
public Ast.Node.Type type;
75+
public List<YamlableNode> nodes;
76+
public String token;
77+
public int start;
78+
public int end;
79+
80+
public Node toNode() {
81+
if (token != null) {
82+
return new Node(type, start, end, token);
83+
} else {
84+
return new Node(type, start, end, nodes.stream().map(YamlableNode::toNode).collect(Collectors.toList()));
85+
}
86+
}
87+
}
4588
}

0 commit comments

Comments
 (0)