Skip to content

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

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

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

Conversation

@ddlees

@ddlees ddlees commented May 29, 2026

Copy link
Copy Markdown
Member

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 components and error-collector message aggregation.
    • Updated integration tests to use rollback-scoped fixture setup for more consistent query preparation and error handling.
    • Refreshed PostgreSQL live tests to use the updated driver-detection helper and the revised database setup signature.
  • Chores
    • Refactored the integration test harness into a session-based workflow with configurable options and cleanup modes, including unified rollback fixture support.

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

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

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: 592ff28b-812e-40b3-bc92-44ae60fd2e3c

📥 Commits

Reviewing files that changed from the base of the PR and between 4ad958a and b28d32d.

📒 Files selected for processing (1)
  • traversal/util_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • traversal/util_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
Exports Open(t, Options) and Session types; adds DriverFromConnectionString, CleanupMode constants, Options struct with helpers, and Session methods (ClearGraph, LoadDataset, WithRollbackFixture, WithRollback); updates buildSchema to use Options; refactors SetupDB/SetupDBWithKinds wrappers to construct sessions via Open.
Fixture management refactor: rollback-based sessions
integration/cypher_test.go, integration/cypher_template_test.go, integration/local_dataset_test.go
Replace manual db.WriteTransaction + errFixtureRollback sentinel with Session.WithRollbackFixture(); move fixture write and query/assert logic into rollback callbacks; simplify error handling and expected-query-error tracking; update SetupDB callsites to pass CleanupGraph argument.
PostgreSQL integration test updates
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
Switch PostgreSQL tests to call DriverFromConnectionString() instead of driverFromConnStr(); adapt SetupDBWithKinds() callsites to the new leading CleanupMode argument.

Traversal Collection Test Coverage

Layer / File(s) Summary
Mock graph DB and test helpers
traversal/util_test.go
Adds mockGraphDB test double implementing graph DB interface with configurable operation error injection; includes hasError matcher and collectionPath helper 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 (deduplication by ID, path collection), PopulateProperties error propagation, and insertion-order preservation 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.

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant Open as Open(t,opts)
  participant Session
  participant WithRollbackFixture
  participant DB as WriteTransaction

  Test->>Open: initialize session
  Open->>Open: detect driver from connection string
  Open->>Open: build dawgs.Config
  Open->>DB: open database connection
  Open-->>Session: return initialized Session
  
  Test->>WithRollbackFixture: pass fixture and callback
  WithRollbackFixture->>DB: create write transaction
  DB->>DB: clear graph (if requested)
  DB->>DB: write fixture data
  DB->>DB: execute query in callback
  DB->>DB: assert result
  DB-->>WithRollbackFixture: transaction complete or error
  WithRollbackFixture-->>Test: return callback result or rollback
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • SpecterOps/DAWGS#88: Both PRs share integration-test harness refactoring in integration/harness.go where Session/Open rollback-scoped fixture wiring is introduced for managing test data lifecycle.
  • SpecterOps/DAWGS#93: Both PRs update PostgreSQL integration tests with DriverFromConnectionString API and SetupDBWithKinds signature changes in property index plan regression tests.

Suggested labels

enhancement, go

Suggested reviewers

  • zinic
  • 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 33.33% 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 describes the main change: standardizing integration test setup and rollback fixtures, with the ticket reference PQE-426 providing context.
Description check ✅ Passed The description follows the template structure with a clear explanation, resolved ticket reference, type of change selected (Test coverage), and mostly complete sections. Testing checkboxes are unchecked, which may indicate incomplete manual verification.
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.

@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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 thread integration/harness.go Outdated
t.Helper()

session := Open(t, Options{
CleanupMode: 0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
CleanupMode: 0,
CleanupMode: CleanupGraph,

nodeKind = graph.StringKind("CountFastPathNode")
edgeKind = graph.StringKind("CountFastPathEdge")
db, ctx = SetupDBWithKinds(t, graph.Kinds{nodeKind}, graph.Kinds{edgeKind})
db, ctx = SetupDBWithKinds(t, 0, graph.Kinds{nodeKind}, graph.Kinds{edgeKind})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
db, ctx = SetupDBWithKinds(t, 0, graph.Kinds{nodeKind}, graph.Kinds{edgeKind})
db, ctx = SetupDBWithKinds(t, CleanupGraph, graph.Kinds{nodeKind}, graph.Kinds{edgeKind})

groupKind = graph.StringKind("Group")
memberOf = graph.StringKind("MemberOf")
db, ctx = SetupDBWithKinds(t, graph.Kinds{userKind, groupKind}, graph.Kinds{memberOf})
db, ctx = SetupDBWithKinds(t, 0, graph.Kinds{userKind, groupKind}, graph.Kinds{memberOf})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
db, ctx = SetupDBWithKinds(t, 0, graph.Kinds{userKind, groupKind}, graph.Kinds{memberOf})
db, ctx = SetupDBWithKinds(t, CleanupGraph, graph.Kinds{userKind, groupKind}, graph.Kinds{memberOf})

Comment thread util/errors_test.go
require.False(t, util.IsNeoTimeoutError(notDriverTimeOutErr))
}

func TestNewErrorCollector(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for adding this coverage 🙏

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.

3 participants