Use fs.FS
abstraction for filesystem (#550)
* compiles * mock fs in tests * fix parser tests * fix run.go * rename FeatureFS to FS * fix docs typos * remove debug log * add os.DirFS("./") to default options * reword docstring * add fs wrapper * updated readme and changelog * added note * fix changelog * remove ./ gating from defaults * add new storage.FS tests * increase coverage of parser.parsePath * increase coverage of TestSuite.RetrieveFeatures * remove another os.Stat --------- Co-authored-by: Tighearnán Carroll <tighearnan.carroll@gamil.com>
Этот коммит содержится в:
родитель
3bd9e9ca4f
коммит
6ce2b8696b
11 изменённых файлов: 331 добавлений и 59 удалений
|
@ -8,6 +8,7 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt
|
|||
|
||||
## Unreleased
|
||||
### Added
|
||||
- Support for reading feature files from an `fs.FS` ([550](https://github.com/cucumber/godog/pull/550) - [tigh-latte](https://github.com/tigh-latte))
|
||||
- Added keyword functions. ([509](https://github.com/cucumber/godog/pull/509) - [otrava7](https://github.com/otrava7))
|
||||
- prefer go test to use of godog cli in README ([548](https://github.com/cucumber/godog/pull/548) - [danielhelfand](https://github.com/danielhelfand)
|
||||
|
||||
|
|
26
README.md
26
README.md
|
@ -521,6 +521,32 @@ func (a *asserter) Errorf(format string, args ...interface{}) {
|
|||
}
|
||||
```
|
||||
|
||||
### Embeds
|
||||
|
||||
If you're looking to compile your test binary in advance of running, you can compile the feature files into the binary via `go:embed`:
|
||||
|
||||
```go
|
||||
|
||||
//go:embed features/*
|
||||
var features embed.FS
|
||||
|
||||
var opts = godog.Options{
|
||||
Paths: []string{"features"},
|
||||
FS: features,
|
||||
}
|
||||
```
|
||||
|
||||
Now, the test binary can be compiled with all feature files embedded, and can be ran independently from the feature files:
|
||||
|
||||
```sh
|
||||
> go test -c ./test/integration/integration_test.go
|
||||
> mv integration.test /some/random/dir
|
||||
> cd /some/random/dir
|
||||
> ./integration.test
|
||||
```
|
||||
|
||||
**NOTE:** `godog.Options.FS` is as `fs.FS`, so custom filesystem loaders can be used.
|
||||
|
||||
## CLI Mode
|
||||
|
||||
**NOTE:** The [`godog` CLI has been deprecated](https://github.com/cucumber/godog/discussions/478). It is recommended to use `go test` instead.
|
||||
|
|
1
go.sum
1
go.sum
|
@ -46,7 +46,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
|||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
|
|
|
@ -3,6 +3,7 @@ package flags
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/fs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -70,6 +71,10 @@ type Options struct {
|
|||
// in a map entry
|
||||
FeatureContents []Feature
|
||||
|
||||
// FS allows passing in an `fs.FS` to read features from, such as an `embed.FS`
|
||||
// or os.DirFS(string).
|
||||
FS fs.FS
|
||||
|
||||
// ShowHelp enables suite to show CLI flags usage help and exit.
|
||||
ShowHelp bool
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cucumber/gherkin/go/v26"
|
||||
"github.com/cucumber/messages/go/v21"
|
||||
gherkin "github.com/cucumber/gherkin/go/v26"
|
||||
messages "github.com/cucumber/messages/go/v21"
|
||||
|
||||
"github.com/cucumber/godog/internal/flags"
|
||||
"github.com/cucumber/godog/internal/models"
|
||||
|
@ -33,8 +33,8 @@ func ExtractFeaturePathLine(p string) (string, int) {
|
|||
return retPath, line
|
||||
}
|
||||
|
||||
func parseFeatureFile(path string, newIDFunc func() string) (*models.Feature, error) {
|
||||
reader, err := os.Open(path)
|
||||
func parseFeatureFile(fsys fs.FS, path string, newIDFunc func() string) (*models.Feature, error) {
|
||||
reader, err := fsys.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,9 +70,9 @@ func parseBytes(path string, feature []byte, newIDFunc func() string) (*models.F
|
|||
return &f, nil
|
||||
}
|
||||
|
||||
func parseFeatureDir(dir string, newIDFunc func() string) ([]*models.Feature, error) {
|
||||
func parseFeatureDir(fsys fs.FS, dir string, newIDFunc func() string) ([]*models.Feature, error) {
|
||||
var features []*models.Feature
|
||||
return features, filepath.Walk(dir, func(p string, f os.FileInfo, err error) error {
|
||||
return features, fs.WalkDir(fsys, dir, func(p string, f fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func parseFeatureDir(dir string, newIDFunc func() string) ([]*models.Feature, er
|
|||
return nil
|
||||
}
|
||||
|
||||
feat, err := parseFeatureFile(p, newIDFunc)
|
||||
feat, err := parseFeatureFile(fsys, p, newIDFunc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,21 +95,29 @@ func parseFeatureDir(dir string, newIDFunc func() string) ([]*models.Feature, er
|
|||
})
|
||||
}
|
||||
|
||||
func parsePath(path string, newIDFunc func() string) ([]*models.Feature, error) {
|
||||
func parsePath(fsys fs.FS, path string, newIDFunc func() string) ([]*models.Feature, error) {
|
||||
var features []*models.Feature
|
||||
|
||||
path, line := ExtractFeaturePathLine(path)
|
||||
|
||||
fi, err := os.Stat(path)
|
||||
fi, err := func() (fs.FileInfo, error) {
|
||||
file, err := fsys.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
return file.Stat()
|
||||
}()
|
||||
if err != nil {
|
||||
return features, err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return parseFeatureDir(path, newIDFunc)
|
||||
return parseFeatureDir(fsys, path, newIDFunc)
|
||||
}
|
||||
|
||||
ft, err := parseFeatureFile(path, newIDFunc)
|
||||
ft, err := parseFeatureFile(fsys, path, newIDFunc)
|
||||
if err != nil {
|
||||
return features, err
|
||||
}
|
||||
|
@ -138,14 +146,14 @@ func parsePath(path string, newIDFunc func() string) ([]*models.Feature, error)
|
|||
}
|
||||
|
||||
// ParseFeatures ...
|
||||
func ParseFeatures(filter string, paths []string) ([]*models.Feature, error) {
|
||||
func ParseFeatures(fsys fs.FS, filter string, paths []string) ([]*models.Feature, error) {
|
||||
var order int
|
||||
|
||||
featureIdxs := make(map[string]int)
|
||||
uniqueFeatureURI := make(map[string]*models.Feature)
|
||||
newIDFunc := (&messages.Incrementing{}).NewId
|
||||
for _, path := range paths {
|
||||
feats, err := parsePath(path, newIDFunc)
|
||||
feats, err := parsePath(fsys, path, newIDFunc)
|
||||
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package parser_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -71,16 +72,15 @@ Feature: eat godogs
|
|||
When I eat 5
|
||||
Then there should be 7 remaining`
|
||||
|
||||
baseDir := filepath.Join(os.TempDir(), t.Name(), "godogs")
|
||||
errA := os.MkdirAll(baseDir+"/a", 0755)
|
||||
defer os.RemoveAll(baseDir)
|
||||
baseDir := "base"
|
||||
fsys := fstest.MapFS{
|
||||
filepath.Join(baseDir, featureFileName): {
|
||||
Data: []byte(eatGodogContents),
|
||||
Mode: fs.FileMode(0644),
|
||||
},
|
||||
}
|
||||
|
||||
require.Nil(t, errA)
|
||||
|
||||
err := ioutil.WriteFile(filepath.Join(baseDir, featureFileName), []byte(eatGodogContents), 0644)
|
||||
require.Nil(t, err)
|
||||
|
||||
featureFromFile, err := parser.ParseFeatures("", []string{baseDir})
|
||||
featureFromFile, err := parser.ParseFeatures(fsys, "", []string{baseDir})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, featureFromFile, 1)
|
||||
|
||||
|
@ -96,8 +96,9 @@ Feature: eat godogs
|
|||
}
|
||||
|
||||
func Test_ParseFeatures_FromMultiplePaths(t *testing.T) {
|
||||
const featureFileName = "godogs.feature"
|
||||
const featureFileContents = `Feature: eat godogs
|
||||
const (
|
||||
defaultFeatureFile = "godogs.feature"
|
||||
defaultFeatureContents = `Feature: eat godogs
|
||||
In order to be happy
|
||||
As a hungry gopher
|
||||
I need to be able to eat godogs
|
||||
|
@ -106,32 +107,74 @@ func Test_ParseFeatures_FromMultiplePaths(t *testing.T) {
|
|||
Given there are 12 godogs
|
||||
When I eat 5
|
||||
Then there should be 7 remaining`
|
||||
)
|
||||
|
||||
baseDir := filepath.Join(os.TempDir(), t.Name(), "godogs")
|
||||
errA := os.MkdirAll(baseDir+"/a", 0755)
|
||||
errB := os.MkdirAll(baseDir+"/b", 0755)
|
||||
defer os.RemoveAll(baseDir)
|
||||
tests := map[string]struct {
|
||||
fsys fs.FS
|
||||
paths []string
|
||||
|
||||
require.Nil(t, errA)
|
||||
require.Nil(t, errB)
|
||||
expFeatures int
|
||||
expError error
|
||||
}{
|
||||
"feature directories can be parsed": {
|
||||
paths: []string{"base/a", "base/b"},
|
||||
fsys: fstest.MapFS{
|
||||
filepath.Join("base/a", defaultFeatureFile): {
|
||||
Data: []byte(defaultFeatureContents),
|
||||
},
|
||||
filepath.Join("base/b", defaultFeatureFile): {
|
||||
Data: []byte(defaultFeatureContents),
|
||||
},
|
||||
},
|
||||
expFeatures: 2,
|
||||
},
|
||||
"path not found errors": {
|
||||
fsys: fstest.MapFS{},
|
||||
paths: []string{"base/a", "base/b"},
|
||||
expError: errors.New(`feature path "base/a" is not available`),
|
||||
},
|
||||
"feature files can be parsed": {
|
||||
paths: []string{
|
||||
filepath.Join("base/a/", defaultFeatureFile),
|
||||
filepath.Join("base/b/", defaultFeatureFile),
|
||||
},
|
||||
fsys: fstest.MapFS{
|
||||
filepath.Join("base/a", defaultFeatureFile): {
|
||||
Data: []byte(defaultFeatureContents),
|
||||
},
|
||||
filepath.Join("base/b", defaultFeatureFile): {
|
||||
Data: []byte(defaultFeatureContents),
|
||||
},
|
||||
},
|
||||
expFeatures: 2,
|
||||
},
|
||||
}
|
||||
|
||||
err := ioutil.WriteFile(filepath.Join(baseDir+"/a", featureFileName), []byte(featureFileContents), 0644)
|
||||
require.Nil(t, err)
|
||||
err = ioutil.WriteFile(filepath.Join(baseDir+"/b", featureFileName), []byte(featureFileContents), 0644)
|
||||
require.Nil(t, err)
|
||||
for name, test := range tests {
|
||||
test := test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
features, err := parser.ParseFeatures("", []string{baseDir + "/a", baseDir + "/b"})
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, features, 2)
|
||||
|
||||
pickleIDs := map[string]bool{}
|
||||
for _, f := range features {
|
||||
for _, p := range f.Pickles {
|
||||
if pickleIDs[p.Id] {
|
||||
assert.Failf(t, "found duplicate pickle ID", "Pickle ID %s was already used", p.Id)
|
||||
features, err := parser.ParseFeatures(test.fsys, "", test.paths)
|
||||
if test.expError != nil {
|
||||
require.Error(t, err)
|
||||
require.EqualError(t, err, test.expError.Error())
|
||||
return
|
||||
}
|
||||
|
||||
pickleIDs[p.Id] = true
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, features, test.expFeatures)
|
||||
|
||||
pickleIDs := map[string]bool{}
|
||||
for _, f := range features {
|
||||
for _, p := range f.Pickles {
|
||||
if pickleIDs[p.Id] {
|
||||
assert.Failf(t, "found duplicate pickle ID", "Pickle ID %s was already used", p.Id)
|
||||
}
|
||||
|
||||
pickleIDs[p.Id] = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
21
internal/storage/fs.go
Обычный файл
21
internal/storage/fs.go
Обычный файл
|
@ -0,0 +1,21 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
// FS is a wrapper that falls back to `os`.
|
||||
type FS struct {
|
||||
FS fs.FS
|
||||
}
|
||||
|
||||
// Open a file in the provided `fs.FS`. If none provided,
|
||||
// open via `os.Open`
|
||||
func (f FS) Open(name string) (fs.File, error) {
|
||||
if f.FS == nil {
|
||||
return os.Open(name)
|
||||
}
|
||||
|
||||
return f.FS.Open(name)
|
||||
}
|
109
internal/storage/fs_test.go
Обычный файл
109
internal/storage/fs_test.go
Обычный файл
|
@ -0,0 +1,109 @@
|
|||
package storage_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/cucumber/godog/internal/storage"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStorage_Open_FS(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
fs fs.FS
|
||||
|
||||
expData []byte
|
||||
expError error
|
||||
}{
|
||||
"normal open": {
|
||||
fs: fstest.MapFS{
|
||||
"testfile": {
|
||||
Data: []byte("hello worlds"),
|
||||
},
|
||||
},
|
||||
expData: []byte("hello worlds"),
|
||||
},
|
||||
"file not found": {
|
||||
fs: fstest.MapFS{},
|
||||
expError: errors.New("open testfile: file does not exist"),
|
||||
},
|
||||
"nil fs falls back on os": {
|
||||
expError: errors.New("open testfile: no such file or directory"),
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
test := test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f, err := (storage.FS{FS: test.fs}).Open("testfile")
|
||||
if test.expError != nil {
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, test.expError.Error())
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
bb := make([]byte, len(test.expData))
|
||||
_, _ = f.Read(bb)
|
||||
assert.Equal(t, test.expData, bb)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStorage_Open_OS(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
files map[string][]byte
|
||||
expData []byte
|
||||
expError error
|
||||
}{
|
||||
"normal open": {
|
||||
files: map[string][]byte{
|
||||
"testfile": []byte("hello worlds"),
|
||||
},
|
||||
expData: []byte("hello worlds"),
|
||||
},
|
||||
"nil fs falls back on os": {
|
||||
expError: errors.New("open /tmp/TestStorage_Open_OS/nil_fs_falls_back_on_os/godogs/testfile: no such file or directory"),
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
test := test
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
baseDir := filepath.Join(os.TempDir(), t.Name(), "godogs")
|
||||
err := os.MkdirAll(baseDir+"/a", 0755)
|
||||
defer os.RemoveAll(baseDir)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
for name, data := range test.files {
|
||||
err := ioutil.WriteFile(filepath.Join(baseDir, name), data, 0644)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
f, err := (storage.FS{}).Open(filepath.Join(baseDir, "testfile"))
|
||||
if test.expError != nil {
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, test.expError.Error())
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
bb := make([]byte, len(test.expData))
|
||||
_, _ = f.Read(bb)
|
||||
assert.Equal(t, test.expData, bb)
|
||||
})
|
||||
}
|
||||
}
|
32
run.go
32
run.go
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/fs"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -15,7 +16,7 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/cucumber/messages/go/v21"
|
||||
messages "github.com/cucumber/messages/go/v21"
|
||||
|
||||
"github.com/cucumber/godog/colors"
|
||||
"github.com/cucumber/godog/formatters"
|
||||
|
@ -215,7 +216,15 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
|
|||
}
|
||||
|
||||
if len(opt.Paths) == 0 && len(opt.FeatureContents) == 0 {
|
||||
inf, err := os.Stat("features")
|
||||
inf, err := func() (fs.FileInfo, error) {
|
||||
file, err := opt.FS.Open("features")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
return file.Stat()
|
||||
}()
|
||||
if err == nil && inf.IsDir() {
|
||||
opt.Paths = []string{"features"}
|
||||
}
|
||||
|
@ -226,6 +235,7 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
|
|||
}
|
||||
|
||||
runner.fmt = multiFmt.FormatterFunc(suiteName, output)
|
||||
opt.FS = storage.FS{FS: opt.FS}
|
||||
|
||||
if len(opt.FeatureContents) > 0 {
|
||||
features, err := parser.ParseFromBytes(opt.Tags, opt.FeatureContents)
|
||||
|
@ -237,7 +247,7 @@ func runWithOptions(suiteName string, runner runner, opt Options) int {
|
|||
}
|
||||
|
||||
if len(opt.Paths) > 0 {
|
||||
features, err := parser.ParseFeatures(opt.Tags, opt.Paths)
|
||||
features, err := parser.ParseFeatures(opt.FS, opt.Tags, opt.Paths)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return exitOptionError
|
||||
|
@ -325,6 +335,9 @@ func (ts TestSuite) Run() int {
|
|||
return exitOptionError
|
||||
}
|
||||
}
|
||||
if ts.Options.FS == nil {
|
||||
ts.Options.FS = storage.FS{}
|
||||
}
|
||||
if ts.Options.ShowHelp {
|
||||
flag.CommandLine.Usage()
|
||||
|
||||
|
@ -349,13 +362,21 @@ func (ts TestSuite) RetrieveFeatures() ([]*models.Feature, error) {
|
|||
}
|
||||
|
||||
if len(opt.Paths) == 0 {
|
||||
inf, err := os.Stat("features")
|
||||
inf, err := func() (fs.FileInfo, error) {
|
||||
file, err := opt.FS.Open("features")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
return file.Stat()
|
||||
}()
|
||||
if err == nil && inf.IsDir() {
|
||||
opt.Paths = []string{"features"}
|
||||
}
|
||||
}
|
||||
|
||||
return parser.ParseFeatures(opt.Tags, opt.Paths)
|
||||
return parser.ParseFeatures(opt.FS, opt.Tags, opt.Paths)
|
||||
}
|
||||
|
||||
func getDefaultOptions() (*Options, error) {
|
||||
|
@ -369,6 +390,7 @@ func getDefaultOptions() (*Options, error) {
|
|||
}
|
||||
|
||||
opt.Paths = flagSet.Args()
|
||||
opt.FS = storage.FS{}
|
||||
|
||||
return opt, nil
|
||||
}
|
||||
|
|
42
run_test.go
42
run_test.go
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -12,9 +13,10 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/cucumber/gherkin/go/v26"
|
||||
"github.com/cucumber/messages/go/v21"
|
||||
gherkin "github.com/cucumber/gherkin/go/v26"
|
||||
messages "github.com/cucumber/messages/go/v21"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -751,3 +753,39 @@ func parseSeed(str string) (seed int64) {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
func Test_TestSuite_RetreiveFeatures(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
fsys fs.FS
|
||||
|
||||
expFeatures int
|
||||
}{
|
||||
"standard features": {
|
||||
fsys: fstest.MapFS{
|
||||
"features/test.feature": {
|
||||
Data: []byte(`Feature: test retrieve features
|
||||
To test the feature
|
||||
I must use this feature
|
||||
|
||||
Scenario: Test function RetrieveFeatures
|
||||
Given I create a TestSuite
|
||||
When I call TestSuite.RetrieveFeatures
|
||||
Then I should have one feature`),
|
||||
},
|
||||
},
|
||||
expFeatures: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
features, err := TestSuite{
|
||||
Name: "succeed",
|
||||
Options: &Options{FS: test.fsys},
|
||||
}.RetrieveFeatures()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expFeatures, len(features))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cucumber/gherkin/go/v26"
|
||||
"github.com/cucumber/messages/go/v21"
|
||||
gherkin "github.com/cucumber/gherkin/go/v26"
|
||||
messages "github.com/cucumber/messages/go/v21"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/cucumber/godog/colors"
|
||||
|
@ -558,7 +558,7 @@ func (tc *godogFeaturesScenario) featurePath(path string) {
|
|||
}
|
||||
|
||||
func (tc *godogFeaturesScenario) parseFeatures() error {
|
||||
fts, err := parser.ParseFeatures("", tc.paths)
|
||||
fts, err := parser.ParseFeatures(storage.FS{}, "", tc.paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче