@mrciphersmith/keryx 0.3.3 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +996 -366
- package/docs/README.md +2 -0
- package/package.json +1 -1
- package/src/gdskills/bundled/install-manifest.json +520 -48
- package/src/gdskills/bundled/stacks/csharp-dotnet/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/governance/eval.json +1881 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/pack.json +38 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/coding-style.mdc +100 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/patterns.mdc +107 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/security.mdc +86 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/evals.json +77 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/SKILL.md +121 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/evals.json +77 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/evals.json +76 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/SKILL.md +130 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/evals.json +77 -0
- package/src/gdskills/bundled/stacks/django/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/django/governance/eval.json +1763 -0
- package/src/gdskills/bundled/stacks/django/governance/scout.json +40 -0
- package/src/gdskills/bundled/stacks/django/pack.json +43 -0
- package/src/gdskills/bundled/stacks/django/rules/coding-style.mdc +80 -0
- package/src/gdskills/bundled/stacks/django/rules/patterns.mdc +92 -0
- package/src/gdskills/bundled/stacks/django/rules/security.mdc +92 -0
- package/src/gdskills/bundled/stacks/django/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/django/skills/django-build-fix/SKILL.md +149 -0
- package/src/gdskills/bundled/stacks/django/skills/django-build-fix/evals.json +49 -0
- package/src/gdskills/bundled/stacks/django/skills/django-code-review/SKILL.md +137 -0
- package/src/gdskills/bundled/stacks/django/skills/django-code-review/evals.json +48 -0
- package/src/gdskills/bundled/stacks/django/skills/django-implementation/SKILL.md +147 -0
- package/src/gdskills/bundled/stacks/django/skills/django-implementation/evals.json +75 -0
- package/src/gdskills/bundled/stacks/django/skills/django-migrate/SKILL.md +166 -0
- package/src/gdskills/bundled/stacks/django/skills/django-migrate/evals.json +49 -0
- package/src/gdskills/bundled/stacks/django/skills/django-testing/SKILL.md +130 -0
- package/src/gdskills/bundled/stacks/django/skills/django-testing/evals.json +48 -0
- package/src/gdskills/bundled/stacks/fastapi/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/fastapi/governance/eval.json +1777 -0
- package/src/gdskills/bundled/stacks/fastapi/governance/scout.json +34 -0
- package/src/gdskills/bundled/stacks/fastapi/pack.json +43 -0
- package/src/gdskills/bundled/stacks/fastapi/rules/coding-style.mdc +68 -0
- package/src/gdskills/bundled/stacks/fastapi/rules/patterns.mdc +108 -0
- package/src/gdskills/bundled/stacks/fastapi/rules/security.mdc +99 -0
- package/src/gdskills/bundled/stacks/fastapi/rules/testing.mdc +85 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/SKILL.md +157 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-build-fix/evals.json +76 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/SKILL.md +150 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/SKILL.md +158 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-implementation/evals.json +75 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/SKILL.md +146 -0
- package/src/gdskills/bundled/stacks/fastapi/skills/fastapi-testing/evals.json +74 -0
- package/src/gdskills/bundled/stacks/flutter-dart/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/flutter-dart/governance/eval.json +1849 -0
- package/src/gdskills/bundled/stacks/flutter-dart/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/flutter-dart/pack.json +41 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/coding-style.mdc +98 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/patterns.mdc +88 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/security.mdc +91 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/testing.mdc +101 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/evals.json +79 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/SKILL.md +124 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/evals.json +77 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/evals.json +74 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/eval.json +2194 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/governance/scout.json +39 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/pack.json +40 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/coding-style.mdc +67 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/patterns.mdc +65 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/security.mdc +69 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/rules/testing.mdc +80 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/SKILL.md +144 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-build-fix/evals.json +74 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/SKILL.md +129 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/SKILL.md +147 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-implementation/evals.json +75 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-migrate/evals.json +74 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/SKILL.md +128 -0
- package/src/gdskills/bundled/stacks/java-kotlin-spring/skills/java-kotlin-spring-testing/evals.json +73 -0
- package/src/gdskills/bundled/stacks/kotlin-android/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/kotlin-android/governance/eval.json +1889 -0
- package/src/gdskills/bundled/stacks/kotlin-android/governance/scout.json +34 -0
- package/src/gdskills/bundled/stacks/kotlin-android/pack.json +38 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/coding-style.mdc +89 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/patterns.mdc +96 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/security.mdc +90 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/SKILL.md +150 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/evals.json +77 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/SKILL.md +151 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/evals.json +76 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/evals.json +78 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/SKILL.md +131 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/evals.json +77 -0
- package/src/gdskills/bundled/stacks/python/agent-refs.json +2 -1
- package/src/gdskills/bundled/stacks/python/pack.json +1 -1
- package/src/gdskills/bundled/stacks/rust/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/rust/governance/eval.json +1823 -0
- package/src/gdskills/bundled/stacks/rust/governance/scout.json +32 -0
- package/src/gdskills/bundled/stacks/rust/pack.json +42 -0
- package/src/gdskills/bundled/stacks/rust/rules/coding-style.mdc +93 -0
- package/src/gdskills/bundled/stacks/rust/rules/patterns.mdc +85 -0
- package/src/gdskills/bundled/stacks/rust/rules/security.mdc +85 -0
- package/src/gdskills/bundled/stacks/rust/rules/testing.mdc +82 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/SKILL.md +141 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-build-fix/evals.json +78 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/SKILL.md +127 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-code-review/evals.json +72 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/SKILL.md +133 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-implementation/evals.json +79 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-testing/SKILL.md +130 -0
- package/src/gdskills/bundled/stacks/rust/skills/rust-testing/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/swift-ios/governance/eval.json +1803 -0
- package/src/gdskills/bundled/stacks/swift-ios/governance/scout.json +32 -0
- package/src/gdskills/bundled/stacks/swift-ios/pack.json +38 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/coding-style.mdc +92 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/patterns.mdc +112 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/security.mdc +78 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/testing.mdc +90 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/SKILL.md +144 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/SKILL.md +122 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/SKILL.md +131 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/SKILL.md +149 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/evals.json +76 -0
- package/src/gdskills/bundled/agents/python-build-fixer.md +0 -52
- package/src/gdskills/bundled/agents/python-code-auditor.md +0 -49
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin-android-testing
|
|
3
|
+
description: "Use when a Kotlin/Android module's test suite needs writing, extending, or fixing -- runTest/TestDispatcher for suspend functions and ViewModels, ComposeTestRule semantics-based finders for UI tests, and MockK at the repository/data-source interface boundary."
|
|
4
|
+
triggers:
|
|
5
|
+
- "write tests for this ViewModel"
|
|
6
|
+
- "add a Compose UI test for this screen"
|
|
7
|
+
- "fix this flaky Android test"
|
|
8
|
+
- "test this suspend function"
|
|
9
|
+
- "mock the repository for this unit test"
|
|
10
|
+
- "cover this feature module with tests"
|
|
11
|
+
- "the test for this screen keeps timing out"
|
|
12
|
+
metadata:
|
|
13
|
+
origin: authored
|
|
14
|
+
category: test
|
|
15
|
+
version: "1.0.0"
|
|
16
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
17
|
+
license: "MIT"
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Kotlin/Android testing
|
|
21
|
+
|
|
22
|
+
Write, extend, or fix a Kotlin/Android module's test suite: coroutine
|
|
23
|
+
tests with `runTest`/`TestDispatcher`, Compose UI tests with
|
|
24
|
+
`ComposeTestRule`, and interface-boundary mocking. `rules/testing.mdc`
|
|
25
|
+
carries the full rule set this skill's checklist is built from — read it,
|
|
26
|
+
not just this summary, before writing tests.
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
### Step 1: Discover the project's test conventions
|
|
31
|
+
|
|
32
|
+
1. Read the module's `build.gradle(.kts)` test dependencies: MockK vs
|
|
33
|
+
Mockito, `kotlinx-coroutines-test` version, and whether a Compose UI
|
|
34
|
+
test dependency (`androidx.compose.ui:ui-test-junit4`) is present.
|
|
35
|
+
2. Find the layout: unit tests under `src/test/`, instrumented/Compose UI
|
|
36
|
+
tests under `src/androidTest/`. Match whichever the module already
|
|
37
|
+
uses; do not invent a third location.
|
|
38
|
+
3. Read 1-2 neighboring test files for: dispatcher-rule setup (a shared
|
|
39
|
+
`MainDispatcherRule` or manual `Dispatchers.setMain`/`resetMain`),
|
|
40
|
+
whether MockK or Mockito is standardized, and existing fixture/builder
|
|
41
|
+
helpers for constructing test data.
|
|
42
|
+
|
|
43
|
+
### Step 2: Plan test cases
|
|
44
|
+
|
|
45
|
+
**`ViewModel`/suspend functions:** happy path, error/exception path from
|
|
46
|
+
a mocked dependency, and any intermediate state a caller can observe (a
|
|
47
|
+
loading state before a result arrives) using a `StandardTestDispatcher`
|
|
48
|
+
you advance explicitly.
|
|
49
|
+
|
|
50
|
+
**Compose UI:** initial render state, a user interaction
|
|
51
|
+
(`performClick()`, `performTextInput()`) and its resulting state/text
|
|
52
|
+
change, and a conditionally-shown element's visibility.
|
|
53
|
+
|
|
54
|
+
**Repository/data layer:** success and failure responses from the mocked
|
|
55
|
+
network/database boundary, and that a domain-level error type is what
|
|
56
|
+
actually reaches the caller (not a raw exception leaking through).
|
|
57
|
+
|
|
58
|
+
### Step 3: Write
|
|
59
|
+
|
|
60
|
+
1. Wrap coroutine test bodies in `runTest { }`; install a `TestDispatcher`
|
|
61
|
+
for `Dispatchers.Main` via a shared JUnit rule (or manual
|
|
62
|
+
`Dispatchers.setMain(...)`/`Dispatchers.resetMain()` in
|
|
63
|
+
`@Before`/`@After`) so `viewModelScope` resolves to it.
|
|
64
|
+
2. Mock the `Repository`/`ApiService`/data-source interface the class
|
|
65
|
+
under test depends on with MockK (`mockk<Repo>()`,
|
|
66
|
+
`coEvery { repo.fetch() } returns result`) — never stub the class
|
|
67
|
+
under test's own internals.
|
|
68
|
+
3. For a Compose UI test, use `createComposeRule()` (or
|
|
69
|
+
`createAndroidComposeRule<Activity>()` when an Activity host is
|
|
70
|
+
needed) and find nodes via `onNodeWithText`/
|
|
71
|
+
`onNodeWithContentDescription`/`onNodeWithTag`, not structural
|
|
72
|
+
indexing.
|
|
73
|
+
4. Advance the test dispatcher deliberately
|
|
74
|
+
(`advanceUntilIdle()`/`runCurrent()`) at the point where the test
|
|
75
|
+
needs to observe an intermediate or final state — never a fixed
|
|
76
|
+
`delay`/`Thread.sleep` to "give it time."
|
|
77
|
+
5. Assert both the rendered/returned state and, where relevant, a
|
|
78
|
+
`coVerify { repo.save(...) }` that the right interaction actually
|
|
79
|
+
happened.
|
|
80
|
+
|
|
81
|
+
### Step 4: Run and fix
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
./gradlew testDebugUnitTest
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run `./gradlew connectedDebugAndroidTest` (or the project's Compose UI
|
|
88
|
+
test task) for instrumented tests when relevant. Fix failing tests (max 3
|
|
89
|
+
iterations) — fix the test, not the source under test, unless the test
|
|
90
|
+
itself has correctly caught a real bug (say so in the report rather than
|
|
91
|
+
silently changing production code).
|
|
92
|
+
|
|
93
|
+
### Step 5: Report
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Generated: feature/profile/ProfileViewModelTest.kt
|
|
97
|
+
- 6 cases (runTest + StandardTestDispatcher), repository mocked with MockK
|
|
98
|
+
- ./gradlew testDebugUnitTest passes
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Rules
|
|
102
|
+
|
|
103
|
+
- ALWAYS match the project's existing dispatcher-rule and mocking-library
|
|
104
|
+
conventions found in Step 1, not a different project's style.
|
|
105
|
+
- NEVER modify source code — only test files.
|
|
106
|
+
- NEVER use `Thread.sleep`/a fixed `delay` to wait for a coroutine or
|
|
107
|
+
Compose UI update; use `runTest`'s virtual time, `advanceUntilIdle()`,
|
|
108
|
+
or `composeTestRule.waitUntil { ... }`.
|
|
109
|
+
- Mock at the repository/data-source interface boundary, never the class
|
|
110
|
+
under test's own private methods or fields.
|
|
111
|
+
|
|
112
|
+
## Red Flags
|
|
113
|
+
|
|
114
|
+
| Rationalization | Why it is wrong |
|
|
115
|
+
|---|---|
|
|
116
|
+
| "I'll add a short delay so the coroutine has time to finish" | Non-deterministic and slow; `runTest`'s virtual clock plus `advanceUntilIdle()` makes the wait both instant and deterministic |
|
|
117
|
+
| "I'll just mock a private method on the ViewModel itself to control what it returns" | Testing a mocked-out internal instead of real behavior; mock the repository/data-source interface the ViewModel actually depends on |
|
|
118
|
+
| "This UI test keeps flaking, I'll add a `Thread.sleep(500)` before the assertion" | Hides a real synchronization gap; use `composeTestRule.waitUntil { ... }` or advance the test dispatcher instead |
|
|
119
|
+
| "I'll loosen this assertion to just check the call didn't throw" | Covers nothing about which state or value resulted; assert the actual state/text/interaction outcome |
|
|
120
|
+
|
|
121
|
+
## Verification
|
|
122
|
+
|
|
123
|
+
Do not report the work done until all of the following hold:
|
|
124
|
+
|
|
125
|
+
- The test file sits at the project's own convention path
|
|
126
|
+
(`src/test/`/`src/androidTest/`), matching Step 1's findings.
|
|
127
|
+
- `./gradlew testDebugUnitTest` (and the instrumented task, if touched)
|
|
128
|
+
exits 0 with every generated test passing.
|
|
129
|
+
- `git status` shows only test files added or modified; no source file
|
|
130
|
+
under test changed.
|
|
131
|
+
- No test synchronizes with `Thread.sleep`/a fixed `delay`.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"This ViewModel's loadProfile function needs test coverage before we merge",
|
|
5
|
+
"Add a test that clicking the retry button actually triggers a refetch",
|
|
6
|
+
"The repository call in this suspend function isn't covered by any test",
|
|
7
|
+
"Write a test for the error state shown when the network call fails",
|
|
8
|
+
"This screen's test keeps waiting forever, can you fix it",
|
|
9
|
+
"We need a test proving the save button disables itself while saving",
|
|
10
|
+
"Cover this list-filtering logic in the ViewModel with unit tests"
|
|
11
|
+
],
|
|
12
|
+
"negative": [
|
|
13
|
+
"Write an XCTest for this SwiftUI view model's published property",
|
|
14
|
+
"Add a widget test for this Flutter StatefulWidget's local state",
|
|
15
|
+
"Write an xUnit test for this ASP.NET Core controller action",
|
|
16
|
+
"Add a React Testing Library test for this component's click handler",
|
|
17
|
+
"Write a pytest case for this FastAPI endpoint's validation logic",
|
|
18
|
+
"Review this Kotlin diff for exported manifest components before merge",
|
|
19
|
+
"Fix the failing Gradle build after this dependency version bump"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"scenarios": [
|
|
23
|
+
{
|
|
24
|
+
"id": "mock-repository-boundary",
|
|
25
|
+
"prompt": "I have a ViewModel with a `loadProfile()` function that calls `profileRepository.fetch()`, a suspend function declared on a `ProfileRepository` interface. I want to unit test what happens when that call fails. How should I set up the mock?",
|
|
26
|
+
"strictness": "high",
|
|
27
|
+
"expected_behavior": [
|
|
28
|
+
{
|
|
29
|
+
"grader": "judge",
|
|
30
|
+
"rubric": "A correct answer mocks the ProfileRepository interface itself (with MockK, unless the project already standardizes on Mockito), stubbing its suspend fetch() function with a coroutine-aware form (e.g. coEvery { repository.fetch() } throws SomeException()) to simulate the failure, rather than reaching into the ViewModel under test to stub its own internal method or field.",
|
|
31
|
+
"pass_criteria": [
|
|
32
|
+
"Mocks the ProfileRepository interface (the collaborator/dependency), not the ViewModel under test's own internals.",
|
|
33
|
+
"Uses a coroutine-aware stubbing form for the suspend fetch() call (e.g. coEvery ... throws / coEvery ... returns), not the plain non-suspend every/when form.",
|
|
34
|
+
"States that the ViewModel is then exercised through its real loadProfile() call with the mocked repository injected, and the resulting error state is asserted."
|
|
35
|
+
],
|
|
36
|
+
"fail_criteria": [
|
|
37
|
+
"Recommends stubbing or overriding a private method or field on the ViewModel under test itself instead of mocking the ProfileRepository dependency.",
|
|
38
|
+
"Uses a plain, non-coroutine-aware mocking call (e.g. every { repository.fetch() } ...) on a suspend function without a coroutine-aware form."
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"calibration": {
|
|
43
|
+
"known_right": "Mock the `ProfileRepository` interface, not the ViewModel: `val repository = mockk<ProfileRepository>()`, then stub the failure with the coroutine-aware form since `fetch()` is a suspend function -- `coEvery { repository.fetch() } throws IOException()`. Construct the ViewModel with that mocked repository injected, call `viewModel.loadProfile()` inside `runTest { }`, advance the test dispatcher, and assert the ViewModel's exposed state ended up in its error variant. The mock stays at the repository boundary the whole way through; the ViewModel's own internals are exercised for real, which is what actually proves the error-handling path works.",
|
|
44
|
+
"known_wrong": "Since `loadProfile()` is public but calls a private `handleFetch()` helper internally, just use MockK's `spyk` on the ViewModel itself and stub `every { viewModel invoke \"handleFetch\" }` (or override the private method via reflection) to throw the exception directly -- that way you don't need to worry about setting up the repository interface at all, you're testing exactly the branch you care about.",
|
|
45
|
+
"vague": "Mock the dependency so the failure path runs and check that the ViewModel ends up in an error state.",
|
|
46
|
+
"subtle_wrong": "Mock the repository, but since `fetch()` is just a regular function call from the test's point of view, stub it the normal way: `every { repository.fetch() } throws IOException()`. It compiles and the test passes locally, so the coroutine-specific stubbing form isn't really necessary here."
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "suspend-function-runtest",
|
|
51
|
+
"prompt": "I want to test a suspend function in this repository class that calls `delay(2000)` before returning a cached value if the network is slow. What's the right way to test that without the test actually taking two seconds?",
|
|
52
|
+
"strictness": "high",
|
|
53
|
+
"expected_behavior": [
|
|
54
|
+
{ "grader": "regex", "value": "runTest" },
|
|
55
|
+
{
|
|
56
|
+
"grader": "judge",
|
|
57
|
+
"rubric": "A correct answer wraps the test body in kotlinx-coroutines-test's runTest { }, which runs on a virtual clock that skips real delay time, so the suspend function's delay(2000) resolves instantly inside the test instead of the test actually pausing for two seconds; it does not rely on Thread.sleep or reducing the delay value in production code to make the test fast.",
|
|
58
|
+
"pass_criteria": [
|
|
59
|
+
"Names runTest { } as the mechanism that makes the test not actually wait for the delay.",
|
|
60
|
+
"Explains that runTest's virtual/skipped time is what avoids the real two-second wait, not a change to the delay duration itself.",
|
|
61
|
+
"Does not require changing the production delay(2000) call just to make the test faster."
|
|
62
|
+
],
|
|
63
|
+
"fail_criteria": [
|
|
64
|
+
"Recommends using Thread.sleep, a shortened delay in a test-only build variant, or otherwise altering production code's delay value to make the test run fast.",
|
|
65
|
+
"Recommends running the suspend function with runBlocking and simply accepting the real two-second wait as unavoidable."
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"calibration": {
|
|
70
|
+
"known_right": "Wrap the test body in `runTest { }` from `kotlinx-coroutines-test`. It runs the coroutine on a `TestScope` with a virtual clock, so when the code under test hits `delay(2000)`, the test doesn't actually pause for two real seconds -- the virtual clock just advances past it and the suspend function resumes immediately. Call the repository function directly inside `runTest { }`, e.g. `val result = repository.fetchWithCache()`, and assert on `result` right after; there's no need to touch the production `delay(2000)` call or introduce a test-only flag to shorten it, since `runTest` already makes the wait free without changing the code under test at all.",
|
|
71
|
+
"known_wrong": "Just run it under `runBlocking { }` like normal and accept that the test takes two seconds -- it's not a huge deal, and it's simpler than learning `runTest`'s virtual-time behavior. If it's really a problem, add a `testMode` flag to the repository that skips the `delay` call entirely when running under test, and set that flag from the test setup.",
|
|
72
|
+
"vague": "Use a coroutine test utility that lets the delay resolve fast instead of actually waiting.",
|
|
73
|
+
"subtle_wrong": "Use `runTest { }` for the test body, but also pass a shortened `delayMillis = 50` parameter into the repository function's signature for testing, since that guarantees the test is fast regardless of how `runTest` happens to handle the delay internally -- belt and suspenders."
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"agents": [
|
|
2
|
+
"agents": [],
|
|
3
|
+
"note": "pair removed — flow 335, post-merge (Wave 4 batch 3 django/fastapi/rust/java-kotlin-spring merged with Wave 4 batch 4/5/6): python-testing's own trigger-positive-1 ('Write pytest tests for the new widgets module') is outranked by flutter-dart/flutter-testing on the shared 'widget' token once the combined catalog (170 skills, 1006 triggers) is in place -- score 0.4736 vs 0.4848. Cause: checkSkillSelectedLeaveOneOut/checkSkillSelected scoring uses binary per-skill document frequency for IDF weighting, so any skill that merely CONTAINS the shared 'test'/'pytest'/'write' vocabulary lowers those tokens' corpus-wide weight regardless of wording -- not fixable by editing python's own or any single sibling pack's content without hollowing out real testing-skill vocabulary (tested directly: zero score movement from rewording django-testing/fastapi-testing). Demoted to experimental per the no-grandfathering rule, the owner's decision (decided-by: MrCipherSmith, owner, in chat, 2026-09-26), and the same precedent flow 317 applied to ts-js-node. Never touched python's own triggers or eval prompts. See the flow 335 journal for the full diagnosis and the honest-gate-scope follow-up (route/gate only among packs of detected/installed stacks, then re-gate python)."
|
|
3
4
|
}
|