一 软件交付所存在的问题
反模式
对于传统IT公司来说,他们的部署方式大多都是使用手工部署,交付周期很长,大多会在实现一个非常大的 feature 才会进行部署,这样便会引发一系列的问题,比如手工部署会过多的依赖部署文档,环境复杂可能需要“部署专家”,部署周期间隔长则会导致反馈周期过长,不能及时的应对需求的变化。这被持续交付称之为软件交付的反模式。
如何避免这些反模式
为了避免以上所说的反模式,我们应该采取一些手段来降低部署/发布的风险:
- 把尽可能多的东西都纳入到版本控制中,对这些进行版本控制,从而可以随时变更发布所需版本
- 频繁发布
- 及时反馈,且作出相应的行动
- 自动化部署流水线
持续交付所推崇的交付原则
- 将所有事情自动化
- 部署流程,一旦我们有了自动化部署环境,那么我们就可以摆脱手工部署所带来的一切困扰,并且可以进行频繁的部署/发布
- 验收测试
- 数据库升级
- ...
- 把所有东西纳入版本控制
- 它们可能是源代码,环境配置,数据库数据/配置,网络配置,构建脚本,文档等,从而确保所有的开发人员使用的是同一代码和配置,也最大力度的使得不同的服务器环境保持一致,除此之外,一旦部署失败,我们可以快速的切换到上一个可用的版本进行部署
- 内建质量
- 软件的质量应该是由整个团结进行负责,不应该只是由QA来负责,越早发现缺陷,修复它的成本就会越低,在开发阶段,测试阶段发现问题要好过于客户发现问题
- DONE 意味着已发布
- DONE 是敏捷看板中的一个story(小功能,包含需求,价值,AC验收条件)从分析到发布上线,当一个 story 的状态被置为 DONE 后,则说明这个 story 已经完成并被部署上线
- 持续改进
- retro 在每一次迭代结束或者在工作过程中团队的状态不太好,都可以进行retreo回顾最近一段时间的状况,并根据大家所提出的 feedback 提取出 action 去执行
- PDCA 可以适用与任何敏捷方法中,比如 standup,pair,inception,retro... 可以很好的对它们的流程/质量进行改善
二 测试策略
测试四象限

其中:
- 业务导向支持开发过程属于是端到端的测试
这种测试往往需要模拟用户的行为,从UI界面到后端的业务的实现整个流程。功能验收测试一般维护成本很大,而且测试也需要很长的时间,位于测试金字塔的顶端,所以这类测试应该尽可能的少写,一般会选择实现 happy path 即可。 - 业务导向评判项目
一般是向客户演示软件的功能,进行易用性以及探索性的的测试,从而发现更优的一些需求 - 技术导向支持开发过程
对于单元测试,由于不需要连接数据库,所以测试的速度会非常快,所以单元测试要去覆盖尽可能多的情况,集成测试需要连接数据库,一般会使用内存数据库,速度会慢与单元测试,但会快于功能性测试,位于测试金字塔的中层。单元测试和集成测试是以开发的角度来验证开发人员实现的代码的正确性,而非验证整个story的功能。
测试替身
对于单元测试或者在进行集成测试的时候需要调用第三方,那么就需要用到测试替身来模拟。测试替身有以下几种类型
- dummy object : 致那些被传递但是不被真正使用的对象,一般用于参数列表
- fake object:是可以真正使用的对象,通常会使用一些捷径,不适合在 prod 上使用,比如内存数据库
- stub:在测试中为每个调用提供一个封装好的响应,不会对测试之外对请求进行响应,只用于测试
- spy:记录一些关于如何被调用对信息对桩
- mock object: 在编程时就设定了它预期要接收的调用和返回的结果
三 持续集成
当团队有多人一起进行协作开发时,频繁的提交代码到版本库中进行合并是非常重要的,这可以最大限度的防止代码冲突的发生以及降低解决冲突的成本,并且可以让代码库的代码保持最新且可以work
实现持续集成的准备工作
- 版本控制
- 自动化构建环境
- 团队的共识,非常重要,团队中的每个人都必须遵守这一实践
集成步骤
- 提交代码时,先查看是否有构建正在运行,如果有先等他构建完,如果失败了,需要和组员一起修复它,然后提交自己的代码
- 一旦构建完成且测试通过,就将最新代码更新到自己到开发环境上
- 如果本地构建成功,就将代码提交到版本库中
- 如果构建失败,就停下手中的事,在本机上立即修复这个问题,然后构建
- 如果这次构建成功的话,就可以开始下一项任务
前提条件
- 频繁提交
- 自动化测试套件(单元测试,集成测试,验收测试),如果没有测试,那么即使构建也无法验证所提交的代码是否可以work
最佳实践
- 构建失败后不要提交代码
- 提交代码前在本地运行测试或让集成服务器去跑测试
- 等提交测试通过在继续工作
- 回家之前构建必须是处于成功状态(如果失败,修复失败的构建or回滚到上一个可以work的代码进行构建)
- 时刻准备着回滚到上一个版本
- 在回滚之前要规定一个修复时间,在这个时间内,其他人不能提交代码,如果在这个时间段内没有修复好,那么回滚
- 不要将失败的测试注释掉,避免回归测试,如果业务发生改变应该修改测试,如果这个功能不存在则可以删除该测试
四 部署流水线
部署流水线是持续交付的核心,指软件从版本库到用户手中何以过程的自动化表现形式。

其中:
- 提交阶段
通过自动化的编译,测试,打包,从而将二进制文件放入到制品库中,为后续的流程作准备。如果编译/测试出错,开发人员可以看到详细的错误的原因并快速修复。 - 验收阶段
从制品库中拿到提交阶段的输出(二进制文件)进行部署、冒烟测试以及验收测试,这一过程是针对业务的功能测试,而非针对开发。 - 手工测试阶段
对系统进行一些易用性,探索性,UAT测试 - 发布阶段
前面一系列的步骤都是为了发布作准备,从而将可以work的软件交付给客户。理想情况下,我们已经在前面的步骤已经确保了软件各方面的正确性,可以正确的发布,但实际情况下,我们难免会遇到一些bug导致发布失败,面对这一情况,我们就需要做到快速的修复或者使用一些方式做到即使发布失败也不会影响到正常的运行
- 版本回退
在发布失败后,最常见的解决方法就是版本回退,不过这会导致一段时间内软件不可使用 -
蓝绿部署
蓝绿部署
要点:修改路由,将用户导向不同的环境
对数据的处理:
1.在部署到蓝环境(待部署的环境)前,将绿环境(正常环境)DB设置为onlyread状态,并备份
2.迁移备份到蓝环境
3.切换路由到蓝环境,如果一切正常将蓝环境DB设置为读写
4.如果蓝环境正常,部署绿环境,将路由再切换回绿环境,备份蓝环境数据到绿环境
影子城发布:部署两个相同的环境,成本可能会比较高,一个替代方案就是将试运行环境和生产环境作为蓝绿环境
- 金丝雀发布(A/B test)

关键点也是通过路由将用户到向不同到服务器中,与蓝绿部署不同的在于,金丝雀发布会将不同的版本放在不同的服务器(集群)中,然后将部分用户导向到新的版本,这不仅适用于测试新版本到功能是否可用,也同时可以用来测试新功能到使用情况,从而决定是否需要这个功能。
