首页/8

8章:项目完善:测试与部署

给博客加上质量保障,让它上线运行

40分钟
4个学习目标

学习目标

  • 1理解为什么要写测试
  • 2学会为博客功能编写单元测试
  • 3掌握TypeScript项目的构建配置
  • 4了解部署流程和最佳实践

上一章回顾:代码组织好了,然后呢?

在上一章中,我们学会了用模块系统组织代码——把类型定义、工具函数、业务逻辑分门别类地放好。博客项目现在结构清晰、职责分明。

但有一个问题:

你怎么知道这些代码是正确的?

你可能已经遇到过这种情况:改了一个函数,结果另一个地方坏了。或者上线后用户反馈某个功能不工作了,但你根本不知道是什么时候坏的。

这就是本章要解决的问题——给我们的博客项目加上质量保障

类比一下:

写代码就像做菜。模块系统帮你把厨房整理好了——调料放这边,食材放那边。但做完菜你得试吃(测试),确认没问题才能端给客人(部署)。如果客人吃了拉肚子(bug),那就是你的测试没做好。

为什么需要测试?

想象一下:你的博客有一个计算阅读时间的功能,逻辑是"每500字1分钟"。

function calculateReadTime(content: string): number {
  const words = content.length;
  return Math.ceil(words / 500);
}

看起来没问题对吧?但如果有人传了一个空字符串呢?Math.ceil(0 / 500) 返回 0,这倒是合理。但如果传了一个只有10个字的文章呢?Math.ceil(10 / 500) 返回 1,显示"1分钟阅读"——对于10个字的文章来说有点奇怪。

测试的价值:

| 没有测试 | 有测试 | |---------|-------| | 改代码全靠祈祷 | 改代码有底气 | | Bug在用户那里发现 | Bug在开发时就发现 | | 不敢重构 | 随时可以重构 | | 代码本身就是文档 | 测试就是最好的文档 |

测试金字塔:

  • 单元测试(我们重点学这个):测试单个函数
  • 集成测试:测试多个模块协作
  • 端到端测试:测试整个应用流程

第一个测试:为博客工具函数写测试

typescript
加载中...

测试的三个步骤:准备、执行、断言

每个测试都遵循同样的模式,我们叫它 AAA 模式

it('应该正确更新文章', () => {
  // 1. Arrange(准备):设置测试数据
  const post = { id: 1, title: '旧标题', content: '内容' };

  // 2. Act(执行):调用被测试的函数
  const updated = updatePost(post, { title: '新标题' });

  // 3. Assert(断言):验证结果
  expect(updated.title).toBe('新标题');
  expect(updated.content).toBe('内容'); // 其他属性不变
});

类比一下:

AAA就像做实验:

  • Arrange = 准备实验器材和材料
  • Act = 进行实验操作
  • Assert = 观察结果是否符合预期

为博客文章管理写测试

typescript
加载中...

构建配置:让项目可以部署

构建配置:让项目可以部署

测试通过了,接下来要把代码"打包"成可以部署的形式。

tsconfig.json 关键配置:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

配置项说明:

| 配置项 | 作用 | 类比 | |-------|------|------| | target | 编译目标版本 | 翻译成哪种语言 | | outDir | 输出目录 | 成品放在哪里 | | rootDir | 源码目录 | 原材料在哪里 | | strict | 严格模式 | 质检标准高低 |

错误处理:让博客更健壮

typescript
加载中...

常见错误

常见错误

1. 测试太多实现细节

// 不好:测试内部实现
expect(service.posts.length).toBe(1);

// 好:测试行为
expect(service.getPost(1)).toBeDefined();

测试应该关注"做什么"而不是"怎么做"。如果你重构了内部实现但行为不变,测试不应该失败。

2. 忘记测试边界情况

空值、极大值、负数、特殊字符——这些都是容易出bug的地方。

3. 测试之间有依赖

每个测试应该独立运行,不依赖其他测试的状态。用 beforeEach 重置状态。

4. 构建时忘记清理旧文件

# 建议在构建前先清理
rm -rf dist && tsc

部署:让博客上线

代码写好了、测试通过了、构建完成了——接下来就是部署。

部署流程:

  1. 代码检查:确保没有TypeScript错误
  2. 运行测试:确保所有测试通过
  3. 构建项目:生成可部署的文件
  4. 上传部署:推送到服务器或平台

常用部署平台:

| 平台 | 特点 | 适合场景 | |-----|------|---------| | Vercel | Next.js官方,一键部署 | 个人博客、小项目 | | Netlify | 免费额度大 | 静态站点 | | 自己的服务器 | 完全控制 | 企业项目 |

package.json 脚本配置:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "test": "jest",
    "lint": "eslint src --ext .ts,.tsx",
    "typecheck": "tsc --noEmit"
  }
}

动手实践

现在轮到你了!让我们为博客项目添加测试和部署配置。

练习1:为格式化函数写测试

创建一个 formatDate 函数,然后为它写测试:

  • 输入 Date 对象,返回 "YYYY-MM-DD" 格式
  • 处理空值情况

练习2:为文章验证写测试

创建一个 validatePost 函数:

  • 标题不能为空
  • 标题长度不超过100
  • 内容不能为空
  • 返回验证结果(成功或错误信息)

练习3:配置构建脚本

为你的项目配置完整的 package.json 脚本,包括:类型检查、测试、构建。

本章总结

恭喜你!你已经学会了如何保障代码质量:

本章要点:

  • 测试是代码质量的保障,不是可有可无的
  • AAA模式(准备-执行-断言)是写测试的基本框架
  • 测试应该关注行为,而不是实现细节
  • 边界情况是最容易出bug的地方
  • 构建配置让项目可以部署到生产环境

对比一下:

| 学习前 | 学习后 | |-------|-------| | 改代码靠祈祷 | 改代码有测试保障 | | 不知道代码有没有bug | 测试告诉你哪里有bug | | 代码只能在本地跑 | 代码可以部署上线 |

下一章预告:

在下一章中,我们将进入TypeScript的高级类型世界——联合类型、交叉类型、类型守卫。这些工具会让你的类型定义更灵活、更强大。

就像学会了基础武功,现在要开始学进阶招式了!

交互式练习

1 / 1

测试练习:为计算函数写测试

为博客的阅读时间计算函数编写完整的单元测试

typescript
Loading...

章节测验

问题 1 / 3得分: 0 / 3

测试的AAA模式指的是什么?

A
Arrange-Act-Assert(准备-执行-断言)
B
Ask-Answer-Analyze(提问-回答-分析)
C
Add-Apply-Adjust(添加-应用-调整)
D
All-Above-Are(以上都是)