Skip to content

test(integration): standardize setup and rollback fixtures PQE-426#91

Open
ddlees wants to merge 8 commits into
mainfrom
global-setup-teardown
Open

test(integration): standardize setup and rollback fixtures PQE-426#91
ddlees wants to merge 8 commits into
mainfrom
global-setup-teardown

Conversation

@ddlees
Copy link
Copy Markdown
Member

@ddlees ddlees commented May 29, 2026

Description

This change centralizes integration test setup, schema assertion, driver detection, graph cleanup, and rollback fixture handling in the shared integration harness. It keeps the existing setup helpers available while adding a Session-based API for clearer cleanup behavior and reusable fixture rollback flows across Cypher integration tests.

Resolves: PQE-426

Type of Change

  • Chore (a change that does not modify the application functionality)
  • Bug fix (a change that fixes an issue)
  • New feature / enhancement (a change that adds new functionality)
  • Refactor (no behaviour change)
  • Test coverage
  • Build / CI / tooling
  • Documentation

Testing

  • Unit tests added / updated
  • Integration tests added / updated
  • Full test suite run (make test_all with CONNECTION_STRING set)

Screenshots (if appropriate):

Driver Impact

  • PostgreSQL driver (drivers/pg)
  • Neo4j driver (drivers/neo4j)

Checklist

  • Code is formatted
  • All existing tests pass
  • go.mod / go.sum are up to date if dependencies changed

Summary by CodeRabbit

  • Tests

    • Added unit tests for traversal collection behavior and error-collector utilities.
    • Improved integration test fixture setup and rollback handling to make tests more reliable.
  • Chores

    • Centralized and refactored the integration test harness with configurable session/options, driver detection, and cleanup modes to simplify test setup.

@ddlees ddlees marked this pull request as draft May 29, 2026 16:11
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4d056e7a-3c02-47a3-91c5-11c5278a302a

📥 Commits

Reviewing files that changed from the base of the PR and between 2b94292 and 67e5bc5.

📒 Files selected for processing (4)
  • integration/cypher_template_test.go
  • integration/harness.go
  • traversal/collection_test.go
  • traversal/util_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • traversal/util_test.go
  • integration/cypher_template_test.go
  • traversal/collection_test.go

Walkthrough

Refactors integration-test setup to a session-based API (Open/Session) with rollback fixtures; updates tests (cypher templates, metamorphic, PostgreSQL) to use the new Session helpers; adds traversal collection unit tests with a mock graph DB and an error-collector unit test.

Changes

Integration Test Harness Refactoring

Layer / File(s) Summary
Test harness core API redesign
integration/harness.go
Adds exported Open(t, Options), Session, Options, DriverFromConnectionString, CleanupMode, and methods for ClearGraph, LoadDataset, WithRollbackFixture, and WithRollback; refactors SetupDB*/SetupDBWithKinds to use Open().
Fixture management refactor: rollback-based sessions
integration/cypher_test.go, integration/cypher_template_test.go
Replace manual db.WriteTransaction + errFixtureRollback sentinel with Session.WithRollbackFixture(); move fixture write and query/assert logic into rollback callbacks and simplify error handling and expected-query-error tracking.
PostgreSQL integration test updates
integration/pgsql_*.go
Switch PostgreSQL tests to call DriverFromConnectionString() and adapt SetupDBWithKinds() callsites to the new leading argument where present.

Traversal Collection Test Coverage

Layer / File(s) Summary
Mock graph DB and test utilities
traversal/util_test.go
Adds mockGraphDB test double with configurable operation errors and helpers (collectionPath) for building two-node paths with a relationship.
Collection component unit tests
traversal/collection_test.go
Adds tests for NodeCollector and PathCollector: construction, Add/Collect behavior, PopulateProperties error propagation, and preservation of insertion order for paths.

Error Collector Test

Layer / File(s) Summary
Error collector unit test
util/errors_test.go
Adds TestNewErrorCollector that builds an ErrorCollector, adds two formatted errors, and asserts the combined error message equals the expected newline-separated string.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • SpecterOps/DAWGS#93: Updates PostgreSQL property index plan regression tests with the same DriverFromConnectionString API changes and SetupDBWithKinds signature updates.

Suggested labels

enhancement, go

Suggested reviewers

  • zinic
  • kpom-specter
  • superlinkx

Poem

