Skip to content

test: prove a failing unit test blocks merging (do not merge) - #137

Closed
j0ker70 wants to merge 6 commits into
mainfrom
test/failing-unit-test
Closed

j0ker70 wants to merge 6 commits into
mainfrom
test/failing-unit-test

Conversation

@j0ker70

@j0ker70 j0ker70 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Do not merge. This pull request will be closed without merging.

It repeats Phase 2's "Done when" check with a real failing unit test, as the comment on #25 asks. #126 already proved it for a failing detekt check. The branch starts from #136's branch, which adds the MVI base classes and the unit test setup, and adds one test to CounterReducerTest that asserts the wrong count. Formatting, detekt, lint and the debug build should still pass, so the unit tests are the only failing check.

What it should show:

  • The Checks job fails on :core:mvi:test only, with 1 failing test.
  • The reports artifact is uploaded.
  • The pull request can't be merged while Checks fails.

#25 stays open until #136 merges.

🤖 Generated with Claude Code

- Plain Kotlin/JVM modules run JUnit 6 through the JUnit Platform, the
  setup Kotlin's docs use, which also brings parameterized tests for the
  YouTube layer's saved responses later.
- Android modules run JUnit 4, AGP's default, because Robolectric and
  Compose's test rules need it and JUnit 6 deprecates the engine that
  would run JUnit 4 tests.
- Both use kotlin.test's annotations and assertions, so a test reads the
  same in either kind of module.
- Add the JUnit Platform launcher explicitly, because Gradle 9 no longer
  puts it on the test classpath.
- Add kotlinx-coroutines-test to both, since most tests will cover
  coroutine code.
- MviState, MviIntent and MviEffect mark each screen's types. The Mvi
  prefix keeps them from clashing with Compose's State and Android's
  Intent in screen code.
- The reducer returns Next, the new state plus any one-time effects, so
  the decision to show an effect stays in pure, tested code.
- MviViewModel runs every intent through the reducer and holds effects
  as pending state with unique ids until the UI calls effectHandled, as
  Android's UI events guidance recommends, so a stopped UI or a
  cancelled handler still gets them.
- Work results come back through dispatch as intents, so every state
  change goes through the reducer.
- The ViewModel base lives in the plain Kotlin/JVM module, built against
  Lifecycle's JVM build, whose ViewModel API matches the Android build.
- A counter example in test code shows the whole pattern, with reducer
  and ViewModel tests.
- The reducer returns the new state and any one-time effects, so effect
  decisions stay in pure code that unit tests cover.
- Intents include the results of work the ViewModel runs, so a finished
  load reaches the screen through the reducer.
- Effects stay pending as UI state until the UI reports them handled,
  as Android's UI events guidance recommends, because a channel doesn't
  guarantee delivery when the ViewModel outlives the UI.
- Fix the roadmap's description of a reducer to match.
- Fill in the MVI contract in architecture.md: the types, how an intent
  flows, effects as pending state, dispatchers, and why the ViewModel
  base fits in a plain Kotlin/JVM module.
- Explain the two JUnit versions in the build settings, and what the
  Android API check does and doesn't check now that a module has code.
- Fill in Running tests locally in testing.md, so later screens follow
  the same test pattern.
- Add the MVI and test rules, and the one-module test commands, to
  AGENTS.md.
- Limit test names with spaces to local tests, because Android runs
  such method names only from API level 30 and the minimum is 29.
- Note the Main dispatcher exception next to the inject-dispatchers
  rule in AGENTS.md, where agents look for it.
- Cite Animal Sniffer's source for how it treats invokedynamic calls,
  and split the long Android API check paragraph into a list.
- Add imports to the effect-handling sketch, so a copy uses
  androidx.lifecycle.compose's LocalLifecycleOwner, not the deprecated
  one in Compose UI.
- Say that a state's initial value doesn't come from the reducer.
- Proves that a pull request whose only failure is a unit test can't
  be merged. The pull request is closed without merging.
@j0ker70

j0ker70 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

Result: the Checks job failed only on :core:mvi:test (10 tests, 1 failed: CounterReducerTest > deliberately failing test()), and the reports artifact was uploaded. Formatting, detekt, lint, the Android API check and the debug build passed. GitHub reported the merge state as BLOCKED. Closing without merging, as planned.

@j0ker70 j0ker70 closed this Oct 15, 2026
@j0ker70
j0ker70 deleted the test/failing-unit-test branch October 15, 2026 12:10
@j0ker70 j0ker70 mentioned this pull request Oct 15, 2026
3 tasks done
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.

1 participant