Skip to content

Commit 3ca2cea

Browse files
Merge branch 'main' into fix/generate-tests-trigger-on-merge
2 parents 5af9be2 + d8f1b27 commit 3ca2cea

1 file changed

Lines changed: 34 additions & 21 deletions

File tree

.github/scripts/generate_tests.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,46 +40,60 @@ def file_name_without_ext(path: str) -> str:
4040
return os.path.basename(path).replace(".kt", "")
4141

4242

43-
def build_prompt(file_path: str, content: str, package_name: str) -> str:
44-
class_name = file_name_without_ext(file_path)
45-
return f"""You are an expert Kotlin developer specializing in unit testing for Kotlin Multiplatform (KMP) projects.
43+
# Static system prompt shared across all files in a batch.
44+
# Marked with cache_control so Claude caches it after the first call,
45+
# saving ~70% on token costs when processing multiple files.
46+
_SYSTEM_PROMPT = """\
47+
You are an expert Kotlin developer specializing in unit testing for Kotlin Multiplatform (KMP) projects.
4648
4749
## Project context
4850
- **CraftD** is a Server Driven UI library for Android/KMP.
4951
- The server returns a list of `SimpleProperties` (key + value as `JsonElement`).
5052
- The lib renders native components dynamically via `CraftDBuilder`.
5153
- Stack: Kotlin, JUnit4, MockK, kotlinx.serialization, Jetpack Compose.
5254
53-
## Your task
54-
Generate comprehensive unit tests for the Kotlin source file below.
55-
56-
## Requirements
55+
## Requirements (apply to every file)
5756
- Framework: **JUnit4** (`@RunWith(JUnit4::class)`) + **MockK** (`io.mockk.*`)
58-
- Package: `{package_name}`
59-
- Test class name: `{class_name}Test`
6057
- Test method style: backtick notation — e.g. `` `given null JsonElement when convertToElement then returns null`() ``
6158
- **Data classes**: test construction with all params, default values, `copy()`, `equals`/`hashCode`.
6259
- **Extension functions with JsonElement**: test null input, valid JSON deserialization, malformed/wrong-type JSON (expect `null` return).
6360
- **DiffUtil callbacks**: test `areItemsTheSame` (same key, different key) and `areContentsTheSame` (equal value, different value, `AbstractMap` comparison edge case).
6461
- **Enums**: verify all enum constant names exist using `enumValueOf`.
6562
- **Mapper functions** (`toSimpleProperties`, `toListSimpleProperties`): test with sample data, empty list, and null-value fields.
6663
- Do **not** include explanations or markdown fences.
67-
- Output **only** the complete Kotlin test file, starting with `package {package_name}`.
68-
69-
## Source file
70-
Path: `{file_path}`
71-
72-
```kotlin
73-
{content}
74-
```
64+
- Output **only** the complete Kotlin test file, starting with `package <package>`.\
7565
"""
7666

7767

78-
def call_claude(client: anthropic.Anthropic, prompt: str) -> str:
68+
def call_claude(
69+
client: anthropic.Anthropic,
70+
file_path: str,
71+
content: str,
72+
package_name: str,
73+
) -> str:
74+
class_name = file_name_without_ext(file_path)
7975
message = client.messages.create(
8076
model="claude-haiku-4-5-20251001",
8177
max_tokens=4096,
82-
messages=[{"role": "user", "content": prompt}],
78+
system=[
79+
{
80+
"type": "text",
81+
"text": _SYSTEM_PROMPT,
82+
"cache_control": {"type": "ephemeral"},
83+
}
84+
],
85+
messages=[
86+
{
87+
"role": "user",
88+
"content": (
89+
f"Generate unit tests for the Kotlin source file below.\n\n"
90+
f"Package: `{package_name}`\n"
91+
f"Test class name: `{class_name}Test`\n\n"
92+
f"## Source file\nPath: `{file_path}`\n\n"
93+
f"```kotlin\n{content}\n```"
94+
),
95+
}
96+
],
8397
)
8498
return message.content[0].text
8599

@@ -151,8 +165,7 @@ def main() -> None:
151165
continue
152166

153167
try:
154-
prompt = build_prompt(file_path, content, package_name)
155-
test_content = call_claude(client, prompt)
168+
test_content = call_claude(client, file_path, content, package_name)
156169

157170
os.makedirs(os.path.dirname(test_path), exist_ok=True)
158171
with open(test_path, "w", encoding="utf-8") as f:

0 commit comments

Comments
 (0)