🐰 A rabbit in the test-tree sings,
Sessions roll back and tidy things,
Mock paths hop, collectors cheer,
Errors gathered, messages clear,
Tests march on — the garden springs.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the primary change: centralizing integration test setup and rollback fixtures, with ticket reference PQE-426.
Description check ✅ Passed The PR description follows the template structure with a clear purpose, correct ticket reference, and appropriate type selection (Test coverage as the primary category).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch global-setup-teardown

Comment @coderabbitai help to get the list of available commands and usage tips.

@ykaiboussiSO ykaiboussiSO changed the title chore: Standerdize Integration TestSetup test(integration): standardize setup and rollback fixtures Jun 1, 2026
@ykaiboussiSO ykaiboussiSO self-assigned this Jun 3, 2026
@ykaiboussiSO ykaiboussiSO changed the title test(integration): standardize setup and rollback fixtures test(integration): standardize setup and rollback fixtures PQE-426 Jun 5, 2026
@ykaiboussiSO ykaiboussiSO marked this pull request as ready for review June 5, 2026 14:50
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
integration/harness.go (1)

77-90: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix cleanup behavior in SetupDBWithKindsNoGraphCleanup

  • SetupDBWithKindsNoGraphCleanup does not enforce close-only cleanup: cleanupMode=0 maps to CleanupGraph, so node deletion happens during cleanup and contradicts the helper’s “NoGraphCleanup” contract.
  • Drop the bolt:// scheme suggestion: the repo’s test setup already normalizes bolt://neo4j:// elsewhere, and there are no bolt:// literals in the codebase.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/harness.go` around lines 77 - 90, SetupDBWithKindsNoGraphCleanup
currently lets cleanupMode=0 map to CleanupGraph so nodes get deleted; change
the logic in SetupDBWithKindsNoGraphCleanup so that when it intends “no graph
cleanup” it sets/uses the close-only cleanup mode (e.g., CleanupCloseOnly or the
existing CloseOnly/Close-only enum/value used by the harness) and ensure the
teardown path only closes DB handles and does NOT call graph-deletion code
(references: SetupDBWithKindsNoGraphCleanup, cleanupMode, CleanupGraph, the
close-only cleanup constant). Also remove any special-case mapping of a "bolt"
scheme in DriverFromConnectionString (stop treating "bolt" as a suggested scheme
or mapping it to neo4j); only accept the canonical neo4j schemes already present
(references: DriverFromConnectionString, neo4j.DriverName).
🧹 Nitpick comments (2)
traversal/util_test.go (1)

39-44: ⚡ Quick win

Invoke delegates in successful write/batch paths.

WriteTransaction and BatchOperation currently return nil without calling their delegates. That can let tests pass even when callback logic is broken.

Proposed fix
 func (m *mockGraphDB) WriteTransaction(ctx context.Context, txDelegate graph.TransactionDelegate, options ...graph.TransactionOption) error {
 	if m.errorMsg.Error() == "Write Transaction Failed" {
 		return fmt.Errorf("Write Transaction Failed")
 	}
-	return nil
+	return txDelegate(m.tx)
 }
@@
 func (m *mockGraphDB) BatchOperation(ctx context.Context, batchDelegate graph.BatchDelegate, options ...graph.BatchOption) error {
 	if m.errorMsg.Error() == "Batch Transaction Failed" {
 		return fmt.Errorf("Batch Transaction Failed")
 	}
-	return nil
+	return batchDelegate(nil)
 }

