初始化文档
This commit is contained in:
77
04 - Quality & Review/4.1 自动化测试规范.md
Normal file
77
04 - Quality & Review/4.1 自动化测试规范.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# **4.1 自动化测试规范**
|
||||
|
||||
自动化测试是保障系统重构信心、防止线上代码回归(Regression)的唯一有效手段。本规范旨在指导研发团队编写**高优、稳定、可维护**的测试代码,坚决抵制“为了追求覆盖率而写无意义断言”的形式主义。
|
||||
|
||||
### **4.1.1 测试分层策略 (Testing Pyramid)**
|
||||
|
||||
团队的自动化测试必须遵循经典的“测试金字塔”原则,明确不同测试的边界与职责:
|
||||
|
||||
* **单元测试 (Unit Tests \- 占比 70%)**:运行极快,完全隔离。仅测试单一函数/方法的内部逻辑。**绝对禁止**任何真实的网络 I/O 和数据库连接。
|
||||
* **集成测试 (Integration Tests \- 占比 20%)**:验证多个内部组件能否协同工作。**允许**连接真实的测试数据库或本地 Redis,但**禁止**调用外部第三方系统(如真实的支付网关或微信 API)。
|
||||
* **接口/端到端自动化测试 (API/E2E Tests \- 占比 10%)**:从用户视角出发,把整个系统当做黑盒,通过 HTTP 协议发起真实请求,验证最终的 Response 和副作用。
|
||||
|
||||
### **4.1.2 单元测试编写规范与覆盖率要求**
|
||||
|
||||
**核心原则:Arrange \- Act \- Assert (3A 模式)**
|
||||
|
||||
* **测试结构**:每一个测试用例必须清晰地分为三部分:
|
||||
1. Arrange (准备):初始化测试数据和 Mock 对象。
|
||||
2. Act (执行):调用被测函数。
|
||||
3. Assert (断言):验证返回值或内部方法调用的状态。
|
||||
* **命名规范**:测试函数名必须能清晰表达测试意图。格式推荐:test\_\<被测方法\>\_\<测试场景\>\_\<预期结果\>。
|
||||
* *✅ 正确示例:test\_calculate\_discount\_with\_vip\_user\_returns\_half\_price()*
|
||||
* **覆盖率要求 (不搞一刀切)**:
|
||||
* **核心业务领域层 (Domain/Service)**:核心算法、金额计算、状态流转的单元测试行覆盖率**必须 \>= 80%**。
|
||||
* **边缘或纯框架粘合层 (Controller/View)**:不做硬性单元测试覆盖率要求,应交由“接口自动化测试”来覆盖。
|
||||
* *红线:严禁为了凑覆盖率去测试框架自带的 Getter/Setter 或基础的 ORM 查询。*
|
||||
|
||||
### **4.1.3 Mock 数据与测试对象构造原则**
|
||||
|
||||
脆弱的测试往往来源于糟糕的测试数据构造方式。
|
||||
|
||||
* **坚决弃用手动组装大字典**:严禁在测试代码中写几百行的字典或 JSON 来伪造数据库对象。这会导致测试代码极难维护。
|
||||
* **引入工厂模式 (Factory)**:强制使用 factory\_boy (Python) 或类似工具(如 Java 的 DataFaker)来生成测试对象实体。
|
||||
\# ✅ 正确示范:使用 Factory 快速生成具有合法默认值的测试对象
|
||||
user \= UserFactory(role='admin', is\_active=True)
|
||||
order \= OrderFactory(user=user, amount=100)
|
||||
|
||||
* **公共数据复用 (Fixtures)**:跨测试用例复用的基础数据(如登录凭证、基础配置),必须统一定义在 conftest.py(针对 Pytest 框架)中,通过依赖注入提供给测试用例。
|
||||
* **Mock 的外部边界红线**:
|
||||
* **必须 Mock**:所有跨出当前服务进程的调用(如请求 AWS、阿里云、第三方大模型、其它微服务)在单测和集成测试中**必须被拦截并 Mock**。
|
||||
* **禁止滥用 Mock**:不要在集成测试中去 Mock 系统内部的私有方法。Mock 应该发生在系统边界处。
|
||||
|
||||
### **4.1.4 集成测试规范 (Integration Testing)**
|
||||
|
||||
集成测试的核心目的是验证系统组件与外部基础设施(特别是数据库)的交互是否正确。
|
||||
|
||||
* **数据库环境清理 (极其重要)**:
|
||||
* 集成测试必须连接到独立的测试数据库(如本地内存 DB,或由 CI 动态拉起的 Docker DB)。
|
||||
* **红线:严禁测试用例之间产生数据污染。** 每个测试用例执行完毕后,必须**触发事务回滚 (Transaction Rollback)** 或清空相关表。在 Django/pytest 体系中,强制使用 @pytest.mark.django\_db 确保测试在事务中运行。
|
||||
* **验证副作用**:集成测试不仅要验证函数的 return 值,更要验证数据库的真实副作用(Side Effects)。
|
||||
def test\_cancel\_order\_updates\_db\_status():
|
||||
order \= OrderFactory(status='PENDING')
|
||||
|
||||
\# Act
|
||||
cancel\_order\_service(order.id)
|
||||
|
||||
\# Assert:必须重新从真实数据库查出数据,验证更新是否落盘
|
||||
order.refresh\_from\_db()
|
||||
assert order.status \== 'CANCELLED'
|
||||
|
||||
### **4.1.5 接口自动化测试要求 (API Testing)**
|
||||
|
||||
接口自动化测试用于替代绝大部分的“手动 Postman 联调”,它是持续交付 (CI/CD) 的最后一道质量门禁。
|
||||
|
||||
* **黑盒视角**:测试代码不需要知道内部是怎么实现的。仅通过框架的 APIClient 或 HTTP 客户端(如 httpx, RestAssured)发起请求。
|
||||
* **全链路验证**:不要仅仅测试单一接口的连通性,必须测试**核心业务链路 (Happy Path)**。
|
||||
* *示例场景:* 1\. 调用登录接口获取 Token \-\> 2\. 携带 Token 创建订单 \-\> 3\. 调用查询接口断言订单存在 \-\> 4\. 调用取消接口 \-\> 5\. 再次查询断言状态变更。
|
||||
* **契约断言 (Contract Assertion)**:
|
||||
* 必须断言 HTTP 状态码(如 200, 201, 400, 403)。
|
||||
* 必须断言外层统一响应结构(code, message)。
|
||||
* 必须断言核心业务数据字段的存在与类型,确保 API 向前兼容。
|
||||
|
||||
### **4.1.6 质量门禁与 CI/CD 强制执行**
|
||||
|
||||
* **本地提交前拦截**:推荐使用 Git pre-commit 钩子,在本地 Commit 前执行快速的单元测试。
|
||||
* **CI 自动化阻断**:任何合并到主干分支(如 main, develop)的 Pull Request/Merge Request,必须触发 CI 流水线。
|
||||
* 如果自动化测试失败(红灯),或者核心代码覆盖率跌破基准线,代码审查工具必须**硬性阻断**合并按钮,不允许任何特权绕过。
|
||||
92
04 - Quality & Review/4.2 代码审查规范.md
Normal file
92
04 - Quality & Review/4.2 代码审查规范.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# **4.2 代码审查 (Code Review) 规范**
|
||||
|
||||
代码审查(Code Review, 简称 CR)不仅仅是发现 Bug 的防线,更是**团队知识共享、架构共识对齐**的最重要途径。本规范旨在建立一套高效、客观、充满建设性的 CR 流程。
|
||||
|
||||
### **4.2.1 审查的触发时机与前置条件 (Prerequisites)**
|
||||
|
||||
为了不浪费审查者(Reviewer)的时间,提交者(Author)在发起合并请求(PR/MR)前,**必须满足以下前置条件(即质量门禁)**,否则 Reviewer 有权直接打回:
|
||||
|
||||
1. **自动化门禁通过 (绿灯状态)**:
|
||||
* 代码必须通过所有的 Linter 格式化检查(如 Ruff, ESLint)。
|
||||
* 必须通过所有的单元测试与核心自动化测试。**不要让人类去 Review 机器能检查出来的缩进和语法错误。**
|
||||
2. **提交规模限制 (Small PR)**:
|
||||
* 一个 PR 的逻辑代码变更行数建议**控制在 400 行以内**。超过 1000 行的“巨型 PR”极难审查,往往会流于形式("LGTM \- Looks Good To Me")。
|
||||
* 如果是大型需求,必须拆分为多个独立的小 PR 提交。
|
||||
3. **完成自我审查 (Self-Review)**:
|
||||
* 作者在指派 Reviewer 之前,必须先自己完整看一遍 Diff,清理掉调试代码(如 print(), console.log)、注释掉的废弃代码。
|
||||
4. **规范的 PR 描述**:
|
||||
* 必须清晰描述“修改了什么”、“为什么修改”、“如何测试”。
|
||||
|
||||
### **4.2.2 审查核心 Checklist (Review Dimensions)**
|
||||
|
||||
Reviewer 在审查时,应当自顶向下,先看架构,再看逻辑,最后看细节。严禁在没有看懂业务逻辑的情况下,只揪着变量命名不放。
|
||||
|
||||
#### **1\. 架构与设计 (Design & Architecture) \-\> *最高优先级***
|
||||
|
||||
* **分层边界**:是否出现了越界操作?(例如:在 Controller/View 层直接拼接了复杂的 SQL,或者在 Serializer 中写了极重的业务流转)。
|
||||
* **设计原则**:是否遵循了 DRY(不重复造轮子)原则?是否有过度设计?
|
||||
* **向后兼容性**:修改现有的 API 或数据库字段,是否会引发线上老版本 App 的崩溃?
|
||||
|
||||
#### **2\. 业务功能正确性 (Functional Correctness)**
|
||||
|
||||
* **需求契合**:代码是否真正解决了 PR 描述中的问题?
|
||||
* **边界条件**:空值、负数、极大值、并发场景下的数据状态是否被妥善处理?
|
||||
* **事务一致性**:涉及多个表的写入时,是否正确使用了数据库事务(如 @Transactional 或 transaction.atomic)?
|
||||
|
||||
#### **3\. 安全与性能隐患 (Security & Performance)**
|
||||
|
||||
* **安全漏洞**:是否存在 SQL 注入风险(直接拼接 SQL 字符串)、XSS/CSRF 风险?越权漏洞(没有校验 owner \== current\_user)?
|
||||
* **性能瓶颈**:是否存在潜在的 N+1 查询?是否在大循环中操作了数据库或发起外部网络请求?是否进行了会导致内存溢出的大列表全量加载?
|
||||
|
||||
#### **4\. 可测试性与健壮性 (Testability & Robustness)**
|
||||
|
||||
* **异常处理**:有没有吞噬异常(空的 except/catch)?是否抛出了合理的业务错误码,还是直接把系统底层报错扔给了前端?
|
||||
* **测试覆盖**:新增的核心逻辑是否包含了对应的单元测试?
|
||||
|
||||
### **4.2.3 基于变更类型的动态审查重点**
|
||||
|
||||
根据提交的代码类型,Reviewer 的关注点应当有所侧重:
|
||||
|
||||
* 🆕 **新功能 (Feature)**: 重点关注 **\[功能正确性\]** → **\[设计合理性/扩展性\]** → **\[代码质量\]**。
|
||||
* 🐛 **缺陷修复 (Bugfix)**: 重点关注 **\[问题根因是否找准\]** → **\[修复是否引入回归风险\]** → **\[是否补充了防回归测试\]**。
|
||||
* ♻️ **重构 (Refactor)**: 重点关注 **\[系统向后兼容性\]** → **\[设计是否得到改进\]** → **\[性能与测试保持\]**。(重构 PR 原则上不应包含新业务逻辑)。
|
||||
|
||||
### **4.2.4 Review 礼仪与沟通规范 (Etiquette)**
|
||||
|
||||
代码审查极其容易引发工程师之间的情绪对立。良好的沟通方式是 CR 顺利推行的润滑剂。
|
||||
|
||||
* **对事不对人**:
|
||||
* ❌ 错误表达:“*你这里写的完全不对,你为什么不用 Map?*”
|
||||
* ✅ 正确表达:“*这段逻辑如果改用 Map 结构,查找复杂度是不是可以从 O(n) 降到 O(1)?我们试一下如何?*”
|
||||
* **区分严重程度 (使用标签)**:
|
||||
* 建议在评论前加上标签,明确反馈的性质,避免作者过度恐慌或误解:
|
||||
* \[Blocker\] / \[Must-Fix\]:致命错误、安全漏洞、严重架构违规。**必须修改才能合并**。
|
||||
* \[Suggestion\] / \[Should-Fix\]:强烈的优化建议(如代码结构、性能)。建议修改。
|
||||
* \[Nit\] / \[Optional\]:细枝末节的挑刺(Nitpick,如命名规范、稍微优雅一点的写法)。作者可凭主观意愿决定是否修改,**不阻塞合并**。
|
||||
* \[Question\]:纯粹的疑问,希望能解释一下为什么这么写。
|
||||
* **提出问题,更要给出建议**:如果指出了一段代码很糟糕,请尽量提供一段伪代码或者文档链接作为优化参考。
|
||||
* **不要吝啬赞美**:如果看到一段非常优雅的实现、极其周全的测试,请直接在评论里留下 👍 或夸奖。正向反馈能极大提升团队技术氛围。
|
||||
|
||||
### **4.2.5 标准的 PR 描述与审查总结模板**
|
||||
|
||||
提交者发起 PR 或 Reviewer 完成一次重大审查时,应尽量使用以下结构化的 Markdown 模板:
|
||||
|
||||
\#\# 📋 变更摘要 (Summary)
|
||||
\* \*\*变更类型\*\*: \[🆕新功能 | 🐛缺陷修复 | ♻️重构 | ⚡性能优化\]
|
||||
\* \*\*关联 Ticket\*\*: \#Issue-123
|
||||
\* \*\*核心目的\*\*: 解决了订单并发退款时的状态不一致问题。
|
||||
|
||||
\#\# 🔍 核心变更点 (Key Changes)
|
||||
1\. 引入了 \`Redisson\` 分布式锁控制并发请求。
|
||||
2\. 重构了 \`RefundService\`,将第三方退款网关的调用抽离为了防腐层。
|
||||
3\. 数据库 \`order\` 表新增了 \`refund\_status\` 字段(已包含 Migration 脚本)。
|
||||
|
||||
\#\# ⚠️ 影响面与风险评估 (Impact & Risks)
|
||||
\* \*\*功能影响\*\*: 仅影响退款链路。
|
||||
\* \*\*兼容性\*\*: \*\*\[注意\]\*\* 接口 \`POST /api/v1/refund\` 新增了必填参数 \`reason\_code\`,需前端同步发版,暂不兼容旧版 App。
|
||||
\* \*\*性能风险\*\*: 引入了分布式锁,预期单个退款请求耗时增加 10ms,在接受范围内。
|
||||
|
||||
\#\# 🎯 自我检查 (Self Check)
|
||||
\- \[x\] 本地单测全部通过。
|
||||
\- \[x\] 没有遗留的 \`print\` 和注释掉的死代码。
|
||||
\- \[x\] 已补充对应的 OpenAPI 文档注解。
|
||||
72
04 - Quality & Review/4.3 安全编码规范.md
Normal file
72
04 - Quality & Review/4.3 安全编码规范.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# **4.3 安全编码规范 (防御性编程)**
|
||||
|
||||
防御性编程的核心思想是:**假设所有的外部输入都是恶意的,假设内部的依赖调用随时会失败**。安全漏洞一旦在生产环境被利用,对业务和公司声誉的打击往往是毁灭性的。
|
||||
|
||||
本规范规定了团队在日常编码中必须遵守的安全底线。
|
||||
|
||||
### **4.3.1 常见 Web 漏洞防护底线**
|
||||
|
||||
#### **1\. SQL 注入 (SQL Injection) 绝对防线**
|
||||
|
||||
* **红线**:**绝对禁止**使用字符串拼接(如 Python 的 f-string 或 %s,Java 的 \+)来构造 SQL 语句。
|
||||
* **规范**:
|
||||
* 默认必须使用框架提供的 ORM 工具(如 Django ORM, SQLAlchemy, MyBatis 动态标签)。
|
||||
* 如果极其特殊的复杂查询必须执行原生 SQL,**必须**使用参数化查询(Parameterized Queries),将变量作为参数安全传递给数据库驱动。
|
||||
|
||||
#### **2\. 跨站脚本攻击 (XSS \- Cross-Site Scripting) 防护**
|
||||
|
||||
* **输入校验**:在后端接口层(如 DRF Serializer 或 Pydantic)必须严格校验输入数据的格式与长度。
|
||||
* **输出转义**:
|
||||
* 现代前端框架(Vue/React)默认防范了 DOM 型 XSS,但如果后端需要渲染模板(如 Django Template),**严禁滥用 |safe 过滤器**。
|
||||
* **富文本处理**:如果业务确实需要接收和展示用户提交的 HTML 富文本,后端在入库前**必须**使用白名单过滤库(如 Python 的 bleach,Java 的 OWASP Java HTML Sanitizer)对危险标签(如 \<script\>, \<iframe\>, onload)进行清洗。
|
||||
|
||||
#### **3\. 跨站请求伪造 (CSRF) 防护**
|
||||
|
||||
* **无状态 Token 场景(如 JWT)**:客户端将 Token 存放在 localStorage 并通过 Header (如 Authorization: Bearer) 发送时,天然免疫 CSRF,无需额外配置。
|
||||
* **Cookie 鉴权场景**:如果项目使用 Cookie 存放 Session ID 或 Token:
|
||||
* 必须为 Cookie 设置 HttpOnly=True(防止 XSS 窃取)和 SameSite=Lax 或 Strict(防止 CSRF 跨站携带)。
|
||||
* 涉及状态修改的接口(POST/PUT/DELETE),必须开启并验证 CSRF Token。
|
||||
|
||||
### **4.3.2 敏感数据处理规范 (数据安全红线)**
|
||||
|
||||
敏感数据(如用户密码、手机号、身份证号、银行卡号、支付凭证)的生命周期必须受到极其严格的管控。
|
||||
|
||||
#### **1\. 传输层加密**
|
||||
|
||||
* **规范**:生产环境的所有 API 请求、后台管理系统访问,**强制使用 HTTPS (TLS 1.2 及以上版本)**。绝对禁止敏感数据在公网明文传输。
|
||||
|
||||
#### **2\. 密码存储红线**
|
||||
|
||||
* **红线**:**任何情况下,绝对禁止以明文形式存储用户密码。**
|
||||
* **规范**:
|
||||
* 密码必须使用强单向哈希算法(如 Bcrypt, Argon2,或 Django 默认的 PBKDF2)进行加密存储。
|
||||
* **禁止使用 MD5 或 SHA1** 作为密码的哈希算法(极其容易被彩虹表破解)。
|
||||
* 加密过程必须加盐(Salt),且每个用户的盐值必须随机且唯一。
|
||||
|
||||
#### **3\. PII (个人身份信息) 的存储与加密**
|
||||
|
||||
* **需解密还原的数据**(如业务人员需要查看真实手机号、发货地址):必须使用强大的对称加密算法(如 AES-256-GCM)进行**落地加密(Encryption at Rest)**,且加密密钥(KMS)必须与数据库物理隔离。
|
||||
* **无需解密的数据**(如仅用于用户登录匹配的手机号):建议直接使用带盐哈希存储,业务逻辑只做哈希比对。
|
||||
|
||||
#### **4\. 数据展示与脱敏 (Data Masking)**
|
||||
|
||||
* **红线**:**前端展示所需的数据脱敏,必须在后端完成!绝对禁止后端返回完整明文数据,依靠前端代码去隐藏或打星号。**
|
||||
* **规范**:通过 API 返回给用户终端的敏感信息,必须提前进行掩码截断。
|
||||
* 手机号:138\*\*\*\*1234
|
||||
* 身份证:110105\*\*\*\*\*\*\*\*1234
|
||||
* 银行卡:\*\*\*\* \*\*\*\* \*\*\*\* 1234
|
||||
* 姓名:张\*三 或 \*三
|
||||
|
||||
#### **5\. 日志安全红线**
|
||||
|
||||
* **红线**:**日志中绝对禁止打印明文密码、鉴权 Token、完整的银行卡号/CVV 码、加密密钥。**
|
||||
* **规范**:在全局中间件或切面(AOP)记录请求和响应日志时,必须配置**敏感字段过滤规则**。如果请求体中包含 "password": "xxx",写入日志时必须替换为 "password": "\*\*\*"。
|
||||
|
||||
### **4.3.3 业务安全与防暴破机制**
|
||||
|
||||
* **水平越权防护 (IDOR/BOLA)**:
|
||||
* 永远不要相信用户提交的资源 ID。在修改或删除任何记录(如 POST /orders/123/cancel)时,除了判断 ID 存在,**必须**在数据库查询层面加上归属校验(如 WHERE order\_id=123 AND user\_id={当前登录用户ID})。*(详见 3.2.7 数据隔离规范)*。
|
||||
* **接口防刷与限流 (Rate Limiting)**:
|
||||
* 对于发送短信验证码、注册、登录等极易被黑客利用进行暴力破解或“薅羊毛”的接口,必须在网关层或应用层配置**频次限制**(如同一 IP 每分钟最多 5 次,同一手机号每天最多 10 次)。
|
||||
* **失败提示模糊化**:
|
||||
* 登录失败时,无论是因为“账号不存在”还是“密码错误”,**统一定义返回**:“账号或密码错误”。禁止明确告知攻击者账号是否存在,防止黑客进行“撞库”和账号枚举。
|
||||
Reference in New Issue
Block a user