🎯 refactor: implement comprehensive BDD test suite with modular architecture
✨ feat: add feature-based test organization per ADR 0024 🐛 fix: resolve compilation errors in suite_feature.go 📝 docs: add comprehensive BDD framework documentation ♻️ refactor: split monolithic tests into modular features 🧪 test: implement synchronization helpers and context management ⚡ perf: add parallel test execution capability 🔧 chore: add feature-specific test scripts and validation 📚 docs: move BDD_TAGS.md to features/ for better organization Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
64
scripts/test-by-tag.sh
Executable file
64
scripts/test-by-tag.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tag-Based Test Runner Script
|
||||
# Runs BDD tests with specific tags
|
||||
|
||||
set -e
|
||||
|
||||
# Check if tag is provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "❌ Usage: $0 <tag> [feature]"
|
||||
echo "Examples:"
|
||||
echo " $0 @smoke # Run all smoke tests"
|
||||
echo " $0 @critical auth # Run critical auth tests"
|
||||
echo " $0 @v2 greet # Run v2 greet tests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TAG=$1
|
||||
FEATURE=""
|
||||
|
||||
# Check if feature is also provided
|
||||
if [ $# -ge 2 ]; then
|
||||
FEATURE=$2
|
||||
fi
|
||||
|
||||
SCRIPTS_DIR=$(dirname `realpath ${BASH_SOURCE[0]}`)
|
||||
cd $SCRIPTS_DIR/..
|
||||
|
||||
echo "🧪 Running tests with tag: $TAG"
|
||||
|
||||
if [ -n "$FEATURE" ]; then
|
||||
echo "📁 Feature: $FEATURE"
|
||||
|
||||
# Set feature-specific environment variables
|
||||
DATABASE="dance_lessons_coach_${FEATURE}_test"
|
||||
CONFIG="features/${FEATURE}/${FEATURE}-test-config.yaml"
|
||||
|
||||
export DLC_DATABASE_HOST="localhost"
|
||||
export DLC_DATABASE_PORT="5432"
|
||||
export DLC_DATABASE_USER="postgres"
|
||||
export DLC_DATABASE_PASSWORD="postgres"
|
||||
export DLC_DATABASE_NAME="${DATABASE}"
|
||||
export DLC_DATABASE_SSL_MODE="disable"
|
||||
export DLC_CONFIG_FILE="${CONFIG}"
|
||||
|
||||
# Run feature-specific tests with tag filtering
|
||||
echo "🚀 Running tagged tests for ${FEATURE} feature..."
|
||||
cd "features/${FEATURE}"
|
||||
FEATURE=${FEATURE} go test -v -tags="$TAG" .
|
||||
else
|
||||
echo "🚀 Running tagged tests for all features..."
|
||||
|
||||
# Run all tests with tag filtering
|
||||
# Note: Godog tag filtering is done through the godog command line
|
||||
# For Go test integration, we need to use a different approach
|
||||
echo "⚠️ Tag filtering for all features requires godog command directly"
|
||||
echo "📝 Running: godog --tags=$TAG features/"
|
||||
|
||||
# This would require setting up the test server manually
|
||||
# For now, we'll show how it would work
|
||||
echo "⏳ This functionality would require additional implementation"
|
||||
echo "💡 Consider using: godog --tags=$TAG features/"
|
||||
echo " after starting the test server manually"
|
||||
fi
|
||||
168
scripts/test-feature.sh
Executable file
168
scripts/test-feature.sh
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Feature-Specific Test Runner Script
|
||||
# Runs BDD tests for a specific feature with proper isolation
|
||||
|
||||
set -e
|
||||
|
||||
# Check if feature name is provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "❌ Usage: $0 <feature-name>"
|
||||
echo "Available features: auth, config, greet, health, jwt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FEATURE=$1
|
||||
SCRIPTS_DIR=$(dirname `realpath ${BASH_SOURCE[0]}`)
|
||||
cd $SCRIPTS_DIR/..
|
||||
|
||||
# Validate feature name
|
||||
case $FEATURE in
|
||||
auth|config|greet|health|jwt)
|
||||
echo "🧪 Setting up ${FEATURE} feature tests..."
|
||||
;;
|
||||
*)
|
||||
echo "❌ Invalid feature: $FEATURE"
|
||||
echo "Available features: auth, config, greet, health, jwt"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Feature-specific configuration
|
||||
DATABASE="dance_lessons_coach_${FEATURE}_test"
|
||||
CONFIG="features/${FEATURE}/${FEATURE}-test-config.yaml"
|
||||
PORT=$(grep "port:" "$CONFIG" | awk '{print $2}')
|
||||
|
||||
# Setup function
|
||||
setup_feature_environment() {
|
||||
echo "🧪 Setting up ${FEATURE} feature tests..."
|
||||
|
||||
# Check if we're in CI environment
|
||||
if [ -n "$GITHUB_ACTIONS" ] || [ -n "$GITEA_ACTIONS" ]; then
|
||||
# CI environment - PostgreSQL is already running as a service
|
||||
echo "🏗️ CI environment detected"
|
||||
|
||||
# Create database if it doesn't exist
|
||||
if ! psql -h postgres -p 5432 -U postgres -lqt | cut -d \| -f 1 | grep -qw "${DATABASE}"; then
|
||||
echo "📦 Creating ${FEATURE} test database..."
|
||||
createdb -h postgres -p 5432 -U postgres "${DATABASE}"
|
||||
echo "✅ ${FEATURE} test database created successfully!"
|
||||
else
|
||||
echo "✅ ${FEATURE} test database already exists"
|
||||
fi
|
||||
else
|
||||
# Local environment - use docker compose
|
||||
echo "💻 Local environment detected"
|
||||
|
||||
# Check if PostgreSQL container is running, start it if not
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "^dance-lessons-coach-postgres$"; then
|
||||
echo "🐋 Starting PostgreSQL container..."
|
||||
docker compose up -d postgres
|
||||
|
||||
# Wait for PostgreSQL to be ready
|
||||
echo "⏳ Waiting for PostgreSQL to be ready..."
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
while [ $attempt -lt $max_attempts ]; do
|
||||
if docker exec dance-lessons-coach-postgres pg_isready -U postgres 2>/dev/null; then
|
||||
echo "✅ PostgreSQL is ready!"
|
||||
break
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo "❌ PostgreSQL failed to start"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "✅ PostgreSQL container is already running"
|
||||
fi
|
||||
|
||||
# Create feature-specific database
|
||||
if docker exec dance-lessons-coach-postgres psql -U postgres -lqt | cut -d \| -f 1 | grep -qw "${DATABASE}"; then
|
||||
echo "✅ ${FEATURE} test database already exists"
|
||||
else
|
||||
echo "📦 Creating ${FEATURE} test database..."
|
||||
if docker exec dance-lessons-coach-postgres createdb -U postgres "${DATABASE}"; then
|
||||
echo "✅ ${FEATURE} test database created successfully!"
|
||||
else
|
||||
echo "❌ Failed to create ${FEATURE} test database"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Run tests function
|
||||
run_feature_tests() {
|
||||
echo "🚀 Running ${FEATURE} feature tests..."
|
||||
|
||||
# Set feature-specific environment variables
|
||||
export DLC_DATABASE_HOST="localhost"
|
||||
export DLC_DATABASE_PORT="5432"
|
||||
export DLC_DATABASE_USER="postgres"
|
||||
export DLC_DATABASE_PASSWORD="postgres"
|
||||
export DLC_DATABASE_NAME="${DATABASE}"
|
||||
export DLC_DATABASE_SSL_MODE="disable"
|
||||
export DLC_CONFIG_FILE="${CONFIG}"
|
||||
|
||||
# Run tests with proper coverage measurement
|
||||
set +e
|
||||
test_output=$(go test ./features/${FEATURE}/... -v -cover -coverpkg=./... -coverprofile=coverage-${FEATURE}.out 2>&1)
|
||||
test_exit_code=$?
|
||||
set -e
|
||||
|
||||
echo "$test_output"
|
||||
|
||||
# Check for undefined steps
|
||||
if echo "$test_output" | grep -q "undefined"; then
|
||||
echo "❌ FAILED: Found undefined steps in ${FEATURE} tests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for pending steps
|
||||
if echo "$test_output" | grep -q "pending"; then
|
||||
echo "❌ FAILED: Found pending steps in ${FEATURE} tests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for skipped steps
|
||||
if echo "$test_output" | grep -q "skipped"; then
|
||||
echo "❌ FAILED: Found skipped steps in ${FEATURE} tests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if tests passed
|
||||
if [ $test_exit_code -eq 0 ]; then
|
||||
echo "✅ All ${FEATURE} feature tests passed successfully!"
|
||||
return 0
|
||||
else
|
||||
echo "❌ ${FEATURE} feature tests failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup_feature_environment() {
|
||||
echo "🧹 Cleaning up ${FEATURE} feature tests..."
|
||||
|
||||
# Check if we're in CI environment
|
||||
if [ -n "$GITHUB_ACTIONS" ] || [ -n "$GITEA_ACTIONS" ]; then
|
||||
# CI environment - drop database
|
||||
echo "🗑️ Dropping ${FEATURE} test database..."
|
||||
dropdb -h postgres -p 5432 -U postgres "${DATABASE}" 2>/dev/null || true
|
||||
echo "✅ ${FEATURE} test database cleaned up"
|
||||
else
|
||||
# Local environment - drop database
|
||||
echo "🗑️ Dropping ${FEATURE} test database..."
|
||||
docker exec dance-lessons-coach-postgres dropdb -U postgres "${DATABASE}" 2>/dev/null || true
|
||||
echo "✅ ${FEATURE} test database cleaned up"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
setup_feature_environment
|
||||
run_feature_tests
|
||||
cleanup_feature_environment
|
||||
110
scripts/validate-isolation.sh
Executable file
110
scripts/validate-isolation.sh
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Isolation Validation Script
|
||||
# Validates that feature isolation is working correctly
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Validating BDD test isolation..."
|
||||
|
||||
# Check feature directories exist
|
||||
echo "📁 Checking feature directory structure..."
|
||||
for feature in auth config greet health jwt; do
|
||||
if [ ! -d "features/${feature}" ]; then
|
||||
echo "❌ Missing features/${feature} directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for feature files
|
||||
if [ -z "$(find features/${feature} -name "*.feature" -type f)" ]; then
|
||||
echo "❌ No feature files found in features/${feature}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for config files
|
||||
if [ ! -f "features/${feature}/${feature}-test-config.yaml" ]; then
|
||||
echo "❌ Missing config file for ${feature} feature"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ ${feature} feature structure validated"
|
||||
done
|
||||
|
||||
# Check for unique ports
|
||||
echo "🔌 Checking for unique port assignments..."
|
||||
port_auth=$(grep "port:" "features/auth/auth-test-config.yaml" | awk '{print $2}')
|
||||
port_config=$(grep "port:" "features/config/config-test-config.yaml" | awk '{print $2}')
|
||||
port_greet=$(grep "port:" "features/greet/greet-test-config.yaml" | awk '{print $2}')
|
||||
port_health=$(grep "port:" "features/health/health-test-config.yaml" | awk '{print $2}')
|
||||
port_jwt=$(grep "port:" "features/jwt/jwt-test-config.yaml" | awk '{print $2}')
|
||||
|
||||
# Check for port conflicts
|
||||
if [ "$port_auth" = "$port_config" ] || [ "$port_auth" = "$port_greet" ] || [ "$port_auth" = "$port_health" ] || [ "$port_auth" = "$port_jwt" ]; then
|
||||
echo "❌ Port conflict detected with auth port $port_auth"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$port_config" = "$port_greet" ] || [ "$port_config" = "$port_health" ] || [ "$port_config" = "$port_jwt" ]; then
|
||||
echo "❌ Port conflict detected with config port $port_config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$port_greet" = "$port_health" ] || [ "$port_greet" = "$port_jwt" ]; then
|
||||
echo "❌ Port conflict detected with greet port $port_greet"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$port_health" = "$port_jwt" ]; then
|
||||
echo "❌ Port conflict detected with health port $port_health"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All features have unique ports"
|
||||
|
||||
# Check for unique database names
|
||||
echo "🗃️ Checking for unique database names..."
|
||||
db_auth="dance_lessons_coach_auth_test"
|
||||
db_config="dance_lessons_coach_config_test"
|
||||
db_greet="dance_lessons_coach_greet_test"
|
||||
db_health="dance_lessons_coach_health_test"
|
||||
db_jwt="dance_lessons_coach_jwt_test"
|
||||
|
||||
# Check for database name conflicts
|
||||
if [ "$db_auth" = "$db_config" ] || [ "$db_auth" = "$db_greet" ] || [ "$db_auth" = "$db_health" ] || [ "$db_auth" = "$db_jwt" ]; then
|
||||
echo "❌ Database conflict detected with auth database"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$db_config" = "$db_greet" ] || [ "$db_config" = "$db_health" ] || [ "$db_config" = "$db_jwt" ]; then
|
||||
echo "❌ Database conflict detected with config database"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$db_greet" = "$db_health" ] || [ "$db_greet" = "$db_jwt" ]; then
|
||||
echo "❌ Database conflict detected with greet database"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$db_health" = "$db_jwt" ]; then
|
||||
echo "❌ Database conflict detected with health database"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All features have unique database names"
|
||||
|
||||
# Test that each feature can be run independently
|
||||
echo "🧪 Testing feature independence..."
|
||||
for feature in auth config greet health jwt; do
|
||||
echo "Testing ${feature} feature..."
|
||||
|
||||
# Try to run the feature test script with setup only
|
||||
if ! bash scripts/test-feature.sh $feature 2>&1 | grep -q "Setting up ${feature} feature tests"; then
|
||||
echo "❌ Failed to setup ${feature} feature tests"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ ${feature} feature can be set up independently"
|
||||
done
|
||||
|
||||
echo "✅ All isolation validations passed!"
|
||||
echo "🎉 BDD test isolation is working correctly"
|
||||
Reference in New Issue
Block a user