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 TaskAdd 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 的更多内容请参考官方文档:

Azure DevOps documentation _ Microsoft Docs

从一个小Bug,到Azure DevOps的更多相关文章

  1. 关于一个小bug的修正

    python初学者,非常喜欢虫师的文章. 练习时发现一个小bug,http://www.cnblogs.com/fnng/p/3782515.html 验证邮箱格式一题中,第三个x不允许有数字,但是测 ...

  2. iOS开发之使用UICollectionView实现美团App的分类功能【偶现大众点评App的一个小bug】

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  3. js动画--一个小bug处理下

    对于上面的课程我们很好的处理了一个小bug,那么我们现在讲程序进行优化一下,前一节的程序中,我们处理处理的属性都是写死了的.为了我们能够很好的对某个属性进行操作的话.我们这样来设置. js文件 win ...

  4. Python2 下 Unicode 的一个小bug

    关于Python的编码问题已经是老生常谈了,此处主要是介绍一个罕见的问题,也算是Python2的一个bug了(Python3不会有此问题). 在有时候我们去爬取网页或者调用一些第三方库获取文本的时候, ...

  5. Cocos2d-JS V3.10 一个小bug提示

    感谢读者古事东流反馈,新版V3.10的音乐播放接口存在一个bug. 重复播放一个音乐,会出现音乐停止的状况. debug了一下,发现src的对比有点问题.传入的url是相对路径,但背景bgMusic. ...

  6. 一个短路求值引起的一个小bug

    今天在写一个判断字符串是否回文时因为短路求值问题导致了一个bug,记录如下: 代码如下 bool isPal(char str[],int len) { int begin=0; int end=le ...

  7. 关于c语言的一个小bug(c专家编程)

    不多说,说了都是累赘!直接看代码吧! #include <stdio.h> int array[] = {23, 34, 12, 17, 204, 99, 16}; #define TOT ...

  8. 关于args的一个小bug

    我在开始学习Java的时候就有点疑惑,到底main方法中的args到底是什么?经过我的一些思考,然后结合代码写一点自己的看法. 下面来看一段代码: /** * @author 薛定谔的猫 * 关于ar ...

  9. 第三方开源动画库EasyAnimation中一个小bug的修复

    看过iOS动画之旅的都知道,其中在最后提到一个作者写的开源动画库EasyAnimation(以下简称EA). EA对CoreAnimation中的view和layer动画做了更高层次的包装和抽象,使得 ...

随机推荐

  1. java链接并操作数据库

    链接准备 MySQL数据库驱动(连接器).mysql-connector-java-x.x.xx.jar会在MySQL安装时提供,若Mysql是默认安装路径,则连接器在:C:\Program File ...

  2. Linux 命令后&的作用

    cp $filename /dev/ & & 代表非阻塞方式拷贝文件,如果不加& 则必须等到执行完该指令后才能执行后来的指令.

  3. 【UE4 C++ 基础知识】<1> UPROPERTY宏、属性说明符、元数据说明符

    属性声明 属性使用标准的C++变量语法声明,前面用UPROPERTY宏来定义属性元数据和变量说明符. UPROPERTY([specifier, specifier, ...], [meta(key= ...

  4. 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链

    散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...

  5. 使用包图 (UML Package Diagram) 构建模型架构

    包图用于以包包含层次结构的形式显示模型的组织方式.包图还可以显示包包含的模型元素以及包与其包含的模型元素之间的依赖关系. 在项目开发中,模型元素可能会很快达到大量数量,因此需要以某种方式构建它们,即使 ...

  6. ScatterLayout分散布局在kv中的引用

    from kivy.uix.scatterlayout import ScatterLayout from kivy.app import App class ScatterLayoutWidget( ...

  7. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

  8. Spring动态添加定时任务

    Spring动态添加定时任务 一.背景 二.需求和实现思路 1.能够动态的添加一个定时任务. 2.能够取消定时任务的执行. 3.动态的修改任务执行的时间. 4.获取定时任务执行的异常 三.代码实现 四 ...

  9. 2021.8.21考试总结[NOIP模拟45]

    T1 打表 由归纳法可以发现其实就是所有情况的总和. $\frac{\sum_{j=1}^{1<<k}(v_j-v_{ans})}{2^k}$ $code:$ 1 #include< ...

  10. 万维网www与HTTP协议

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105901440 学习课程:<2019王道考研计算机网络> 学习目的 ...