Also applies to: 53-58

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@traversal/util_test.go` around lines 39 - 44, The mock implementations for
WriteTransaction and BatchOperation must invoke their provided delegates on the
successful path instead of just returning nil; update
mockGraphDB.WriteTransaction to call the supplied txDelegate (and return any
error it returns) when m.errorMsg does not indicate failure, and likewise update
mockGraphDB.BatchOperation to call the provided batch delegate (and return its
error) when no failure is simulated; ensure you pass the context (and any
required args) into the delegate and propagate its returned error so tests
exercise callback logic.
util/errors_test.go (1)

41-50: ⚡ Quick win

Consider adding test coverage for the empty collector case.

The test validates the multiple-error path correctly, but does not verify that Combined() returns nil when no errors have been added. This is important behavior since callers like Operation.Done() rely on this nil-return contract.

🧪 Suggested addition for empty collector case
func TestNewErrorCollector(t *testing.T) {
	errCollector := util.NewErrorCollector()
	
	// Test empty collector returns nil
	err := errCollector.Combined()
	require.Nil(t, err)

	errCollector.Add(fmt.Errorf("errorOne"))
	errCollector.Add(fmt.Errorf("errorTwo"))
	err = errCollector.Combined()

	require.NotNil(t, err)
	require.Equal(t, err.Error(), "errorOne\nerrorTwo")
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@util/errors_test.go` around lines 41 - 50, Add a test case in
TestNewErrorCollector to assert that a newly created util.NewErrorCollector()
returns nil from Combined() when no errors have been added; call errCollector :=
util.NewErrorCollector(), then err := errCollector.Combined() and require.Nil(t,
err) before exercising errCollector.Add(...) and the existing assertions on
Combined(), so the test covers both the empty-collector nil contract relied on
by callers like Operation.Done() and the multi-error behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integration/harness.go`:
- Around line 349-361: The helper SetupDBWithKindsNoGraphCleanup currently
forwards the passed CleanupMode allowing callers to select CleanupGraph; change
it to always use the CloseOnly mode before calling Open so the graph is never
cleared. Specifically, in SetupDBWithKindsNoGraphCleanup override the incoming
cleanupMode value to CleanupMode.CloseOnly (or the CloseOnly constant used in
your CleanupMode type) and pass that into Open via Options (Options.CleanupMode)
while keeping other fields (ExtraNodeKinds, ExtraEdgeKinds, DatasetPath,
Datasets) unchanged.

In `@traversal/collection_test.go`:
- Around line 61-63: Replace the direct dereference of err.Error() with the
proper testify helper to avoid a panic when err is nil: in the test that calls
newCollector.PopulateProperties(ctx, db, "name") (the failing assertion around
err), use assert.EqualError(t, err, "Read Transaction Failed") instead of
assert.Equal(t, err.Error(), "Read Transaction Failed") so the assertion handles
a nil error safely and reports failures cleanly.

In `@traversal/util_test.go`:
- Around line 22-25: The mockGraphDB.SetDefaultGraph implementation returns an
inconsistent error message; when m.errorMsg.Error() == "Failed setting default
graph namespace" it should return that same error instead of "Failed to refresh
kinds". Update SetDefaultGraph (method on mockGraphDB) to return the matching
error (either by returning m.errorMsg or fmt.Errorf("Failed setting default
graph namespace")) so the returned error accurately reflects the condition
checked.
- Around line 22-25: The mock methods (e.g., mockGraphDB.SetDefaultGraph and the
other similar methods in this file) call m.errorMsg.Error() without nil checks
which can panic; update each mock method to first guard that m.errorMsg != nil
before calling .Error() (or use a safe helper like hasErrorMsg := m.errorMsg !=
nil && m.errorMsg.Error() == "Some message"), and keep the existing conditional
behavior intact so a zero-value mockGraphDB behaves as a successful mock.

---

Outside diff comments:
In `@integration/harness.go`:
- Around line 77-90: SetupDBWithKindsNoGraphCleanup currently lets cleanupMode=0
map to CleanupGraph so nodes get deleted; change the logic in
SetupDBWithKindsNoGraphCleanup so that when it intends “no graph cleanup” it
sets/uses the close-only cleanup mode (e.g., CleanupCloseOnly or the existing
CloseOnly/Close-only enum/value used by the harness) and ensure the teardown
path only closes DB handles and does NOT call graph-deletion code (references:
SetupDBWithKindsNoGraphCleanup, cleanupMode, CleanupGraph, the close-only
cleanup constant). Also remove any special-case mapping of a "bolt" scheme in
DriverFromConnectionString (stop treating "bolt" as a suggested scheme or
mapping it to neo4j); only accept the canonical neo4j schemes already present
(references: DriverFromConnectionString, neo4j.DriverName).

---

Nitpick comments:
In `@traversal/util_test.go`:
- Around line 39-44: The mock implementations for WriteTransaction and
BatchOperation must invoke their provided delegates on the successful path
instead of just returning nil; update mockGraphDB.WriteTransaction to call the
supplied txDelegate (and return any error it returns) when m.errorMsg does not
indicate failure, and likewise update mockGraphDB.BatchOperation to call the
provided batch delegate (and return its error) when no failure is simulated;
ensure you pass the context (and any required args) into the delegate and
propagate its returned error so tests exercise callback logic.

In `@util/errors_test.go`:
- Around line 41-50: Add a test case in TestNewErrorCollector to assert that a
newly created util.NewErrorCollector() returns nil from Combined() when no
errors have been added; call errCollector := util.NewErrorCollector(), then err
:= errCollector.Combined() and require.Nil(t, err) before exercising
errCollector.Add(...) and the existing assertions on Combined(), so the test
covers both the empty-collector nil contract relied on by callers like
Operation.Done() and the multi-error behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 779cd8a6-ac6b-4d95-9fdd-7ed249d4cacf

📥 Commits

Reviewing files that changed from the base of the PR and between a637b4a and 2b94292.

📒 Files selected for processing (10)
  • integration/cypher_template_test.go
  • integration/cypher_test.go
  • integration/harness.go
  • integration/pgsql_aggregate_traversal_plan_test.go
  • integration/pgsql_count_fast_path_test.go
  • integration/pgsql_property_equality_test.go
  • integration/pgsql_property_index_plan_test.go
  • traversal/collection_test.go
  • traversal/util_test.go
  • util/errors_test.go

Comment thread integration/harness.go
Comment thread traversal/collection_test.go
Comment thread traversal/util_test.go
Comment on lines +22 to +25
func (m *mockGraphDB) SetDefaultGraph(ctx context.Context, graph graph.Graph) error {
if m.errorMsg.Error() == "Failed setting default graph namespace" {
return fmt.Errorf("Failed to refresh kinds")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return the matching error in SetDefaultGraph.

Line 24 returns "Failed to refresh kinds" for a "Failed setting default graph namespace" condition, which is inconsistent and makes failure intent ambiguous.

Proposed fix
 func (m *mockGraphDB) SetDefaultGraph(ctx context.Context, graph graph.Graph) error {
 	if m.errorMsg.Error() == "Failed setting default graph namespace" {
-		return fmt.Errorf("Failed to refresh kinds")
+		return fmt.Errorf("Failed setting default graph namespace")
 	}
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (m *mockGraphDB) SetDefaultGraph(ctx context.Context, graph graph.Graph) error {
if m.errorMsg.Error() == "Failed setting default graph namespace" {
return fmt.Errorf("Failed to refresh kinds")
}
func (m *mockGraphDB) SetDefaultGraph(ctx context.Context, graph graph.Graph) error {
if m.errorMsg.Error() == "Failed setting default graph namespace" {
return fmt.Errorf("Failed setting default graph namespace")
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@traversal/util_test.go` around lines 22 - 25, The mockGraphDB.SetDefaultGraph
implementation returns an inconsistent error message; when m.errorMsg.Error() ==
"Failed setting default graph namespace" it should return that same error
instead of "Failed to refresh kinds". Update SetDefaultGraph (method on
mockGraphDB) to return the matching error (either by returning m.errorMsg or
fmt.Errorf("Failed setting default graph namespace")) so the returned error
accurately reflects the condition checked.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard errorMsg before calling .Error() across mock methods.

