test(db): one fixture builder instead of fourteen per-view seeds - #269
Merged
Merged
Conversation
The per-view seed helpers in internal/db/tasks_test.go had grown to fifteen, one per PR this week, each re-inserting its own areas, projects and to-dos, and the shared assertion helpers sat beside them rather than in testhelpers_test.go. Move uuidsOf, sameSet and keysOf into testhelpers_test.go next to a small fixture builder, and fold the fourteen per-view seeds into the tests that used them, so a test now seeds only the rows it asserts on. seedTasks stays: twenty-two tests read it as the general fixture, and folding it would rewrite most of the file for no gain. The builder takes every value an assertion can turn on rather than defaulting it. "index" is a required argument on every row and dates are passed in, because several ordering tests seed those deliberately against the order they expect, and area and project indexes are negative, as Things writes them. Each seed was first rewritten through the builder and pinned row for row against a copy of the SQL it replaced, so the fold below only removes rows from a fixture, never changes a value. The passing test list is identical, 263 tests, and the list-query golden file regenerates with no diff. While here: - TestListTasksTodayIncludeCompletedProject stopped a row a minute in the past, which falls on the previous calendar day in the first minute after midnight and failed the test there. It now stops it at time.Now(), the convention the rest of the file follows. - TestListQueryGoldenSQL reported differences only from inside its per-case loop, so a difference outside a "### view=" block passed with got != want. This is the fix #264 applied to TestRenderGolden. - The comment above TestPrintTasksNoRepeatedProjectHeader said today, upcoming and anytime all list a scheduled project as a row; anytime has carried no project rows since issue #217. Closes #244
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #244
What changed
internal/db/tasks_test.gohad fifteen seed helpers, one per PR thisweek, each re-inserting its own areas, projects and to-dos, and the
shared assertion helpers
uuidsOf,sameSetandkeysOfsat besidethem rather than in
testhelpers_test.go.The three assertion helpers move to
testhelpers_test.go, next to asmall fixture builder, and the fourteen per-view seeds are folded into
the tests that used them. A test now seeds only the rows it asserts on:
TestListTasksSomedayHidesChildOfSomedayProjectwent from nine rows totwo,
TestListTasksTodayIncludeCompletedProjectfrom twelve to three.seedTasksstays. Twenty-two tests read it as the general fixturecovering every view and status, so folding it would rewrite most of the
file for no gain; it is now built through the same builder as everything
else.
The builder
"index"is a required argument on every row and every date is passedin. Nothing an assertion can turn on is defaulted, because eleven tests
assert order rather than membership and several seed their indexes
deliberately against the order they expect, which is what leaves the key
under test as the only thing that can produce it. Area and project
indexes stay negative, as Things writes them — the ordering CASE keys
exist because an unfiled row's
COALESCEdefault of 0 would sort itlast instead of first (#217, #237).
Options name a Things bucket rather than the raw columns:
inbox(),anytime(),anytimeOn(date),evening(date),someday(),somedayOn(date). The rest are one per column:inArea,inProject,underHeading,notes,trashed,completed(stop),cancelled(stop),status,deadline,todayIndex,todayIndexRef,repeats.Also in this pass
TestListTasksTodayIncludeCompletedProjectstopped a row a minute inthe past. The calendar day decides whether a closed row is still under
Today (#230), so a minute before midnight falls on the previous day and
the test failed in the first minute of every day. It now stops the row
at
time.Now(), the convention the rest of the file follows.TestListQueryGoldenSQLreported differences only from inside itsper-case loop, so a difference outside a
### view=block — trailingwhitespace, text before the first header — passed with
got != want.This is the two-line fix #264 applied to
TestRenderGolden. Verified byappending a blank line to the golden file: the test now fails with
generated SQL differs from testdata/list_query_golden.txt outside any case body.The comment above
TestPrintTasksNoRepeatedProjectHeadersaid today,upcoming and anytime all list a scheduled project as a row. Anytime has
carried no project rows since #217.
Evidence
The passing test list is identical before and after — 263 tests across
internal/dbandinternal/output, no test renamed, added or removed:Per-function coverage is identical too, function for function across
both packages, so the folded fixtures still reach every line the fuller
ones did:
Every seed was first rewritten through the builder and pinned row for
row against a copy of the SQL it replaced — all four tables dumped and
compared column by column, with
stopDatevalues bucketed to the minuteso two
time.Now()calls a microsecond apart compare equal. All fifteenmatched exactly, including the
todayIndex = 0values that would sortdifferently from NULL under the today and upcoming orderings. Only then
were rows dropped from a fixture, so the fold below removes rows and
never changes a value. That scaffolding is not part of the PR.
A differential mutation study confirms the smaller fixtures still bite.
Nine predicates in
internal/db/tasks.gowere broken one at a time —untrashedRows,notHeading,todoOrProject, the template-row andtemplate-child exclusions,
untrashedParent,unparented,todoOnlyand
openRows— and each mutant run against both the old and the newtest file. Every mutation is still caught. Four more, on the view table
itself, are caught by the folded tests too: someday losing
unparented,anytime gaining
includesProjects, trash losing it, andtodoOrProjectadmitting headings.
What the fold does cost is redundancy. Five of those nine mutations used
to fail
TestListTasksDeadlinesIncludeProjectsandTestListTasksDeadlinesOrderWithProjectas well, because the sharedseed handed them six rows they never asserted on and their exact-set
assertions failed on any leak. Each of those five is still caught by
TestListTasksDeadlinesProjectExclusions, which is the test that ownsthose rows. The same trade, smaller, applies to
TestListTasksLogbookIncludesCancelled,TestListTasksTodayOrderWithProjectsandTestListTasksViewsIncludeProjects. Putting the rows back is theduplication this PR set out to remove.
testdata/list_query_golden.txtregenerates with no diff.Notes for review
The three arrangement tests that seed negative area and project indexes
—
TestAnytimeGroupsByAreaThenProject,TestTodayGroupsLooseTodosBeforeProjectTodosandTestSomedayGroupsUnfiledThenAreas— keep their own inline SQL. Theywere never seed helpers, so converting them is outside what #244 asks
for, and their literal indexes are the whole point of those tests.
TestListTasksTrashProjectExclusionsasserts thattrash-headis notlisted, but the row is hidden by the trashed-parent fold rather than by
the heading exclusion — it stayed out even with
todoOrProjectmutatedto admit type 2. That is unchanged from before this PR; the fixture had
the same shape. Its
live-projandlive-todoassertions do bite.TestListTasksDeadlinesIncludeProjectsandTestListTasksDeadlinesOrderWithProjectnow visibly assert the samelisting, one with
sameSetand one withreflect.DeepEqual, andTestListTasksLogbookIncludesCancelledandTestListTasksLogbookCancelledOrderare the same pair. Both predatethis PR and are left alone.
No production code changed.