Found by a whole-repository review.
What is wrong
The suite cannot dot-source the script, so anything in the linear body can only be pinned by an assertion about the source text. Such an assertion is worth something only when it asserts order, count or adjacency - finding two strings somewhere in a 2868-line file proves nothing.
Five assertions do not clear that bar:
dev_drive.Tests.ps1:65
dev_drive.Tests.ps1:109
dev_drive.Tests.ps1:186
dev_drive.Tests.ps1:273
dev_drive.Tests.ps1:375
Two of them are worse than merely weak
:273 names a condition in its own title - that something happens when BitLocker is skipped - which its assertion never checks. It is also superseded by the stronger test at :342-373, which does pin the adjacency. It can go.
:375 is a global negative grep for the phrase "try again" across the whole file. It passes today, but it will fail the first time a legitimate future message contains those words in an unrelated sentence, and the failure will name a constraint that has nothing to do with the change. A test that will one day be wrong for the wrong reason is a maintenance trap.
What to do
For each: either rewrite it to assert order, count or adjacency - the syntax tree is available and gives exact branch membership, which is stronger than any text proximity - or delete it if a stronger test already covers the same ground.
A worked example already in the file: the assertions that check every withheld deduplication parameter sits inside an if ($DedupCapability.UsesBlockDedup) body do it by walking IfStatementAst and comparing offsets, and were proved to have teeth by inverting the guard on a copy and watching them fail. That is the standard the five should meet.
Scope
dev_drive.Tests.ps1 only. No production code changes.
Updated 2026-08-26, after #97
The line numbers above are stale - the test file has roughly doubled - so find the five by their titles.
There are now several worked examples in the file of assertions that do clear the bar, all of them proved to have teeth by reintroducing their defect on a scratch copy:
- walking the parent chain of a
CommandAst to prove a call sits inside no loop of any shape, including the script block ForEach-Object is handed
- reading the parameter names off a
CommandAst to prove every New-Partition either gives an explicit size or names the virtual disk
- lifting a function out of the tree and enumerating the rejection tokens it can answer, to prove another function has wording for each of them
The third is the pattern most likely to help here: rather than asserting that a string appears, ask the syntax tree a question whose answer changes when the defect returns.
Updated 2026-08-26, second pass — the five are named, and three more join them
The five are identified by title. The stale line numbers were resolved against 4e54197, the last commit to touch the test file before this issue was filed. All five still exist under these titles, so nobody has to hunt for them again:
turns on strict mode
does not claim the weekly scrub job runs at a time it never schedules
starts the compression level unset, so no message can print one nobody chose
prints a plan summary line when BitLocker is skipped
never tells the user to just try again
The verdicts recorded above still stand: the fourth names a condition its assertion never checks and is superseded by a stronger neighbour, and the fifth is a whole-file negative grep that will one day fail for a reason unrelated to the change.
Three more, moved here from #87
#87 proposed lifting the BitLocker and deduplication blocks into phase functions so these behaviours could be tested. Measured at 269045b, that is the expensive way to close them: 20 of the 21 own functions those blocks call already have a Describe block, and Describe 'The script itself' already holds 77 assertions, 49 of them touching the syntax tree. What is genuinely uncovered is uncovered structurally, and closes here without touching production code.
1. Upgrade catches a failed automatic unlock before it calls the BitLocker setup a success. It compares four anchors in text order. That catches the inner try around Enable-BitLockerAutoUnlock being deleted, but not it being widened to wrap the whole BitLocker sequence — the offsets keep their order either way, and a widened try is exactly the defect the separate try exists to prevent. Ask the tree instead: the Enable-BitLockerAutoUnlock call must sit inside a TryStatementAst that is not the one wrapping the sequence.
2. Upgrade checks that the drive accepts writes after BitLocker and before deduplication. Three anchors in text order, so it catches deletion and nothing else. Compare node positions instead: the Get-VolumeWriteState call and the throw that follows it must fall between the end of the BitLocker if body and the Enable-ReFSDedup call.
3. New — nothing covers the password retry loop at all. The while guarding the BitLocker attempt is the only thing standing between a machine that keeps refusing a password and an endless prompt. Assert that its condition names the retry counter against its ceiling, that the counter is incremented inside the body, and that the throw follows the loop. Resolve-BitLockerFailure and Request-BitLockerFailureChoice are both already tested, so what is missing is the wiring, not the decision.
Standard, unchanged
Every one of these must be proved to have teeth by reintroducing its defect on a scratch copy of the script and watching the assertion fail. Scope is still dev_drive.Tests.ps1 only.
Found by a whole-repository review.
What is wrong
The suite cannot dot-source the script, so anything in the linear body can only be pinned by an assertion about the source text. Such an assertion is worth something only when it asserts order, count or adjacency - finding two strings somewhere in a 2868-line file proves nothing.
Five assertions do not clear that bar:
dev_drive.Tests.ps1:65dev_drive.Tests.ps1:109dev_drive.Tests.ps1:186dev_drive.Tests.ps1:273dev_drive.Tests.ps1:375Two of them are worse than merely weak
:273names a condition in its own title - that something happens when BitLocker is skipped - which its assertion never checks. It is also superseded by the stronger test at:342-373, which does pin the adjacency. It can go.:375is a global negative grep for the phrase "try again" across the whole file. It passes today, but it will fail the first time a legitimate future message contains those words in an unrelated sentence, and the failure will name a constraint that has nothing to do with the change. A test that will one day be wrong for the wrong reason is a maintenance trap.What to do
For each: either rewrite it to assert order, count or adjacency - the syntax tree is available and gives exact branch membership, which is stronger than any text proximity - or delete it if a stronger test already covers the same ground.
A worked example already in the file: the assertions that check every withheld deduplication parameter sits inside an
if ($DedupCapability.UsesBlockDedup)body do it by walkingIfStatementAstand comparing offsets, and were proved to have teeth by inverting the guard on a copy and watching them fail. That is the standard the five should meet.Scope
dev_drive.Tests.ps1only. No production code changes.Updated 2026-08-26, after #97
The line numbers above are stale - the test file has roughly doubled - so find the five by their titles.
There are now several worked examples in the file of assertions that do clear the bar, all of them proved to have teeth by reintroducing their defect on a scratch copy:
CommandAstto prove a call sits inside no loop of any shape, including the script blockForEach-Objectis handedCommandAstto prove everyNew-Partitioneither gives an explicit size or names the virtual diskThe third is the pattern most likely to help here: rather than asserting that a string appears, ask the syntax tree a question whose answer changes when the defect returns.
Updated 2026-08-26, second pass — the five are named, and three more join them
The five are identified by title. The stale line numbers were resolved against
4e54197, the last commit to touch the test file before this issue was filed. All five still exist under these titles, so nobody has to hunt for them again:turns on strict modedoes not claim the weekly scrub job runs at a time it never schedulesstarts the compression level unset, so no message can print one nobody choseprints a plan summary line when BitLocker is skippednever tells the user to just try againThe verdicts recorded above still stand: the fourth names a condition its assertion never checks and is superseded by a stronger neighbour, and the fifth is a whole-file negative grep that will one day fail for a reason unrelated to the change.
Three more, moved here from #87
#87 proposed lifting the BitLocker and deduplication blocks into phase functions so these behaviours could be tested. Measured at
269045b, that is the expensive way to close them: 20 of the 21 own functions those blocks call already have aDescribeblock, andDescribe 'The script itself'already holds 77 assertions, 49 of them touching the syntax tree. What is genuinely uncovered is uncovered structurally, and closes here without touching production code.1. Upgrade
catches a failed automatic unlock before it calls the BitLocker setup a success. It compares four anchors in text order. That catches the innertryaroundEnable-BitLockerAutoUnlockbeing deleted, but not it being widened to wrap the whole BitLocker sequence — the offsets keep their order either way, and a widenedtryis exactly the defect the separatetryexists to prevent. Ask the tree instead: theEnable-BitLockerAutoUnlockcall must sit inside aTryStatementAstthat is not the one wrapping the sequence.2. Upgrade
checks that the drive accepts writes after BitLocker and before deduplication. Three anchors in text order, so it catches deletion and nothing else. Compare node positions instead: theGet-VolumeWriteStatecall and thethrowthat follows it must fall between the end of the BitLockerifbody and theEnable-ReFSDedupcall.3. New — nothing covers the password retry loop at all. The
whileguarding the BitLocker attempt is the only thing standing between a machine that keeps refusing a password and an endless prompt. Assert that its condition names the retry counter against its ceiling, that the counter is incremented inside the body, and that the throw follows the loop.Resolve-BitLockerFailureandRequest-BitLockerFailureChoiceare both already tested, so what is missing is the wiring, not the decision.Standard, unchanged
Every one of these must be proved to have teeth by reintroducing its defect on a scratch copy of the script and watching the assertion fail. Scope is still
dev_drive.Tests.ps1only.