* Add example about incorrect project structure This is to help reproduce #383 * Added some debugging statements * Update go.sum for example project * Made a cmd_run_test.go file in order to test and run the builderAndRunGodog function in order to see it fail * added new assertion test * Matt and I added debugging Co-authored-by: Matt Wynne <matt@mattwynne.net> * Matt and I tried to logging through the cobra command by using cmd.OutOrStdout( ) * Improved some debugging * Add a failing test for Builder that reproduces #383 * added new test for IncorrectProjectStructure #383 * Revert "Add a failing test for Builder that reproduces #383" This reverts commit e5b26933b5d4e979009f8f4341448fa8322720d2. * ignored vscode files Co-authored-by: Matt Wynne <matt@cucumber.io> * undid debugging changes * undid debugging changes * removed redundant test * added check for incorrect project structure we examined the output from running `go test` which tells us if we didn't find any test files. we tweaked the error message to follow the capitalization rules Co-authored-by: Matt Wynne <matt@cucumber.io> * Update internal/builder/builder_test.go Co-authored-by: Matt Wynne <matt@mattwynne.net> Co-authored-by: Matt Wynne <matt@cucumber.io> Co-authored-by: Viacheslav Poturaev <nanopeni@gmail.com>
		
			
				
	
	
		
			362 строки
		
	
	
	
		
			8,4 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			362 строки
		
	
	
	
		
			8,4 КиБ
		
	
	
	
		
			Go
		
	
	
	
	
	
package builder_test
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"go/build"
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	"github.com/stretchr/testify/require"
 | 
						|
 | 
						|
	"github.com/cucumber/godog"
 | 
						|
	"github.com/cucumber/godog/internal/builder"
 | 
						|
)
 | 
						|
 | 
						|
func InitializeScenario(ctx *godog.ScenarioContext) {}
 | 
						|
 | 
						|
