## A Manager's Real Dilemma
A Manager's Real Dilemma
Anyone who has taken over a legacy project knows this feeling: the codebase has been running for five years, and the core modules don't have a single line of unit tests. Before picking up a requirement, the team holds a half-hour meeting to discuss "whether this logic can be touched," and changing one line of code requires half a day of manual regression testing in the test environment. Nobody dares to be the first to take action.
My small team was in exactly this state last year. Our core business system had roughly 30,000 lines of legacy code, with unit test coverage below 15%—and most of the existing tests were loose-assertion "going-through-the-motions" tests. The chain reaction was all too typical:
- Longer and longer delivery schedules: every change required extensive time reserved for manual regression testing
- Slow onboarding for new hires: without tests serving as a "behavioral specification," they could only read the code and rely on oral tradition from veteran employees
- Compounding interest on technical debt: the more afraid people were to change the code, the worse it got; the worse it got, the more afraid they became
Hire someone dedicated to writing tests? A small team doesn't have that budget. Have existing developers squeeze in time to write them? That fizzled out after two sprints. Until we decided to seriously give it a try: use AI to batch-generate unit tests and bring up coverage of the legacy code.
What AI Can Actually Do Here
Let's set expectations straight first: AI cannot "guarantee quality" for you, but it can pave the most tedious stretch of road from 0 to 60 points. Specifically, it handles four things:
1. Reading code and understanding logic. Having a new hire read 30,000 lines of code takes a month; AI can produce a summary of a module's responsibilities, dependency relationships, and boundary conditions within minutes. That alone is valuable—many legacy codebases are so old that even their original authors can't explain them anymore.
2. Generating test skeletons and cases. Happy paths, boundary values, exception branches, empty inputs—AI will proactively enumerate scenarios you might not think of and generate ready-to-run test code.
3. Explaining "what this code actually does." For undocumented legacy functions, the test cases AI generates are themselves an executable behavioral description. If the tests pass, it means AI's understanding is correct.
4. Iterative collaboration on revisions. Don't panic when tests fail—paste the error back, and AI will determine whether the test is wrong or the code itself has a hidden bug. The latter is a bonus: this time we caught three boundary-condition bugs that had been lurking for years.
Our Implementation Process (Directly Reusable)
As a manager, what I care about isn't how magical a particular tool is, but whether the process can be standardized and the risks controlled. The process we ultimately got working has five steps:
Step 1: Define the scope. Don't tackle the entire repository. Select the top 20% of core modules based on two dimensions: "change frequency × incident history." We chose two modules: order amount calculation and inventory deduction.
Step 2: Have AI first understand the code, then generate tests. Dumping an entire file to AI in one go and asking it to "write tests" works far worse than splitting it into two steps: first have it output its understanding of the code and a test plan, manually confirm it hasn't gone off track, then have it write the specific test cases. This manual confirmation step is the key risk-control point—if AI's misunderstanding of legacy code gets baked directly into tests, you end up with fake tests that "look like coverage but actually validate wrong behavior."
Step 3: Run the tests and categorize failures. Handle failed cases in three categories: AI misunderstood the code (revise the tests), test environment issues (fix the mocks), or the code has a real bug (file an issue—don't casually change production logic).
Step 4: Human review and merge. All test code goes through the normal code review process. AI-generated does not mean exempt from inspection, especially assertion strength—tests with assertions that are too loose are negative assets.
Step 5: Make it the norm. From then on, every MR touching legacy code is required to include AI-generated tests for the new changes, so the coverage debt gets paid down gradually, rather than another one-off "campaign-style cram session."
A Reusable Prompt Template
This is the template our team finalized after three internal iterations. It works with any mainstream LLM API:
你是一位资深测试工程师,请为下面的存量代码生成单元测试。
【背景信息】
- 项目语言/框架:{例如 Java 8 + JUnit 5 + Mockito}
- 该模块的业务职责:{一两句话描述,帮助 AI 校准理解}
- 运行环境限制:{例如 无数据库依赖,需 mock 外部服务}
【请按以下步骤输出】
1. 先用不超过 5 条要点总结你对这段代码行为的理解,
包括关键分支和边界条件,供我确认;
2. 列出测试计划:每个用例一行,标注
[正常路径] / [边界值] / [异常分支] / [疑似代码隐患];
3. 等我确认后,再生成完整可运行的测试代码。
【要求】
- 每个用例必须有明确的断言,禁止只调用不校验;
- 标注 [疑似代码隐患] 的用例单独说明理由,不要自行修改被测代码;
- mock 只用于外部依赖,不要 mock 被测对象内部逻辑。
【待测代码】
{粘贴目标函数或类}The core design of the template is forced step-by-step execution: confirm the understanding first, then generate code, and have AI flag "suspected issues" separately rather than silently working around them. These two details significantly reduce the production of fake tests.
Before and After: Numbers and Feel
No made-up pretty numbers—just the facts we measured ourselves:
| Dimension | Before Using AI | After AI Assistance |
|---|---|---|
| Coverage of the two core modules | ~15% | Raised to 70%+ |
| Adding tests for a medium-complexity function | Half a day on average, often procrastinated | Human effort compressed to 30–40 minutes (mostly review) |
| Psychological cost of modifying core modules | Meetings to discuss "can we touch this" | Tests provide a safety net; schedule normally |
| Unexpected bonus | — | Found 3 boundary-condition bugs |
What matters more is the change in team collaboration. Tests used to be an "extra burden"; now AI writes the first draft and humans review, and tests have become the entry point for new hires to understand legacy code—new hires reviewing AI-generated tests get up to speed much faster than reading raw code.
Three Risk Points Managers Must Watch
Finally, a few honest words for peers:
- Beware of fake coverage. Pretty coverage numbers don't mean safety. Focus your reviews on assertion quality—a single
assertNotNullinspires no confidence whatsoever. - AI's misunderstandings can solidify into a "wrong behavioral baseline." The step-by-step confirmation process isn't optional—it's mandatory.
- Don't let the team develop a dependency of "we have AI, so we don't need to understand testing." AI produces a first draft; the judgment for test design must stay within the team.
On tooling costs: mainstream LLM APIs all support this kind of code task, but prices and effectiveness vary considerably between models. I recommend doing a small-scale comparison on a few modules before running batch jobs; refer to each platform's official pricing page for specific costs.
Legacy test debt used to be the kind of debt you "knew you should repay but never got scheduled." Now AI has pushed the cost of repayment down to a range the team can afford—this may be the most cost-effective technical investment a small team can make this year.
If you want to start building your own AI-assisted development workflow, you can first register for a unified model API service and try running the prompt template above directly: https://api.thistoken.ai/register
---
Every example in this post runs with a single API key — get yours at https://api.thistoken.ai/register and start in minutes.
Ready to try Token.AI?
Create a project-level API Key, enable channels in the console, and configure routing, budgets, and audit logs.
注册 ThisToken.AI 并获取 API Key