初始化文档

This commit is contained in:
QG
2026-03-24 16:13:32 +08:00
commit dc34a1536e
11 changed files with 1015 additions and 0 deletions

View 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 流水线。
* 如果自动化测试失败(红灯),或者核心代码覆盖率跌破基准线,代码审查工具必须**硬性阻断**合并按钮,不允许任何特权绕过。

View 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 文档注解。

View File

@@ -0,0 +1,72 @@
# **4.3 安全编码规范 (防御性编程)**
防御性编程的核心思想是:**假设所有的外部输入都是恶意的,假设内部的依赖调用随时会失败**。安全漏洞一旦在生产环境被利用,对业务和公司声誉的打击往往是毁灭性的。
本规范规定了团队在日常编码中必须遵守的安全底线。
### **4.3.1 常见 Web 漏洞防护底线**
#### **1\. SQL 注入 (SQL Injection) 绝对防线**
* **红线****绝对禁止**使用字符串拼接(如 Python 的 f-string 或 %sJava 的 \+)来构造 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 的 bleachJava 的 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 次)。
* **失败提示模糊化**
* 登录失败时,无论是因为“账号不存在”还是“密码错误”,**统一定义返回**:“账号或密码错误”。禁止明确告知攻击者账号是否存在,防止黑客进行“撞库”和账号枚举。