func Test_GodogBuild(t *testing.T) {
 | 
						|
	t.Run("WithSourceNotInGoPath", testWithSourceNotInGoPath)
 | 
						|
	t.Run("WithoutSourceNotInGoPath", testWithoutSourceNotInGoPath)
 | 
						|
	t.Run("WithoutTestSourceNotInGoPath", testWithoutTestSourceNotInGoPath)
 | 
						|
	t.Run("WithinGopath", testWithinGopath)
 | 
						|
	t.Run("WithVendoredGodogWithoutModule", testWithVendoredGodogWithoutModule)
 | 
						|
	t.Run("WithVendoredGodogAndMod", testWithVendoredGodogAndMod)
 | 
						|
	t.Run("WithIncorrectProjectStructure", testWithIncorrectProjectStructure)
 | 
						|
 | 
						|
	t.Run("WithModule", func(t *testing.T) {
 | 
						|
		t.Run("OutsideGopathAndHavingOnlyFeature", testOutsideGopathAndHavingOnlyFeature)
 | 
						|
		t.Run("OutsideGopath", testOutsideGopath)
 | 
						|
		t.Run("OutsideGopathWithXTest", testOutsideGopathWithXTest)
 | 
						|
		t.Run("InsideGopath", testInsideGopath)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
var builderFeatureFile = `Feature: eat godogs
 | 
						|
  In order to be happy
 | 
						|
  As a hungry gopher
 | 
						|
  I need to be able to eat godogs
 | 
						|
 | 
						|
  Scenario: Eat 5 out of 12
 | 
						|
    Given there are 12 godogs
 | 
						|
    When I eat 5
 | 
						|
    Then there should be 7 remaining
 | 
						|
`
 | 
						|
 | 
						|
var builderTestFile = `package godogs
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	"github.com/cucumber/godog"
 | 
						|
)
 | 
						|
 | 
						|
func thereAreGodogs(available int) error {
 | 
						|
	Godogs = available
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func iEat(num int) error {
 | 
						|
	if Godogs < num {
 | 
						|
		return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
 | 
						|
	}
 | 
						|
	Godogs -= num
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func thereShouldBeRemaining(remaining int) error {
 | 
						|
	if Godogs != remaining {
 | 
						|
		return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
func InitializeScenario(ctx *godog.ScenarioContext) {
 | 
						|
	ctx.Step("^there are (\\d+) godogs$", thereAreGodogs)
 | 
						|
	ctx.Step("^I eat (\\d+)$", iEat)
 | 
						|
	ctx.Step("^there should be (\\d+) remaining$", thereShouldBeRemaining)
 | 
						|
 | 
						|
	ctx.BeforeScenario(func(*godog.Scenario) {
 | 
						|
		Godogs = 0 // clean the state before every scenario
 | 
						|
	})
 | 
						|
}
 | 
						|
`
 | 
						|
 | 
						|
var builderXTestFile = `package godogs_test
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	"github.com/cucumber/godog"
 | 
						|
 | 
						|
	"godogs"
 | 
						|
)
 | 
						|
 | 
						|
func thereAreGodogs(available int) error {
 | 
						|
	godogs.Godogs = available
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func iEat(num int) error {
 | 
						|
	if godogs.Godogs < num {
 | 
						|
		return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, godogs.Godogs)
 | 
						|
	}
 | 
						|
	godogs.Godogs -= num
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func thereShouldBeRemaining(remaining int) error {
 | 
						|
	if godogs.Godogs != remaining {
 | 
						|
		return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, godogs.Godogs)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func InitializeScenario(ctx *godog.ScenarioContext) {
 | 
						|
	ctx.Step("^there are (\\d+) godogs$", thereAreGodogs)
 | 
						|
	ctx.Step("^I eat (\\d+)$", iEat)
 | 
						|
	ctx.Step("^there should be (\\d+) remaining$", thereShouldBeRemaining)
 | 
						|
 | 
						|
	ctx.BeforeScenario(func(*godog.Scenario) {
 | 
						|
		godogs.Godogs = 0 // clean the state before every scenario
 | 
						|
	})
 | 
						|
}
 | 
						|
`
 | 
						|
 | 
						|
var builderMainCodeFile = `package godogs
 | 
						|
 | 
						|
// Godogs available to eat
 | 
						|
var Godogs int
 | 
						|
 | 
						|
func main() {
 | 
						|
}
 | 
						|
`
 | 
						|
 | 
						|
var emptyBuilderTestFile = `package godogs
 | 
						|
 | 
						|
import "github.com/cucumber/godog"
 | 
						|
 
 | 
						|
func InitializeScenario(ctx *godog.ScenarioContext) {}
 | 
						|
`
 | 
						|
 | 
						|
var builderModFile = `module godogs`
 | 
						|
 | 
						|
func buildTestPackage(dir string, files map[string]string) error {
 | 
						|
	if err := os.MkdirAll(dir, 0755); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	for name, content := range files {
 | 
						|
		if err := ioutil.WriteFile(filepath.Join(dir, name), []byte(content), 0644); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func buildTestCommand(t *testing.T, wd, featureFile string) *exec.Cmd {
 | 
						|
	testBin := filepath.Join(wd, "godog.test")
 | 
						|
	testBin, err := filepath.Abs(testBin)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	if build.Default.GOOS == "windows" {
 | 
						|
		testBin += ".exe"
 | 
						|
	}
 | 
						|
 | 
						|
	err = builder.Build(testBin)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	featureFilePath := filepath.Join(wd, featureFile)
 | 
						|
	return exec.Command(testBin, featureFilePath)
 | 
						|
}
 | 
						|
 | 
						|
func envVarsWithoutGopath() []string {
 | 
						|
	var env []string
 | 
						|
 | 
						|
	for _, def := range os.Environ() {
 | 
						|
		if strings.Index(def, "GOPATH=") == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		env = append(env, def)
 | 
						|
	}
 | 
						|
 | 
						|
	return env
 | 
						|
}
 | 
						|
 | 
						|
func testWithSourceNotInGoPath(t *testing.T) {
 | 
						|
	dir := filepath.Join(os.TempDir(), t.Name(), "godogs")
 | 
						|
	files := map[string]string{
 | 
						|
		"godogs.feature": builderFeatureFile,
 | 
						|
		"godogs.go":      builderMainCodeFile,
 | 
						|
		"godogs_test.go": builderTestFile,
 | 
						|
		"go.mod":         builderModFile,
 | 
						|
	}
 | 
						|
 | 
						|
	err := buildTestPackage(dir, files)
 | 
						|
	defer os.RemoveAll(dir)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	prevDir, err := os.Getwd()
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	err = os.Chdir(dir)
 | 
						|
	require.Nil(t, err)
 | 
						|
	defer os.Chdir(prevDir)
 | 
						|
 | 
						|
	testCmd := buildTestCommand(t, "", "godogs.feature")
 | 
						|
	testCmd.Env = os.Environ()
 | 
						|
 | 
						|
	var stdout, stderr bytes.Buffer
 | 
						|
	testCmd.Stdout = &stdout
 | 
						|
	testCmd.Stderr = &stderr
 | 
						|
 | 
						|
	err = testCmd.Run()
 | 
						|
	require.Nil(t, err, "stdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String())
 | 
						|
}
 | 
						|
 | 
						|
func testWithoutSourceNotInGoPath(t *testing.T) {
 | 
						|
	builderTC := builderTestCase{}
 | 
						|
 | 
						|
	builderTC.dir = filepath.Join(os.TempDir(), t.Name(), "godogs")
 | 
						|
	builderTC.files = map[string]string{
 | 
						|
		"godogs.feature": builderFeatureFile,
 | 
						|
		"go.mod":         builderModFile,
 | 
						|
	}
 | 
						|
 | 
						|
	builderTC.run(t)
 | 
						|
}
 | 
						|
 | 
						|
func testWithoutTestSourceNotInGoPath(t *testing.T) {
 | 
						|
	builderTC := builderTestCase{}
 | 
						|
 | 
						|
	builderTC.dir = filepath.Join(os.TempDir(), t.Name(), "godogs")
 | 
						|
	builderTC.files = map[string]string{
 | 
						|
		"godogs.feature": builderFeatureFile,
 | 
						|
		"godogs.go":      builderMainCodeFile,
 | 
						|
		"go.mod":         builderModFile,
 | 
						|
	}
 | 
						|
 | 
						|
	builderTC.run(t)
 | 
						|
}
 | 
						|
 | 
						|
func testWithIncorrectProjectStructure(t *testing.T) {
 | 
						|
	dir := filepath.Join(os.TempDir(), t.Name(), "godogs")
 | 
						|
	files := map[string]string{
 | 
						|
		"godogs.go": emptyBuilderTestFile,
 | 
						|
		"go.mod":    builderModFile,
 | 
						|
	}
 | 
						|
 | 
						|
	err := buildTestPackage(dir, files)
 | 
						|
	defer os.RemoveAll(dir)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	prevDir, err := os.Getwd()
 | 
						|
	require.Nil(t, err)
 | 
						|
	err = os.Chdir(dir)
 | 
						|
	require.Nil(t, err)
 | 
						|
	defer os.Chdir(prevDir)
 | 
						|
 | 
						|
	testBin, err := filepath.Abs(filepath.Join(dir, "godog.test"))
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	if build.Default.GOOS == "windows" {
 | 
						|
		testBin += ".exe"
 | 
						|
	}
 | 
						|
 | 
						|
	// call the builder - we should get an error
 | 
						|
	err = builder.Build(testBin)
 | 
						|
	// check that we even got an error at all
 | 
						|
	require.NotNil(t, err)
 | 
						|
	// now check the details of the error message
 | 
						|
	require.EqualError(t, err, "incorrect project structure: no test files found")
 | 
						|
}
 | 
						|
 | 
						|
func testWithinGopath(t *testing.T) {
 | 
						|
	builderTC := builderTestCase{}
 | 
						|
 | 
						|
	gopath := filepath.Join(os.TempDir(), t.Name(), "_gp")
 | 
						|
	defer os.RemoveAll(gopath)
 | 
						|
 | 
						|
	builderTC.dir = filepath.Join(gopath, "src", "godogs")
 | 
						|
	builderTC.files = map[string]string{
 | 
						|
		"godogs.feature": builderFeatureFile,
 | 
						|
		"godogs.go":      builderMainCodeFile,
 | 
						|
		"godogs_test.go": builderTestFile,
 | 
						|
		"go.mod":         builderModFile,
 | 
						|
	}
 | 
						|
 | 
						|
	pkg := filepath.Join(gopath, "src", "github.com", "cucumber")
 | 
						|
	err := os.MkdirAll(pkg, 0755)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	wd, err := os.Getwd()
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	// symlink godog package
 | 
						|
	err = os.Symlink(wd, filepath.Join(pkg, "godog"))
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	builderTC.testCmdEnv = []string{"GOPATH=" + gopath}
 | 
						|
	builderTC.run(t)
 | 
						|
}
 | 
						|
 | 
						|
func testWithVendoredGodogWithoutModule(t *testing.T) {
 | 
						|
	builderTC := builderTestCase{}
 | 
						|
 | 
						|
	gopath := filepath.Join(os.TempDir(), t.Name(), "_gp")
 | 
						|
	defer os.RemoveAll(gopath)
 | 
						|
 | 
						|
	builderTC.dir = filepath.Join(gopath, "src", "godogs")
 | 
						|
	builderTC.files = map[string]string{
 | 
						|
		"godogs.feature": builderFeatureFile,
 | 
						|
	}
 | 
						|
 | 
						|
	pkg := filepath.Join(builderTC.dir, "vendor", "github.com", "cucumber")
 | 
						|
	err := os.MkdirAll(pkg, 0755)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	wd, err := os.Getwd()
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	// symlink godog package
 | 
						|
	err = os.Symlink(wd, filepath.Join(pkg, "godog"))
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	builderTC.testCmdEnv = append(envVarsWithoutGopath(), "GOPATH="+gopath)
 | 
						|
	builderTC.run(t)
 | 
						|
}
 | 
						|
 | 
						|
type builderTestCase struct {
 | 
						|
	dir        string
 | 
						|
	files      map[string]string
 | 
						|
	goModCmds  []*exec.Cmd
 | 
						|
	testCmdEnv []string
 | 
						|
}
 | 
						|
 | 
						|
func (bt builderTestCase) run(t *testing.T) {
 | 
						|
	err := buildTestPackage(bt.dir, bt.files)
 | 
						|
	defer os.RemoveAll(bt.dir)
 | 
						|
	require.Nil(t, err)
 | 
						|
 | 
						|
	for _, c := range bt.goModCmds {
 | 
						|
		c.Dir = bt.dir
 | 
						|
		out, err := c.CombinedOutput()
 | 
						|
		require.Nil(t, err, "%s", string(out))
 | 
						|
	}
 | 
						|
 | 
						|
	testCmd := buildTestCommand(t, bt.dir, "godogs.feature")
 | 
						|
	testCmd.Env = append(os.Environ(), bt.testCmdEnv...)
 | 
						|
 | 
						|
	var stdout, stderr bytes.Buffer
 | 
						|
	testCmd.Stdout = &stdout
 | 
						|
	testCmd.Stderr = &stderr
 | 
						|
 | 
						|
	err = testCmd.Run()
 | 
						|
	require.Nil(t, err, "stdout:\n%s\nstderr:\n%s", stdout.String(), stderr.String())
 | 
						|
}
 |