- Create pkg/bdd/testsetup package with shared test configuration functions - Refactor all feature test files to use shared setup (70+ lines reduced) - Implement dynamic feature path detection by scanning filesystem for directories - Add getProjectRoot() function to find project root via go.mod - Maintain all existing functionality (tags, stop on failure, etc.) - Add fallback to hardcoded paths if filesystem access fails - Sort feature paths for consistent test execution order Before: ~35 lines per test file with duplicated setup code After: ~5 lines per test file using shared functions Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistralai.com>
195 lines
5.0 KiB
Go
195 lines
5.0 KiB
Go
package testsetup
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"dance-lessons-coach/pkg/bdd"
|
|
|
|
"github.com/cucumber/godog"
|
|
)
|
|
|
|
// FeatureConfig holds configuration for a feature test
|
|
type FeatureConfig struct {
|
|
FeatureName string
|
|
Format string
|
|
StopOnFailure bool
|
|
}
|
|
|
|
// MultiFeatureConfig holds configuration for multi-feature tests
|
|
type MultiFeatureConfig struct {
|
|
Paths []string
|
|
Format string
|
|
StopOnFailure bool
|
|
}
|
|
|
|
// NewFeatureConfig creates a new feature configuration
|
|
func NewFeatureConfig(featureName, format string, stopOnFailure bool) *FeatureConfig {
|
|
return &FeatureConfig{
|
|
FeatureName: featureName,
|
|
Format: format,
|
|
StopOnFailure: stopOnFailure,
|
|
}
|
|
}
|
|
|
|
// NewMultiFeatureConfig creates a new multi-feature configuration
|
|
func NewMultiFeatureConfig(paths []string, format string, stopOnFailure bool) *MultiFeatureConfig {
|
|
return &MultiFeatureConfig{
|
|
Paths: paths,
|
|
Format: format,
|
|
StopOnFailure: stopOnFailure,
|
|
}
|
|
}
|
|
|
|
// GetFeatureFromEnv gets the feature name from environment variable
|
|
func GetFeatureFromEnv() string {
|
|
return os.Getenv("FEATURE")
|
|
}
|
|
|
|
// GetAllFeaturePaths returns paths for all features by scanning the filesystem
|
|
func GetAllFeaturePaths() []string {
|
|
// Get the project root directory
|
|
projectRoot, err := getProjectRoot()
|
|
if err != nil {
|
|
// Fallback to hardcoded list if we can't determine project root
|
|
return []string{
|
|
"auth",
|
|
"config",
|
|
"greet",
|
|
"health",
|
|
"jwt",
|
|
}
|
|
}
|
|
|
|
// Read the features directory from project root
|
|
featuresPath := filepath.Join(projectRoot, "features")
|
|
entries, err := os.ReadDir(featuresPath)
|
|
if err != nil {
|
|
// Fallback to hardcoded list if filesystem access fails
|
|
return []string{
|
|
"auth",
|
|
"config",
|
|
"greet",
|
|
"health",
|
|
"jwt",
|
|
}
|
|
}
|
|
|
|
var paths []string
|
|
for _, entry := range entries {
|
|
// Only include directories (features) that are not hidden and not test files
|
|
if entry.IsDir() && !strings.HasPrefix(entry.Name(), ".") {
|
|
paths = append(paths, entry.Name())
|
|
}
|
|
}
|
|
|
|
// Sort paths for consistent ordering
|
|
sort.Strings(paths)
|
|
|
|
return paths
|
|
}
|
|
|
|
// getProjectRoot finds the project root directory by looking for go.mod
|
|
func getProjectRoot() (string, error) {
|
|
// Start from current directory and walk up the tree
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Walk up the directory tree until we find go.mod or reach root
|
|
for {
|
|
// Check if go.mod exists in current directory
|
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
return dir, nil
|
|
}
|
|
|
|
// Move up one directory
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
// Reached root directory
|
|
break
|
|
}
|
|
dir = parent
|
|
}
|
|
|
|
// If we get here, we didn't find go.mod - return original working directory
|
|
return "", fmt.Errorf("could not find project root (go.mod not found)")
|
|
}
|
|
|
|
// CreateTestSuite creates a configured godog test suite
|
|
func CreateTestSuite(t *testing.T, config *FeatureConfig, suiteName string) godog.TestSuite {
|
|
// Set FEATURE environment variable for feature-specific configuration
|
|
os.Setenv("FEATURE", config.FeatureName)
|
|
|
|
// Allow tag override via environment variable
|
|
tags := os.Getenv("GODOG_TAGS")
|
|
if tags == "" {
|
|
// Default tags if not overridden
|
|
tags = "~@flaky && ~@todo && ~@skip"
|
|
}
|
|
|
|
// Allow stop on failure override via environment variable
|
|
stopOnFailure := config.StopOnFailure
|
|
if envStop := os.Getenv("GODOG_STOP_ON_FAILURE"); envStop != "" {
|
|
// Support various boolean formats
|
|
stopOnFailure, _ = strconv.ParseBool(envStop)
|
|
}
|
|
|
|
return godog.TestSuite{
|
|
Name: suiteName,
|
|
TestSuiteInitializer: bdd.InitializeTestSuite,
|
|
ScenarioInitializer: bdd.InitializeScenario,
|
|
Options: &godog.Options{
|
|
Format: config.Format,
|
|
Paths: []string{"."},
|
|
TestingT: t,
|
|
Strict: true,
|
|
Randomize: -1,
|
|
StopOnFailure: stopOnFailure,
|
|
Tags: tags,
|
|
},
|
|
}
|
|
}
|
|
|
|
// CreateMultiFeatureTestSuite creates a configured godog test suite for multiple features
|
|
func CreateMultiFeatureTestSuite(t *testing.T, config *MultiFeatureConfig, suiteName string) godog.TestSuite {
|
|
// Set FEATURE environment variable for feature-specific configuration
|
|
// For multi-feature tests, we don't set a specific feature
|
|
os.Setenv("FEATURE", "")
|
|
|
|
// Allow tag override via environment variable
|
|
tags := os.Getenv("GODOG_TAGS")
|
|
if tags == "" {
|
|
// Default tags if not overridden
|
|
tags = "~@flaky && ~@todo && ~@skip"
|
|
}
|
|
|
|
// Allow stop on failure override via environment variable
|
|
stopOnFailure := config.StopOnFailure
|
|
if envStop := os.Getenv("GODOG_STOP_ON_FAILURE"); envStop != "" {
|
|
// Support various boolean formats
|
|
stopOnFailure, _ = strconv.ParseBool(envStop)
|
|
}
|
|
|
|
return godog.TestSuite{
|
|
Name: suiteName,
|
|
TestSuiteInitializer: bdd.InitializeTestSuite,
|
|
ScenarioInitializer: bdd.InitializeScenario,
|
|
Options: &godog.Options{
|
|
Format: config.Format,
|
|
Paths: config.Paths,
|
|
TestingT: t,
|
|
Strict: true,
|
|
Randomize: -1,
|
|
StopOnFailure: stopOnFailure,
|
|
Tags: tags,
|
|
},
|
|
}
|
|
}
|