microsoft / microsoft/microsoft-ui-reactor

[Bug] Row-edit backward test: two entailed assertions, and its "differential isolation" block compares two arms that converge

Open Beginner friendly
#1,022 1 comment 0 reactions 0 assignees View on GitHub
bug needs-triage
Dominant language
C#
Stars
646
Forks
54
Avg merge
1d 3h
Merged PRs (30d)
84

Description

### What happened?

`tests/Reactor.Tests/DataGridRowEditKeyboardTests.cs` →
`FocusPrevRowEditColumn_WalksBackwardAndWraps` (`:254-282` on `main`) contains two assertions
that **cannot fail independently**, and a comment that names the wrong pair as the test's
direction oracle.

The test's real oracle is sound — this is not a false green, and `FocusPrevRowEditColumn` is
genuinely covered. It is filed because both problems make the test *read* as more rigorous than
it is, which is how vacuous assertions survive review.

Constants (`:47-49`): `IdCol = 0`, `NameCol = 1`, `ScoreCol = 2`.

**1. Two entailed assertions.**

```csharp
:270 Assert.Equal(NameCol, state.FocusedColIndex); // x must be 1
:271 Assert.NotEqual(IdCol, state.FocusedColIndex); // asserts x != 0 <- ENTAILED

:280 Assert.Equal(NameCol, forward.FocusedColIndex); // x must be 1
:281 Assert.NotEqual(ScoreCol, forward.FocusedColIndex); // asserts x != 2 <- ENTAILED
```

Exhaustive over all `int x`: no value satisfies the `Equal` and fails the `NotEqual` beneath it.
Deleting `:271` and `:281` cannot change the test's verdict on any input.

`:271`'s comment — *"read-only column is skipped both ways"* — states a real and important
property, but the assertion under it does not test that property. The property is already proven,
by the two `Equal`s: they pin **every** position the backward walk visits (`Score` at `:267`,
then `Name` at `:270`), so `Id`'s absence from that sequence is the proof. There is no position
left for a further assertion to constrain.

**2. The sharper one: the "differential isolation" block compares arms that converge.**

```csharp
:275 // Differential isolation: same grid, same start, only the direction differs.
:266/:269 backward: Id -> Score -> Name (TWO steps, ends NameCol)
:279 forward: Id -> Name (ONE step, ends NameCol)
```

The two arms take **different step counts** and land on the **same column**. Their endpoint
values are both `NameCol`, so at the point the comment claims a differential, the two directions
are *indistinguishable*. An endpoint comparison between these arms would be direction-blind.

The genuine discriminator is already in the file, one step earlier, and is unlabelled:

```csharp
:267 Assert.Equal(ScoreCol, state.FocusedColIndex); // backward, step 1
:280 Assert.Equal(NameCol, forward.FocusedColIndex); // forward, step 1
```

Same start, one step each, different results. **That** is the pair that cannot both hold if the
two directions collapse — and it is what makes the test non-vacuous today.

### Steps to reproduce

Both parts are decidable statically; each also has a mutation that confirms it.

1. **Entailment.** Delete `:271` and `:281`, then
`dotnet test tests/Reactor.Tests --filter "FullyQualifiedName~FocusPrevRowEditColumn_WalksBackwardAndWraps" -p:Platform=x64 -p:SkipSignaturesGen=true`
→ still passes. Detection power is unchanged, because no `int` satisfies the `Equal` above
each and fails the `NotEqual`.
2. **Converging arms.** Compare `:270` and `:280` by inspection: both assert `NameCol`. The two
arms report the same value, so no comparison between them can distinguish direction.
3. **Where the power actually is.** Mutate `DataGridState.FocusPrevRowEditColumn()` to call
`MoveRowEditFocus(+1)` and re-run → the failure is at **`:267`** (`Expected: 2, Actual: 1`),
not at any of the assertions in the block labelled "differential isolation".

### Suggested change

- Delete `:271` and `:281`.
- Retarget the comment at `:275` so it names `:267` vs `:280` — the first step of each arm — as
the discriminating pair, and states why the endpoints are *not* comparable (unequal step
counts, converging on `NameCol`).
- Keep `:279-280`: pinning forward-from-read-only is worth asserting on its own merits. It just
is not a differential against the backward arm's endpoint.

General form, for the surrounding tests: `Assert.NotEqual(armA, armB)` earns its place only when
the expectations are **computed from the fixture**, where both arms can drift to the same value
while each still matches its own derived expectation. Against **distinct literal constants**, the
paired `Equal`s are the stronger construction and already fail loudly if the fixture degenerates.

### Related context

The 2-column editable ring is the underlying reason this test is delicate. With only `Name` and
`Score` editable, prev and next are the **same element** from any in-ring start, so direction is
observable *only* from a start outside the ring (the read-only column, or the `-1` sentinel) —
which is exactly the origin `:262` chooses, and why that choice is correct and load-bearing.

The same 2-element ring independently hid a real product bug in #1016 (*"a single Tab went
first → last → wrapped back to first and focus never appeared to move"*). A **third editable
column** in this fixture would make the directions diverge from every start and remove the
constraint from both. Worth considering alongside this change rather than after it.

### Reactor version / commit

`e0bab27f` introduced both assertions (`git log -S`), and is contained in `origin/main`.
Verified against `origin/main` @ `3f85ca49`.

### Platform

Both — headless xUnit, architecture-independent.

### .NET SDK version

10.0.302

### Windows version

N/A — headless unit test, no live WinUI objects constructed.

### Windows App SDK version

N/A — headless unit test.

### Logs / stack trace

N/A — the test passes. The finding is that two of its assertions cannot fail, and that a comment
attributes the test's discriminating power to the wrong pair of lines.

### Confirmation

- [x] I have searched existing issues and this isn't a duplicate.
- [x] This bug reproduces against the current `main` branch.

Contributor guide

Open the contributing guide

Research direction

Start in tests/Reactor.Tests/DataGridRowEditKeyboardTests.cs at FocusPrevRowEditColumn_WalksBackwardAndWraps, then run the provided dotnet test filter. Remove the two entailed NotEqual assertions and retarget the differential-isolation comment to the first-step assertions at :267 and :280, while keeping the forward assertion. Done means the focused test still passes and the comment accurately describes the converging endpoints.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
testing-qa
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.