与 AI 一起开始 AWS 开发 ― 通过 Q Developer 实现持续质量保证
Back to Top为了覆盖更广泛的受众,这篇文章已从日语翻译而来。
您可以在这里找到原始版本。
引言
#在上次中,体验了从规范到实现及测试生成的流程,并确认了 AI 如何支持软件开发。
本次(Day 3)作为延续,将聚焦于质量保证。
1. 看哪些方面 ― 质量视角盘点
#首先整理“在评审中要看什么”。
这也与 Q Developer 自动检查的项目有关。
| 关注点 | 检查项 | 目的 |
|---|---|---|
| 异常处理 | 异常吞没与重新抛出策略一致性 | 确保故障可分析性 |
| 命名规范 | 类名、变量名、目录结构一致性 | 降低阅读成本 |
| 依赖关系 | 是否存在循环依赖与分层违规 | 保证结构健全 |
| 日志设计 | 粒度、关联 ID、审计性 | 提高运维可追溯性 |
| 测试意图 | 边界条件与 Oracle 存在性 | 保证有效性与覆盖性 |
2. 使用 Q Developer 进行评审
#当向 AI 请求代码审查时,可以使用如下命令开始。
示例使用上次创建的 ToDo 应用。
启动 Q Developer。
# 启动对话模式
q
将评审视角归类到评审类别中,然后以类别为单位向 Q Developer 下达指令。
| 评审视角 | 评审类别 | 说明 |
|---|---|---|
| 异常处理 | 设计/可读性 | 异常策略一致性及异常传播处理属于设计范畴 |
| 命名规范 | 可读性 | 命名不一致/职责不符作为可读性问题指出 |
| 依赖关系 | 设计 | 分层违规/循环依赖等架构问题 |
| 日志设计 | 可读性/设计 | 日志颗粒度/关联 ID 属于设计及运维设计视角 |
| 测试意图 | 设计/质量(测试质量) | 对 AI 而言,“测试的妥当性”被视为设计/质量问题 |
另外,虽然上述表格中未列出,但安全性作为全局横向的重要视角,会被追加到 Q Developer 的指令中。
在启动后的提示符中输入以下内容。
※若出现工具执行建议,若仅允许本会话中运行请选择 y,若以后也持续允许请选择 t。
请审查 main.py 和 test_api.py 的代码。
请从安全性、可读性、设计角度进行分类指摘,并给出修正建议。
响应:
🛠️ Using tool: fs_read (trusted)
⋮
● Reading file: /home/ubuntu/todo-fastapi/main.py, all lines
✓ Successfully read 1684 bytes from /home/ubuntu/todo-fastapi/main.py
⋮
● Completed in 0.0s
🛠️ Using tool: fs_read (trusted)
⋮
● Reading file: /home/ubuntu/todo-fastapi/test_api.py, all lines
✓ Successfully read 3155 bytes from /home/ubuntu/todo-fastapi/test_api.py
⋮
● Completed in 0.0s
> ## 代码审查结果
### 🔒 安全性问题
main.py:
1. 没有输入值限制
python
# 问题: title/description 没有长度限制
title: str # 可能的 DoS 攻击
2. 没有速率限制
python
# 问题: API 调用无任何限制
@app.post("/todos") # 可能受到大量请求
3. 未设置 CORS
python
# 问题: 未进行跨域控制
app = FastAPI() # 未设置 CORS
test_api.py:
4. 硬编码的 URL
python
BASE_URL = "http://localhost:8000" # 建议放入配置文件
### 📖 可读性问题
main.py:
1. 全局变量
python
# 问题: 全局状态
todos = []
todo_id_counter = 1
2. 魔法数字
python
# 问题: 端口号硬编码
uvicorn.run(app, host="0.0.0.0", port=8000)
test_api.py:
3. 重复代码
python
# 问题: 相同模式重复
print(f"Create Todo: {response.status_code}")
print(json.dumps(response.json(), indent=2))
### 🏗️ 设计问题
main.py:
1. 违反单一职责原则
python
# 问题: 业务逻辑与 API 层混在
def create_todo(todo: TodoCreate):
global todo_id_counter # 数据操作出现在 API 层
2. 线程安全性
python
# 问题: 存在竞态条件风险
todo_id_counter += 1 # 非原子操作
test_api.py:
3. 测试缺乏独立性
python
# 问题: 测试之间存在依赖
todo_id = test_create_todo() # 依赖上一个测试结果
## 🔧 修正建议
### 安全性改进
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/ubuntu/todo-fastapi/main_improved.py
+ 1: from fastapi import FastAPI, HTTPException
+ 2: from fastapi.middleware.cors import CORSMiddleware
+ 3: from pydantic import BaseModel, Field, validator
+ 4: from typing import List, Optional
+ 5: from datetime import datetime, timezone
~~~(省略)~~~
+ 84: @app.delete("/todos/{todo_id}", status_code=204)
+ 85: def delete_todo(todo_id: int = Field(..., gt=0)):
+ 86: if not repo.delete(todo_id):
+ 87: raise HTTPException(status_code=404, detail="Todo not found")
+ 88:
+ 89: if __name__ == "__main__":
+ 90: import uvicorn
+ 91: uvicorn.run(app, host="127.0.0.1", port=8000)
⋮
↳ Purpose: Create improved main.py with security enhancements
Creating: /home/ubuntu/todo-fastapi/main_improved.py
⋮
● Completed in 0.1s
> ### 测试改进
🛠️ Using tool: fs_write (trusted)
⋮
● Path: /home/ubuntu/todo-fastapi/test_improved.py
+ 1: import requests
+ 2: import json
+ 3: from datetime import datetime, timedelta
+ 4: from typing import Dict, Any
+ 5:
~~~(省略)~~~
+ 121: # 清理
+ 122: self.cleanup()
+ 123: self.test_get_todos()
+ 124:
+ 125: if __name__ == "__main__":
+ 126: tester = TodoAPITester()
+ 127: tester.run_all_tests()
⋮
↳ Purpose: Create improved test file with better structure
Creating: /home/ubuntu/todo-fastapi/test_improved.py
⋮
● Completed in 0.3s
> ## 📋 改进要点汇总
### 安全性改进
• **输入值限制**:通过 Field() 设置 min_length/max_length
• **CORS 设置**:仅允许特定源
• **线程安全**:使用 threading.Lock 进行互斥控制
• **绑定地址**:更改为 127.0.0.1(限制外部访问)
### 可读性改进
• **职责分离**:通过 TodoRepository 类分离数据操作
• **配置外部化**:通过环境变量或类初始化管理配置
• **消除重复**:在测试类中将公共处理方法化
### 设计改进
• **依赖注入**:采用仓库模式
• **测试独立性**:添加清理功能
• **错误处理**:使用适当的 HTTP 状态码
• **类型安全性**:加强 Field() 验证
改进版已具备接近生产环境的质量。
如指示,AI 审查结果以如下方式进行分类显示。
| 类别 | 示例 | 应对策略 |
|---|---|---|
| 安全性 | 未处理的异常、硬编码的认证信息 | 优先处理 |
| 可读性 | 命名不一致、注释缺失 | 考虑处理 |
| 设计 | 类臃肿、循环依赖 | 需团队内达成共识 |
由此可见,可与 AI 进行评审。
但 AI 的自动修正建议(工具执行)仅为**“建议”级别**。
务必由人工进行审批。
3. 使用度量“可视化”
#评审是定性活动,但 Q Developer 也可实现基于数值指标的定量管理。
这里将从更实务的角度详细说明为什么需要度量,以及如何运用度量。
3.1 度量的作用是什么?
#度量是用于以“数值”客观评估代码质量和开发流程的工具。消除主观的“好像还行”“估计没问题”,实现以下三点:
- 现状可视化:可定量把握需改善的部分
- 改进效果测量:通过与上次对比判断是否有所改善
- 基准共享:团队全员可在相同尺度上进行讨论
尤其在与 AI 共存的开发中,生成代码质量存在波动,因此度量对于“质量稳定化”至关重要。
3.2 主要度量指标详情
#在此整理评估代码质量时特别重要的度量指标。这些不仅仅是“数字”,还是质量改进优先级划分和团队达成共识的关键指标。理解度量的目的和含义,可使评审结果更具实务价值。
| 指标 | 目的 | 参考值 | 详细说明 |
|---|---|---|---|
| 静态分析得分 | 语法和结构健全性 | ≥90分 | 综合评估循环依赖、未使用代码、异常处理、安全性问题等。量化为分数有助于确定改进优先级。 |
| 测试覆盖率 | 功能覆盖率 | ≥80% | 不仅查看数值,更要确认哪些函数未被覆盖。关键逻辑应达到100%。 |
| 注释率 | 可读性与文档性 | 10~20% | 注释多并非越好,关键在于留下代码意图和设计决策的“质量”。 |
| 命名一致率 | 遵循质量标准程度 | ≥95% | 函数和变量命名模式是否一致,可减少评审时间。 |
| 变更影响深度 | 重构易维护性 | 越低越好 | 测量更改对其他模块的影响程度。深度高意味着代码维护成本高。 |
3.3 实际测量度量指标
#由于上次创建的 todo-fastapi/ 模块结构较小,首先以测试覆盖率为例。我们将使用 pytest 进行覆盖率测量。
指令:
python main.py
pytest --cov=. --cov-report=xml
响应:
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command: python main.py &
⋮
↳ Purpose: Start FastAPI server in background
⋮
● Completed in 0.1s
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
sleep 3 && pytest --cov=. --cov-report=xml
⋮
↳ Purpose: Wait for server to start and run pytest with coverage
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.1, pluggy-1.6.0
rootdir: /home/ubuntu/todo-fastapi
plugins: anyio-4.11.0, cov-7.0.0
collected 8 items
test_api.py ..E..... [100%]
==================================== ERRORS ====================================
______________________ ERROR at setup of test_delete_todo ______________________
file /home/ubuntu/todo-fastapi/test_api.py, line 24
def test_delete_todo(todo_id):
~~~(省略)~~~
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
ps aux | grep "python main.py"
⋮
↳ Purpose: Check if server is running
ubuntu 222074 0.2 0.6 231596 49596 pts/7 Sl+ 21:55 0:00 python main.py
ubuntu 224348 0.0 0.0 4756 3248 pts/5 S+ 22:02 0:00 bash -c ps aux | grep "python main.py"
ubuntu 224350 0.0 0.0 4100 1992 pts/5 S+ 22:02 0:00 grep python main.py
⋮
● Completed in 0.28s
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
curl -s http://localhost:8000/todos || echo "Server not responding"
⋮
↳ Purpose: Test server connectivity
[{"id":1,"title":"Test Todo","description":"Test description","priority":"high","due_date":"2025-11-17T21:55:47.625131","created_at":"2025-11-16T21:55:47.632922"},{"id":2,"title":"Minimal Todo","description":null,"priority":"low","due_date":null,"created_at":"2025-11-16T21:55:47.654090"},{"id":5,"title":"Test Todo","description":"Test description","priority":"high","due_date":"2025-11-17T22:02:54.546964","created_at":"2025-11-16T22:02:54.550647"},{"id":6,"title":"Minimal Todo","description":null,"priority":"low","due_date":null,"created_at":"2025-11-16T22:02:54.575022"}]
⋮
● Completed in 0.16s
> ✅ 服务器已启动,测试已执行
结果:
• **服务器**:正常运行中(PID 222074)
• **XML 报告**:Coverage XML 写入至 coverage.xml - 成功
• **测试**:7 个成功,1 个错误(fixture 问题)
• **API**:正常工作(存在 Todo 数据)
🛠️ Using tool: execute_bash (trusted)
⋮
● I will run the following shell command:
pkill -f "python main.py"
⋮
↳ Purpose: Stop the server
⋮
● Completed in 0.15s
> 服务器已停止。XML 覆盖率报告已正常生成。
这样就生成了 coverage.xml。
3.4 让 Q Developer 分析 coverage.xml(对话)
#在对话模式中,可按如下方式请求:
读取 coverage.xml,
・各函数的覆盖率
・未测试部分列表
・优先添加测试用例的建议
・复杂度高的函数排名
请输出。
Q Developer 会调用内部工具(fs_read / analyze_code),并返回以下内容:
- 未覆盖的函数
- 条件分支测试不足
- 异常情况和边界测试缺失
- 测试添加的具体示例(通常还会给出参数示例)
响应:
🛠️ Using tool: fs_read (trusted)
⋮
● Reading file: /home/ubuntu/todo-fastapi/coverage.xml, all lines
✓ Successfully read 4891 bytes from /home/ubuntu/todo-fastapi/coverage.xml
⋮
● Completed in 0.0s
~~~(省略)~~~
问题:尽管服务器已启动,但 main.py 的覆盖率仍为 0%。这是因为测试仅发送了 HTTP 请求,pytest 并未直接执行 main.py 的代码。可通过使用 TestClient 来解决该问题。
看来覆盖率无法正确收集。 Q Developer 不仅会说“做不到”,还会给出解决方案。
按照 Q Developer 的建议,请求改用 TestClient。
指令:
请修改为使用 TestClient
响应:
🛠️ Using tool: fs_write
⋮
● Path: test_api.py
- 0 : import requests
+ 0: from fastapi.testclient import TestClient
1, 1: import pytest
2, 2: from datetime import datetime
+ 3: from main import app
3, 4:
- 4 : BASE_URL = "http://localhost:8000"
+ 5: client = TestClient(app)
5, 6:
6, 7: def test_create_todo():
7: todo_data = {
8: "title": "Test Todo",
9: "description": "Test description",
10: "priority": "high",
11: "due_date": "2025-11-17T12:00:00"
12: }
~~~(省略)~~~
Coverage XML written to file coverage.xml
========================= 8 passed, 1 warning in 1.17s =========================
⋮
● Completed in 1.557s
> ✅ 使用 TestClient 的测试已成功!
结果:
• **httpx**:安装完成
• **测试**:全部 8 项成功
• **XML 报告**:Coverage XML 写入到 coverage.xml - 成功
• **执行时间**:1.17 秒
• **警告**:仅有 Pydantic V1 validator 使用警告
通过使用 TestClient,可在无需启动服务器的情况下执行 API 测试,并且可以测量 main.py 的代码覆盖率。
已收集到覆盖率数据,于是再次按如下方式请求:
读取 coverage.xml,
・各函数的覆盖率
・未测试部分列表
・优先添加测试用例的建议
・复杂度高的函数排名
请输出。
响应:
🛠️ Using tool: fs_read (trusted)
⋮
● Reading file: /home/ubuntu/todo-fastapi/coverage.xml, all lines
✓ Successfully read 4181 bytes from /home/ubuntu/todo-fastapi/coverage.xml
⋮
● Completed in 0.0s
> ## 覆盖率分析结果
### 📊 全局覆盖率
• **总体覆盖率**:97.87% (92/94 行) - 大幅改善!
• **main.py**:95.83% (46/48 行)
• **test_api.py**:100% (46/46 行)
### 🔍 各函数覆盖率
#### main.py (95.83% 覆盖)
• create_todo()(第 38-48 行):✅ 完全测试覆盖
• get_todos()(第 49-51 行):✅ 完全测试覆盖
• delete_todo()(第 57-63 行):✅ 完全测试覆盖
• validate_due_date()(第 24-28 行):✅ 完全测试覆盖
#### test_api.py (100% 覆盖)
• 所有测试函数均已执行
### ❌ 未测试部分列表
#### main.py(仅 2 行未测试)
1. 第 66 行:import uvicorn
2. 第 67 行:uvicorn.run(app, host="0.0.0.0", port=8000
这些位于 if __name__ == "__main__" 块内的服务器启动代码,在测试时不会执行。
### 🎯 建议优先添加的测试用例
#### 低优先级(已有高覆盖率)
1. 添加边界情况测试
• 空字符串标题
• 极端超长标题/说明
• 边界值测试
2. 错误处理详细测试
• 非法 JSON 格式
• 类型转换错误
3. 性能测试
• 大量数据下的性能验证
### 📈 高复杂度函数排行
#### 第 1 名:create_todo()(main.py 第 38-48 行)
• **复杂度**:高
• **覆盖率**:✅ 100%
• **原因**:全局变量操作、对象创建、列表操作、计数器管理
• **行数**:11 行
#### 第 2 名:delete_todo()(main.py 第 57-63 行)
• **复杂度**:中高
• **覆盖率**:✅ 100%
• **原因**:循环处理、条件分支、异常处理、列表操作
• **行数**:7 行
#### 第 3 名:validate_due_date()(main.py 第 24-28 行)
• **复杂度**:中
• **覆盖率**:✅ 100%
• **原因**:条件分支、日期时间比较、异常抛出
• **行数**:5 行
#### 第 4 名:get_todos()(main.py 第 49-51 行)
• **复杂度**:低
• **覆盖率**:✅ 100%
• **原因**:简单列表返回
• **行数**:3 行
### 🎉 成果
引入 TestClient 带来显著改进:
• **覆盖率**:35.96% → 97.87% (+61.91%)
• **main.py**:0% → 95.83% (+95.83%)
• **全部测试**:成功(8/8)
• **执行时间**:加速(无需启动服务器)
### 💡 推荐行动
1. 维持现状 - 覆盖率已优秀
2. 提升代码质量
• 迁移到 Pydantic V2(消除警告)
• 添加类型提示
3. 添加集成测试
• 多操作组合测试
4. 完善文档
• 编写 API 规范文档
结论:通过引入 TestClient,几乎实现了完美的测试覆盖率。剩下的 2 行属于运行时代码,实际上可视为 100% 覆盖。
顺利收集到了覆盖率数据。
3.5 如何利用度量指标进行改进
#度量指标的目的不在于“查看数值”本身。相反,度量是指示**“从哪里开始改进最有效”**的“改进导航”。正确理解数值所代表的含义,并将其与下一步行动相连,可加速质量改进循环。
以下将更具体地说明如何从典型度量指标出发,将其转化为改进措施。
为改进,可按如下方式使用:
-
针对低覆盖率函数 → 编写补充测试
覆盖率低意味着缺少对行为进行验证的测试。特别是业务逻辑或校验处理等易出错部分,应优先添加测试。
示例:create_todo() 覆盖率为 0% → 添加 POST /todos 的正常及异常测试 -
针对高复杂度函数 → 首先进行拆分(重构)
高复杂度函数不易阅读,容易引入错误,也不易测试。
通过拆分职责或将公共处理方法化,可提升可读性,进而使测试更易编写。
示例:create_todo() 同时承担状态管理、校验和注册处理 → 按职责拆分成多个函数 -
命名不一致 → 向 AI 提供代码规范,统一命名
命名规范不一致会增加理解成本,并延长评审时间。
如将命名规范(例如 snake_case / camelCase、缩写规则)提供给 Q Developer,即可自动指出不一致命名。
此外,AI 还能根据项目提供自动命名修改建议。 -
针对变更影响深度高的部分 → 考虑重新设计
“修改此函数会破坏其他 10 个文件”的现象意味着可维护性差。
可通过整理依赖关系、拆分职责、明确架构层次等方式,有意缩小影响范围。
此外,度量可让改进结果“以数字说明”,使得向团队解释“为什么需要改进”变得更容易。定量化使改进要点清晰,团队内达成共识亦更便捷。
如此一来,可在“定量”评估代码覆盖情况的同时,维持质量,并持续扩展与验证功能。
4. 度量驱动的混合评审运营模型
#这是一个结合 AI 和人类各自优势,以定量度量为核心运转质量保证循环的运营模型。传统评审依赖个人经验或直觉,而引入度量后可实现“视角统一”“效果测量”“改进优先级划分”,并借助 AI,实现可持续的质量保证。
AI 审查在覆盖率与速度上具备优势,而度量则作为改进指南。最终判断由人完成,AI × 度量 × 人类判断形成具有可重复性与可持续性的质量保证。
总结
#本次最大成果在于通过度量可“定量”评估质量。由此,以往依赖感性与个人经验的评审活动,演进为基于数字的客观改进循环。
尤其在以下方面取得重大进展:
- 通过静态分析得分、覆盖率、复杂度、命名一致率等指标,评审的“疏漏”得以可视化
- 基于数值可判断“应优先修复何处”,提升了改进活动效率
- 将 AI 审查建议与人工判断结合,构建了可持续运转的质量改进流程
由此减少了评审精度的差异,质量改进的 PDCA 基于数据闭环。
希望能对各位的生成式 AI 应用有所帮助。
