Testing apps that use Collect
Copy MarkdownCollect keeps document data up to date using database triggers. Because database triggers behave differently in the Ecto test sandbox, some adjustments to your test setup are required.
Use the sandbox in :auto mode
Most Ecto test suites run the SQL sandbox in :manual mode, where each test runs inside a transaction
that is rolled back when the test finishes. That gives you clean isolation, but it doesn't
work for testing Collect's incremental updates.
The reason is that Collect's triggers and Collect.merge_deltas/3 need to see committed data. Inside a rolled-back
transaction, the data your test writes is never committed, so the triggers don't behave the way they
would in production, and your assertions won't match.
So for tests that exercise document changes, switch the sandbox to :auto mode:
Ecto.Adapters.SQL.Sandbox.mode(YourApp.Repo, :auto)This way your writes are committed, and the triggers function similar to production.
Clean up between tests
The trade-off with :auto mode is that nothing is rolled back, so anything a test creates sticks around.
For Collect, that includes the triggers it installs on your tables. If one test creates a document table
and the next runs without clearing it, those leftover triggers can fire during the second test and
quietly throw off its results - and because it depends on test order, the failures are intermittent and hard to track down.
Clean up artifacts
Running a reset in a setup block guarantees that every test starts clean, regardless of how the previous one ended - including tests that failed partway through.
You can drop all Collect's artifacts your tests create, calling Collect.TestHelpers.reset_document_artifacts/3 for each config:
setup do
for config <- my_test_configs() do
Collect.TestHelpers.reset_document_artifacts(config, repo: Repo)
end
:ok
endClean up data
Collect.TestHelpers.reset_document_artifacts/3 removes the tables and triggers Collect created, but it leaves data tables alone.
Under :auto mode, every change a test makes is committed, so you also need to reset your data
between tests, or changes from one test (a deleted row, an inserted record) will carry into the next.
Reset your data with TRUNCATE ... RESTART IDENTITY CASCADE to reset the auto-incrementing identity sequence:
setup do
Collect.TestHelpers.reset_document_artifacts(config, repo: Repo)
Repo.query!("""
TRUNCATE articles, categories, article_categories
RESTART IDENTITY CASCADE
""")
# ... insert fresh fixtures
:ok
end