从一个小 Bug,到 Azure DevOps
1. 一个小Bug
最近和同事提起一个几年前的 Bug,那是一个很小很小的 Bug,没什么技术含量。那时候我刚入职,正好公司卖了一款仪器到某个国家,但是那边说配套的软件运行不起来,一打开就报错。经过排查发现出错的代码很简单,大致是这样:
public static int GetSecond(DateTime time)
{
return Convert.ToInt32(time.ToString().Split(":")[2]);
}
当时真是哭笑不得。这段代码应该是从旧语言迁移过来,如果只在国内完全没问题,但放到国外就可能报错,因为不同地区和语言会有不同的时间格式,例如加拿大的时间显示格式就不一样,秒的后面还带了表示上午/下午的 a.m/p.m.
,这一点可以通过在代码中更改 Thread.CurrentThread.CurrentCulture
来验证:
var time = new DateTime(2000, 1, 20, 1, 2, 3);
Console.WriteLine(time); \\ 输出 2000-01-20 1:02:03
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-CA");
Console.WriteLine(time); \\ 输出 2000-01-20 1:02:03 a.m.
至于测试人员,可以通过将系统设置中的“时间和语言- > 语言&区域”中的区域格式为英语(加拿大)来验证:
可是无论开发人员还是测试人员都没有发现有问题,当时这个离谱的 Bug 就这样插着翅膀,飞越高山和大海,飞到了国外客户的手上。整个团队上上下下由开发到测试都没发现整个 Bug,也许团队在技术和流程上都有问题,让我不得不怀疑我进了个大坑。
吃一堑就要长一智。虽然只是一个小 Bug,但也反映了团队技术和代码流程的欠缺。为了避免再发生这种情况,需要从团队培养及流程改善两个方面着手。团队培养是另一个话题,这篇文章只说说流程改善。当时我们已经在使用 TFS(Azure DevOps 的前身),不过只用于代码管理,很多功能都没有用到。后来 Azure DevOps 不断改善,我们也使用了它更多的功能来帮助我们改进产品质量。这篇文章以文章开头的那个小 Bug 为例,简单讲解 Azure DevOps 处理它的流程。
2. 在 Azure DevOps 上记录并开始处理这个 Bug
首先假设我已经在 Azure DevOps 管理代码,并且配置好 Pipeline 等基础设施,我现在只需要处理这个 Bug。
第一步,添加一个 Bug。除了Bug 的标题,Bug 的详细内容里还可以添加重现步骤、系统信息等,如果有错误日志的话还可以作为附件添加到这个 Bug 里。
当团队理解并同意了这个 Bug 的内容后,在 Boards 中将它从 New 拖动到 Approved,并在 ··· 的下拉菜单中选中 Add Task 和 Add Test 分别添加任务和测试用例。
我随意添加了两个任务以及一个测试用例。
3. 在 Visual Studio 中修复 Bug 并添加单元测试
之后轮到团队中负责处理这个 Bug 的开发人员接手工作。打开 VisualStudio 新建分支,修复这个 Bug,并根据单元测试 Arrange、Act、Assert 的方式添加一个对应的单元测试:
[TestMethod]
public void GetSecond_DifferentCultureInfo_Succeed()
{
var time = new DateTime(2000, 1, 20, 1, 2, 3);
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-CA");
var second = DateTimeUtils.GetSecond(time);
Assert.AreEqual(second, time.Second);
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("zh-CN");
second = DateTimeUtils.GetSecond(time);
Assert.AreEqual(second, time.Second);
}
运行单元测试,确保所有单元测试都通过后在 Git 更改 面板提交这个 Bug 的信息,并且输入关联的工作项的 ID,然后点击 全部提交并推送。
推送成功后回到代码编辑器,可以看到被修改的函数上的 CodeLens 有一个待变单元测试通过的绿色图标,鼠标放上去可以显示它被哪些单元测试验证过。
在被修改的函数及相关的单元测试的 CodeLens 最右边显示“4个工作项”,鼠标放上去可以看到之前提交代码时关联的工作项。
4. 在 Pull Request 中验收代码
接下来的操作需要回到 Azure DevOps。新的代码不能随随便便就签进去主分支,需要创建一个 PullRequest 通知相关人员这个代码变动,并在这个 Pull Request 里记录关联的工作项,经过修改的代码,需要谁来 Code Review 等。听起来很多,其实提交代码的开发人员只需要点击创建 Pull Request,选择要合并的分支,然后点击创建,其它内容几乎都由 Azure DevOps 自动填充。
Pull Request 最起码需要两道把关,一个是自动运行的单元测试,它需要代码里所有单元测试都运行并且通过。另一个是 Code Review,Azure DevOps 可以设置各种 Code Review 策略,包括最少的 Code Review 人数、当有变更时重置所有审核等。Code Review 除了保证签入的代码质量,还是代码集体所有的一个体现。代码集体所有是敏捷中一个重要的要素,它确保团队中知识的传承,并促进能力的提升。
下图是一个已完成的 Pull Request,可以看到几个绿色的代表通过的图标,代表它通过了多少道“工序”。还可以看到它关联的工作项,由谁创建,由哪个分支合并到哪里等信息。
切换到 Files 选项卡,可以看到具体的代码变更:
5. 测试验证与测试用例
完成上面的步骤后将 Bug 从 Approved 拖动到 Committed,并且将关联的两个 Task 设为完成。代码合并到 master 后 Azure Pipeline 将自动编译并部署好最新的代码,然后通过邮件或 Teams 通知给相关测试人员。测试人员在收到通知后打开 Board,当它看到这个 Bug 的全部 Task 都已经完成(黄色图标旁边的 2/2),他就知道应该开始进行测试验收。完成测试后在测试用例右边的 ··· 下拉菜单中选择测试结果,顺利的话选择 Pass test,并且把这个 Bug 拖到 Done。
到这一步 Bug 的处理已经完成。为防止错误再次发生,开发人员添加了单元测试,并且所有相关人员都通过这个流程分享了经验,无论是代码或是团队都变得更加强大。但这还不是结束,这个 Bug 里包含的测试用例是它留下的另一份宝贵财产,需要谨慎对待。打开这个 Bug,可以在右下角 Tested By 部分看到它的测试用例。
点击这个测试用例查看详细信息,可以看到它的 Steps(这里我懒得写),以及各种关联的工作项。
Azure DevOps 提供了 Test Plans 模块,用于管理测试用例和测试计划。在开发过程中产生的各种测试用例最终汇集成测试计划,由测试人员确保曾经正确运行过的功能不会再次出错。不过这部分只开放给收费用户,有机会再详细介绍它的各种功能。
6. 最后
现在公司的代码已经在 Azure DevOps 上安了家,一系列流程都运作得很畅顺(虽然还有很多很多可以改进的地方),尽管软件功能膨胀了几倍但售后反馈的问题反而更少。回过头来看看几年前那个 Bug,当时的代码生产方式和代码质量与现在真的有天壤之别,这其中 Azure DevOps 功不可没。
最后提醒一下,如果想尝试 Azure DevOps 可以不依照我写的流程。这篇文章介绍的流程只是个简化版本,实际工作起来稍微不同,而且应该根据自己团队的实际情况灵活改变,打造属于自己和自己团队的流程(幸好 Azure DevOps 可以做到相当灵活)。
关于 Azure DevOps 的更多内容请参考官方文档:
作者:dino.c
出处:http://www.cnblogs.com/dino623/
说明:欢迎转载并请标明来源和作者。如有错漏请指出,谢谢。