package ingestiontestgate import ( "context" "os" "path/filepath" "testing" ) func moduleRoot(t *testing.T) string { t.Helper() wd, err := os.Getwd() if err != nil { t.Fatalf("arbeitsverzeichnis ermitteln: %v", err) } // gate_test.go liegt in internal/ingestiontestgate — Modulwurzel ist // zwei Ebenen darüber. return filepath.Join(wd, "..", "..") } // TestScanForKnownErrorPointTests_RealPackagesAllCovered ist die // geforderte Pflichtprüfung 2: Stichprobe, mindestens ein // Regressionstest je bekanntem Fehlerpunkt — automatisiert und // reproduzierbar gegen den echten Quelltext ausgeführt. func TestScanForKnownErrorPointTests_RealPackagesAllCovered(t *testing.T) { root := moduleRoot(t) result, err := ScanForKnownErrorPointTests(root) if err != nil { t.Fatalf("scan: %v", err) } if !result.Passed { for _, r := range result.Results { if !r.Covered { t.Errorf("bekannter fehlerpunkt %q (%s) hat KEINEN passenden regressionstest in %s gefunden", r.Point.Name, r.Point.Rationale, r.Point.PackageRelDir) } } t.FailNow() } for _, r := range result.Results { t.Logf("%s: %s (%s/%s)", r.Point.Name, r.TestName, r.Point.PackageRelDir, r.FoundInFile) } } // TestScanForKnownErrorPointTests_DetectsMissingCoverage beweist, dass // der Scanner einen tatsächlich fehlenden Regressionstest auch real // erkennt (Negativtest) — ein Gate, das nie eine Lücke melden kann, // wäre wertlos. func TestScanForKnownErrorPointTests_DetectsMissingCoverage(t *testing.T) { dir := t.TempDir() // Nur EIN Paketverzeichnis anlegen (für "Header-Injection"), die // beiden anderen bekannten Fehlerpunkte bleiben absichtlich ohne // Verzeichnis/Tests. mailerDir := filepath.Join(dir, "internal", "mailer") if err := os.MkdirAll(mailerDir, 0o750); err != nil { t.Fatalf("verzeichnis anlegen: %v", err) } content := []byte("package mailer\n\nimport \"testing\"\n\nfunc TestRejectsCRLFInHeader(t *testing.T) {}\n") if err := os.WriteFile(filepath.Join(mailerDir, "mailer_test.go"), content, 0o600); err != nil { t.Fatalf("testdatei schreiben: %v", err) } // Leere Verzeichnisse für die anderen beiden Punkte, damit ReadDir // nicht mit einem Fehler abbricht. if err := os.MkdirAll(filepath.Join(dir, "internal", "mimeparse"), 0o750); err != nil { t.Fatalf("verzeichnis anlegen: %v", err) } if err := os.MkdirAll(filepath.Join(dir, "internal", "folderstate"), 0o750); err != nil { t.Fatalf("verzeichnis anlegen: %v", err) } result, err := ScanForKnownErrorPointTests(dir) if err != nil { t.Fatalf("scan: %v", err) } if result.Passed { t.Fatal("erwartete erkannte lücke (2 von 3 fehlerpunkten unabgedeckt), scan meldet bestanden") } covered := 0 for _, r := range result.Results { if r.Covered { covered++ } } if covered != 1 { t.Fatalf("erwartete genau 1 abgedeckten fehlerpunkt, habe %d", covered) } } // TestRun_RealGateAgainstCurrentIngestionImportState ist die geforderte // Pflichtprüfung 1: Gate-Lauf gegen aktuellen Stand von ING-10/IMP-09 // dokumentiert — führt das vollständige Gate real gegen den aktuellen // Modul-Quelltext aus (inklusive echter Postgres-Integrationstests) und // dokumentiert das Ergebnis mit Zeitstempel. func TestRun_RealGateAgainstCurrentIngestionImportState(t *testing.T) { if os.Getenv("TEST_TENANT_DSN") == "" { t.Skip("TEST_TENANT_DSN nicht gesetzt, Integrationstest übersprungen") } root := moduleRoot(t) ctx := context.Background() result, err := Run(ctx, root) if err != nil { t.Fatalf("gate-lauf: %v", err) } if result.Timestamp.IsZero() { t.Fatal("erwarteter zeitstempel fehlt") } if !result.KnownErrorPoints.Passed { t.Fatalf("bekannte fehlerpunkte nicht vollständig abgedeckt: %+v", result.KnownErrorPoints.Results) } if !result.TestSuite.Passed { t.Fatalf("testsuiten fehlgeschlagen, ausgabe:\n%s", result.TestSuite.Output) } reportPath := filepath.Join(t.TempDir(), "qa-02-gate-report.md") if err := os.WriteFile(reportPath, []byte(result.Report()), 0o600); err != nil { t.Fatalf("bericht schreiben: %v", err) } t.Logf("Gate-Bericht (%s):\n%s", reportPath, result.Report()) }