From aa3055db8fdfbde289056d59893be8bc97515824 Mon Sep 17 00:00:00 2001 From: tianzhou Date: Fri, 31 Oct 2025 04:34:28 -0700 Subject: [PATCH] chore: suppress test output --- cmd/apply/apply.go | 39 ++++--- cmd/apply/apply_integration_test.go | 7 ++ cmd/dump/dump_permission_integration_test.go | 2 - cmd/include_integration_test.go | 27 ++--- cmd/migrate_integration_test.go | 13 +-- cmd/schema_integration_test.go | 103 +------------------ 6 files changed, 53 insertions(+), 138 deletions(-) diff --git a/cmd/apply/apply.go b/cmd/apply/apply.go index 1658d40f..f7ef4430 100644 --- a/cmd/apply/apply.go +++ b/cmd/apply/apply.go @@ -93,6 +93,7 @@ type ApplyConfig struct { Plan *plan.Plan // Pre-generated plan (optional, alternative to File) AutoApprove bool NoColor bool + Quiet bool // Suppress plan display and progress messages (useful for tests) LockTimeout string ApplicationName string } @@ -157,8 +158,10 @@ func ApplyMigration(config *ApplyConfig, provider postgres.DesiredStateProvider) return nil } - // Display the plan - fmt.Print(migrationPlan.HumanColored(!config.NoColor)) + // Display the plan (unless quiet mode is enabled) + if !config.Quiet { + fmt.Print(migrationPlan.HumanColored(!config.NoColor)) + } // Prompt for approval if not auto-approved if !config.AutoApprove { @@ -177,7 +180,9 @@ func ApplyMigration(config *ApplyConfig, provider postgres.DesiredStateProvider) } // Apply the changes - fmt.Println("\nApplying changes...") + if !config.Quiet { + fmt.Println("\nApplying changes...") + } // Build database connection for applying changes connConfig := &util.ConnectionConfig{ @@ -227,15 +232,19 @@ func ApplyMigration(config *ApplyConfig, provider postgres.DesiredStateProvider) // Execute by groups with wait directive support for i, group := range migrationPlan.Groups { - fmt.Printf("\nExecuting group %d/%d...\n", i+1, len(migrationPlan.Groups)) + if !config.Quiet { + fmt.Printf("\nExecuting group %d/%d...\n", i+1, len(migrationPlan.Groups)) + } - err = executeGroup(ctx, conn, group, i+1) + err = executeGroup(ctx, conn, group, i+1, config.Quiet) if err != nil { return err } } - fmt.Println("Changes applied successfully!") + if !config.Quiet { + fmt.Println("Changes applied successfully!") + } return nil } @@ -368,7 +377,7 @@ func validateSchemaFingerprint(migrationPlan *plan.Plan, host string, port int, } // executeGroup executes all steps in a group, handling directives separately from SQL statements -func executeGroup(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int) error { +func executeGroup(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int, quiet bool) error { // Check if this group has directives hasDirectives := false @@ -381,15 +390,15 @@ func executeGroup(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, if !hasDirectives { // No directives - concatenate all SQL and execute in implicit transaction - return executeGroupConcatenated(ctx, conn, group, groupNum) + return executeGroupConcatenated(ctx, conn, group, groupNum, quiet) } else { // Has directives - execute statements individually - return executeGroupIndividually(ctx, conn, group, groupNum) + return executeGroupIndividually(ctx, conn, group, groupNum, quiet) } } // executeGroupConcatenated concatenates all SQL statements and executes them in an implicit transaction -func executeGroupConcatenated(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int) error { +func executeGroupConcatenated(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int, quiet bool) error { var sqlStatements []string // Collect all SQL statements @@ -400,7 +409,9 @@ func executeGroupConcatenated(ctx context.Context, conn *sql.DB, group plan.Exec // Concatenate all SQL statements concatenatedSQL := strings.Join(sqlStatements, ";\n") + ";" - fmt.Printf(" Executing %d statements in implicit transaction\n", len(sqlStatements)) + if !quiet { + fmt.Printf(" Executing %d statements in implicit transaction\n", len(sqlStatements)) + } // Execute all statements in a single call (implicit transaction) _, err := conn.ExecContext(ctx, concatenatedSQL) @@ -412,7 +423,7 @@ func executeGroupConcatenated(ctx context.Context, conn *sql.DB, group plan.Exec } // executeGroupIndividually executes statements individually without transactions -func executeGroupIndividually(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int) error { +func executeGroupIndividually(ctx context.Context, conn *sql.DB, group plan.ExecutionGroup, groupNum int, quiet bool) error { for stepIdx, step := range group.Steps { if step.Directive != nil { // Handle directive execution @@ -422,7 +433,9 @@ func executeGroupIndividually(ctx context.Context, conn *sql.DB, group plan.Exec } } else { // Execute regular SQL statement - fmt.Printf(" Executing: %s\n", truncateSQL(step.SQL, 80)) + if !quiet { + fmt.Printf(" Executing: %s\n", truncateSQL(step.SQL, 80)) + } _, err := conn.ExecContext(ctx, step.SQL) if err != nil { diff --git a/cmd/apply/apply_integration_test.go b/cmd/apply/apply_integration_test.go index d6b6ef3b..77e03861 100644 --- a/cmd/apply/apply_integration_test.go +++ b/cmd/apply/apply_integration_test.go @@ -225,6 +225,7 @@ func TestApplyCommand_TransactionRollback(t *testing.T) { Plan: migrationPlan, // Use pre-generated plan with injected failure AutoApprove: true, NoColor: false, + Quiet: true, // Suppress output in tests LockTimeout: "", ApplicationName: "pgschema", } @@ -460,6 +461,7 @@ func TestApplyCommand_CreateIndexConcurrently(t *testing.T) { Plan: migrationPlan, // Use pre-generated plan AutoApprove: true, NoColor: false, + Quiet: true, // Suppress output in tests LockTimeout: "", ApplicationName: "pgschema", } @@ -650,6 +652,7 @@ func TestApplyCommand_WithPlanFile(t *testing.T) { Plan: migrationPlan, // Use pre-generated plan AutoApprove: true, NoColor: false, + Quiet: true, // Suppress output in tests LockTimeout: "", ApplicationName: "pgschema", } @@ -880,6 +883,7 @@ func TestApplyCommand_FingerprintMismatch(t *testing.T) { Plan: migrationPlan, // Use pre-generated plan with old fingerprint AutoApprove: true, NoColor: false, + Quiet: true, // Suppress output in tests LockTimeout: "", ApplicationName: "pgschema", } @@ -1048,6 +1052,7 @@ func TestApplyCommand_WaitDirective(t *testing.T) { Plan: migrationPlan, // Use pre-generated plan AutoApprove: true, NoColor: false, + Quiet: true, // Suppress output in tests LockTimeout: "", ApplicationName: "pgschema", } @@ -1176,6 +1181,7 @@ CREATE TABLE employees ( File: schemaFile, AutoApprove: true, // Auto-approve for testing NoColor: true, + Quiet: true, // Suppress output in tests ApplicationName: "pgschema-test", } @@ -1296,6 +1302,7 @@ CREATE TABLE users ( Schema: "public", AutoApprove: true, NoColor: true, + Quiet: true, // Suppress output in tests ApplicationName: "pgschema-test", } diff --git a/cmd/dump/dump_permission_integration_test.go b/cmd/dump/dump_permission_integration_test.go index 73acddc8..11564b8f 100644 --- a/cmd/dump/dump_permission_integration_test.go +++ b/cmd/dump/dump_permission_integration_test.go @@ -394,7 +394,6 @@ func testProcedureAndFunctionSourceAccess(t *testing.T, ctx context.Context, con if !strings.Contains(procedureDef, "Procedure source visibility test") { t.Errorf("Expected procedure body content, got: %s", procedureDef) } - t.Logf("Success: pg_get_functiondef returned procedure: %s", procedureDef) } // Test 4: Check that pg_get_functiondef() works for functions despite NULL routine_definition @@ -417,7 +416,6 @@ func testProcedureAndFunctionSourceAccess(t *testing.T, ctx context.Context, con if !strings.Contains(functionDef, "Function source visibility test") { t.Errorf("Expected function body content, got: %s", functionDef) } - t.Logf("Success: pg_get_functiondef returned function: %s", functionDef) } // Test 5: Try to dump schema as regular_user (should succeed with pg_get_functiondef) diff --git a/cmd/include_integration_test.go b/cmd/include_integration_test.go index 81122f79..e1f74059 100644 --- a/cmd/include_integration_test.go +++ b/cmd/include_integration_test.go @@ -8,6 +8,7 @@ package cmd // the same organized file structure. import ( + "bytes" "database/sql" "fmt" "os" @@ -82,6 +83,11 @@ func applyIncludeSchema(t *testing.T, containerInfo *struct { // Add the apply command as a subcommand rootCmd.AddCommand(apply.ApplyCmd) + // Capture stdout and stderr to suppress verbose output + var stdout, stderr bytes.Buffer + rootCmd.SetOut(&stdout) + rootCmd.SetErr(&stderr) + // Set command arguments for apply args := []string{ "apply", @@ -98,10 +104,8 @@ func applyIncludeSchema(t *testing.T, containerInfo *struct { // Execute the root command with apply subcommand err := rootCmd.Execute() if err != nil { - t.Fatalf("Failed to apply include schema: %v", err) + t.Fatalf("Failed to apply include schema: %v\nStdout: %s\nStderr: %s", err, stdout.String(), stderr.String()) } - - t.Logf("✓ Successfully applied include-based schema using apply command") } // executeMultiFileDump runs pgschema dump --multi-file using the CLI command @@ -121,6 +125,11 @@ func executeMultiFileDump(t *testing.T, containerInfo *struct { // Add the dump command as a subcommand rootCmd.AddCommand(dump.DumpCmd) + // Capture stdout and stderr to suppress verbose output + var stdout, stderr bytes.Buffer + rootCmd.SetOut(&stdout) + rootCmd.SetErr(&stderr) + // Set command arguments for dump args := []string{ "dump", @@ -138,10 +147,8 @@ func executeMultiFileDump(t *testing.T, containerInfo *struct { // Execute the root command with dump subcommand err := rootCmd.Execute() if err != nil { - t.Fatalf("Failed to execute multi-file dump using pgschema dump: %v", err) + t.Fatalf("Failed to execute multi-file dump: %v\nStdout: %s\nStderr: %s", err, stdout.String(), stderr.String()) } - - t.Logf("✓ Successfully executed multi-file dump using pgschema dump to %s", filepath.Dir(outputPath)) } // compareIncludeFiles compares dumped files with original include files using direct comparison @@ -150,8 +157,6 @@ func compareIncludeFiles(t *testing.T, dumpDir string) { // Compare the entire directory structure and contents compareDirectoryLayout(t, sourceDir, dumpDir) - - t.Logf("✓ Include file comparison completed") } // compareDirectoryLayout compares the complete directory layout between source and dump @@ -193,8 +198,6 @@ func compareDirectoryLayout(t *testing.T, sourceDir, dumpDir string) { continue } - t.Logf("✓ Directory exists: %s", dirName) - // Compare the contents of this directory sourceDirPath := filepath.Join(sourceDir, dirName) dumpDirPath := filepath.Join(dumpDir, dirName) @@ -280,9 +283,7 @@ func compareFileContents(t *testing.T, sourceFilePath, dumpFilePath, displayName return } - if string(sourceContent) == string(dumpContent) { - t.Logf("✓ Content match for %s", displayName) - } else { + if string(sourceContent) != string(dumpContent) { t.Errorf("Content mismatch for %s", displayName) t.Logf("\n\nExpected:\n%s\n\n", string(sourceContent)) t.Logf("\n\nActual:\n%s\n\n", string(dumpContent)) diff --git a/cmd/migrate_integration_test.go b/cmd/migrate_integration_test.go index ce8deaa8..60240397 100644 --- a/cmd/migrate_integration_test.go +++ b/cmd/migrate_integration_test.go @@ -214,15 +214,12 @@ func runPlanAndApplyTest(t *testing.T, ctx context.Context, container *struct { dbName = dbName[:63] } - t.Logf("=== PLAN AND APPLY TEST: %s → %s (DB: %s) ===", filepath.Base(tc.oldFile), filepath.Base(tc.newFile), dbName) - // Create test-specific database if err := createDatabase(ctx, containerHost, portMapped, dbName); err != nil { t.Fatalf("Failed to create test database %s: %v", dbName, err) } // STEP 1: Apply old.sql to initialize database state - t.Logf("--- Applying old.sql to initialize database state ---") oldContent, err := os.ReadFile(tc.oldFile) if err != nil { t.Fatalf("Failed to read %s: %v", tc.oldFile, err) @@ -233,24 +230,19 @@ func runPlanAndApplyTest(t *testing.T, ctx context.Context, container *struct { if err := executeSQL(ctx, containerHost, portMapped, dbName, string(oldContent)); err != nil { t.Fatalf("Failed to execute old.sql: %v", err) } - t.Logf("Applied old.sql to initialize database state") } // STEP 2: Test plan command with new.sql as target - t.Logf("--- Testing plan command outputs ---") testPlanOutputs(t, container, dbName, tc.newFile, tc.planSQLFile, tc.planJSONFile, tc.planTXTFile) if !*generate { // STEP 3: Apply the migration using apply command - t.Logf("--- Applying migration using apply command ---") err = applySchemaChanges(containerHost, portMapped, dbName, container.User, container.Password, "public", tc.newFile) if err != nil { t.Fatalf("Failed to apply schema changes using pgschema apply: %v", err) } - t.Logf("Applied migration successfully") // STEP 4: Test idempotency - plan should produce no changes - t.Logf("--- Testing idempotency ---") secondPlanOutput, err := generatePlanSQLFormatted(containerHost, portMapped, dbName, container.User, container.Password, "public", tc.newFile) if err != nil { t.Fatalf("Failed to generate plan SQL for idempotency check: %v", err) @@ -258,12 +250,8 @@ func runPlanAndApplyTest(t *testing.T, ctx context.Context, container *struct { if secondPlanOutput != "" { t.Errorf("Expected no changes when applying schema twice, but got SQL output:\n%s", secondPlanOutput) - } else { - t.Logf("Idempotency verified: no changes detected on second apply") } } - - t.Logf("=== PLAN AND APPLY TEST COMPLETED ===") } // testPlanOutputs tests all plan output formats against expected files @@ -413,6 +401,7 @@ func applySchemaChanges(host string, port int, database, user, password, schema, File: schemaFile, AutoApprove: true, NoColor: true, + Quiet: true, // Suppress plan display and progress messages in tests LockTimeout: "", ApplicationName: "pgschema", } diff --git a/cmd/schema_integration_test.go b/cmd/schema_integration_test.go index 58f8889d..ece2c140 100644 --- a/cmd/schema_integration_test.go +++ b/cmd/schema_integration_test.go @@ -1,18 +1,13 @@ package cmd import ( - "bytes" "context" - "fmt" "os" "path/filepath" "strings" "testing" - "github.com/pgschema/pgschema/cmd/apply" - planCmd "github.com/pgschema/pgschema/cmd/plan" "github.com/pgschema/pgschema/testutil" - "github.com/spf13/cobra" ) // TestNonPublicSchemaOperations verifies that pgschema works correctly with non-public schemas. @@ -60,7 +55,7 @@ func TestNonPublicSchemaOperations(t *testing.T) { } // Step 1: Generate plan using CLI - planOutput, err := executePlanCommand( + planOutput, err := generatePlanSQLFormatted( host, port, dbname, @@ -81,7 +76,7 @@ func TestNonPublicSchemaOperations(t *testing.T) { } // Step 2: Apply changes using CLI - err = executeApplyCommand( + err = applySchemaChanges( host, port, dbname, @@ -168,7 +163,7 @@ func TestNonPublicSchemaOperations(t *testing.T) { } // Apply changes ONLY to app_a schema - err = executeApplyCommand( + err = applySchemaChanges( host, port, dbname, @@ -249,7 +244,7 @@ func TestNonPublicSchemaOperations(t *testing.T) { } // Step 1: Generate plan using CLI for mixed-case schema - planOutput, err := executePlanCommand( + planOutput, err := generatePlanSQLFormatted( host, port, dbname, @@ -270,7 +265,7 @@ func TestNonPublicSchemaOperations(t *testing.T) { } // Step 2: Apply changes using CLI for mixed-case schema - err = executeApplyCommand( + err = applySchemaChanges( host, port, dbname, @@ -439,91 +434,3 @@ func TestNonPublicSchemaOperations(t *testing.T) { // }) } -// executePlanCommand executes the pgschema plan command using the CLI interface -func executePlanCommand(host string, port int, database, user, password, schema, schemaFile string) (string, error) { - // Reset plan flags for clean state - planCmd.ResetFlags() - - // Create root command with plan as subcommand - rootCmd := &cobra.Command{ - Use: "pgschema", - } - rootCmd.AddCommand(planCmd.PlanCmd) - - // Capture stdout - var buf bytes.Buffer - oldStdout := os.Stdout - r, w, err := os.Pipe() - if err != nil { - return "", err - } - os.Stdout = w - - // Set command arguments - args := []string{ - "plan", - "--host", host, - "--port", fmt.Sprintf("%d", port), - "--db", database, - "--user", user, - "--password", password, - "--schema", schema, - "--file", schemaFile, - "--output-sql", "stdout", - } - rootCmd.SetArgs(args) - - // Execute command in goroutine - done := make(chan error, 1) - go func() { - done <- rootCmd.Execute() - }() - - // Copy output - copyDone := make(chan struct{}) - go func() { - defer close(copyDone) - defer r.Close() - buf.ReadFrom(r) - }() - - // Wait for command - cmdErr := <-done - w.Close() - <-copyDone - - // Restore stdout - os.Stdout = oldStdout - - if cmdErr != nil { - return buf.String(), fmt.Errorf("plan command failed: %w (output: %s)", cmdErr, buf.String()) - } - - return buf.String(), nil -} - -// executeApplyCommand executes the pgschema apply command using the CLI interface -func executeApplyCommand(host string, port int, database, user, password, schema, schemaFile string) error { - // Create root command with apply as subcommand - rootCmd := &cobra.Command{ - Use: "pgschema", - } - rootCmd.AddCommand(apply.ApplyCmd) - - // Set command arguments - args := []string{ - "apply", - "--host", host, - "--port", fmt.Sprintf("%d", port), - "--db", database, - "--user", user, - "--password", password, - "--schema", schema, - "--file", schemaFile, - "--auto-approve", // Auto-approve for testing - } - rootCmd.SetArgs(args) - - // Execute the command - return rootCmd.Execute() -} \ No newline at end of file