Line 23 (and the other similar checks) dereferences m.errorMsg without a nil guard. A zero-value mockGraphDB will panic instead of behaving like a successful mock.

Proposed fix
+func (m *mockGraphDB) hasError(msg string) bool {
+	return m.errorMsg != nil && m.errorMsg.Error() == msg
+}
+
 func (m *mockGraphDB) SetDefaultGraph(ctx context.Context, graph graph.Graph) error {
-	if m.errorMsg.Error() == "Failed setting default graph namespace" {
+	if m.hasError("Failed setting default graph namespace") {
 		return fmt.Errorf("Failed to refresh kinds")
 	}
 	return nil
 }
 
 func (m *mockGraphDB) ReadTransaction(ctx context.Context, txDelegate graph.TransactionDelegate, options ...graph.TransactionOption) error {
@@
-	if m.errorMsg.Error() == "Read Transaction Failed" {
+	if m.hasError("Read Transaction Failed") {
 		return fmt.Errorf("Read Transaction Failed")
 	}
@@
 func (m *mockGraphDB) WriteTransaction(ctx context.Context, txDelegate graph.TransactionDelegate, options ...graph.TransactionOption) error {
-	if m.errorMsg.Error() == "Write Transaction Failed" {
+	if m.hasError("Write Transaction Failed") {
 		return fmt.Errorf("Write Transaction Failed")
 	}
 	return nil
 }

Also applies to: 29-37, 39-44, 46-51, 53-58, 60-65, 67-72, 74-79, 81-86

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@traversal/util_test.go` around lines 22 - 25, The mock methods (e.g.,
mockGraphDB.SetDefaultGraph and the other similar methods in this file) call
m.errorMsg.Error() without nil checks which can panic; update each mock method
to first guard that m.errorMsg != nil before calling .Error() (or use a safe
helper like hasErrorMsg := m.errorMsg != nil && m.errorMsg.Error() == "Some
message"), and keep the existing conditional behavior intact so a zero-value
mockGraphDB behaves as a successful mock.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants