• [热门活动] 【有奖反馈】敏捷智库知识卡出新版啦!选出你喜欢的知识卡,好礼等你拿~
    第13期敏捷智库知识卡出新版啦~~蓝色清新海报款,白色简洁流程图喜欢哪一款?参与反馈就有机会获得华为手环,蓝牙音箱等。点击下方链接或者扫描图片上二维码即可参与,让我们马上开始吧~https://devcloud.huaweicloud.com/expert/open-assessment/qtn?id=e40ffc503cad4841935db18d6af933a9往期卡片回顾:【敏捷智库知识卡】第1-7期合集【敏捷智库知识卡】 第8期 拍脑袋估算法?OUT!:科学估算,平稳生产,嗷闪!【敏捷智库知识卡】第9期 微服务架构难落地?MSA实施指导框架来帮你【敏捷智库知识卡】 第10期 任务不让指派还没人认领,我咋整?—— Scrum Master的心酸谁能知?【敏捷智库知识卡】 第11期 项目团队人员变动频繁怎么办——大牛走了,你怕不怕?【敏捷智库知识卡】第12期 需求剪不断理还乱(内附1-12期卡片合集下载)高清无水印知识卡请点击附件下载
  • [交流吐槽] 【包不同的沙雕敏捷】第二集 需求管理靠看板
    你是否被需求管理混乱,需求跟踪困难等类似的问题困扰?反正包不同是被难到了。辛亏扫地僧支招,才化解了包不同的窘境。扫地僧究竟出了什么主意呢?一起来看《包不同的沙雕敏捷第二集  需求管理用看板》《包不同的沙雕敏捷》故事主要讲述立志成为敏捷大咖的技术小白包不同在敏捷工作中的日常,与同事之间温馨搞笑的生活故事。视频贴
  • [热门活动] 【有奖反馈】敏捷智库知识卡出新版啦!选出你喜欢的知识卡,好礼等你拿~
    第13期敏捷智库知识卡出新版啦~~蓝色清新海报款,白色简洁流程图喜欢哪一款?参与反馈就有机会获得华为手环,蓝牙音箱等。点击下方链接或者扫描图片上二维码即可参与,让我们马上开始吧~https://devcloud.huaweicloud.com/expert/open-assessment/qtn?id=e40ffc503cad4841935db18d6af933a9往期卡片回顾:【敏捷智库知识卡】第1-7期合集【敏捷智库知识卡】 第8期 拍脑袋估算法?OUT!:科学估算,平稳生产,嗷闪!【敏捷智库知识卡】第9期 微服务架构难落地?MSA实施指导框架来帮你【敏捷智库知识卡】 第10期 任务不让指派还没人认领,我咋整?—— Scrum Master的心酸谁能知?【敏捷智库知识卡】 第11期 项目团队人员变动频繁怎么办——大牛走了,你怕不怕?【敏捷智库知识卡】第12期 需求剪不断理还乱(内附1-12期卡片合集下载)高清无水印知识卡请点击附件下载
  • [技术干货] 【DevCloud · 敏捷智库】暴走在发布前夜的开发,你怕不怕?
    来自一个CEO的叙述在一次企业交流会上,一个公司的CEO提道,“我们公司做敏捷开发的转型有一段时间了,采用的是4周一迭代,相比之前的瀑布式开发,我们可以在每一个月就让客户看到我们的成果物,这确实为公司和客户搭建起了良好的沟通桥梁。但是,也出现了一个不好的情况,就是开发和客户之前的矛盾激化了,由于采用了迭代,所以每个月都有2天开发团队要通宵熬夜,大家苦不堪言。有个别的开发同学,骂完公司骂同事,骂完同事骂客户的,甚至连自己都不放过……”那些暴走在发布前夜的开发,你是否也遇见过呢?感同身受的无奈和愤怒来自开发的一波怒气“我晕,这谁提的代码啊,上来就白页面了,还玩个球啊!”“我倒,我本地都是好用的啊,怎么部署到环境上不行了呢!”“我去,这哪个大兄弟提了这么些代码,太能写了。我和他代码冲突多到想哭!”“我的代码让哪个孙子给覆盖了,我一下午白写了,别让我查出来谁干的哈!”“催催催,催个大脑袋啊,你行你来,不行就别说话,合代码这事是人干的活吗!”“几位大哥,我知道问题出在哪了,我这还有段代码没提交上去呢,嘿嘿,不好意思哈。”“我*!”来自领导的心酸无奈领导:“每次发布前,我都不太想去你们开发那,太压抑了!,你说咋办?”骨干:“咋办,还能咋办,换人呗。一个个都不懂咋开发还能咋办。”领导:“不是都经过笔试面试进来的吗?咋还能不懂开发呢?”骨干:“开发不是开发完了就行,得好用啊。这帮小年轻就知道埋头coding,然后扣出来的都是一堆不好用的代码,不好用倒也没啥,直接就往代码库里提交啊!”领导:“这帮小年轻这么虎吗?”骨干:“这还不算是虎的呢,还那种代码冲突了的,不管三七二十一直接就忽略冲突提交,我有好几回,一拉取最新代码,一面红色啊。”领导:“那你多带带他们,告诉他们怎么做啊!“骨干:“我都告诉过很多遍了,每次都说‘我测了啊!’,‘诶?奇怪了!’,‘不好意思哥,我忘提交了’,就这帮小年轻,我是真心带不动哈。我还是觉得以前瀑布挺好的,要不就变回去得了。“领导:“那不行啊,客户现在挺认可我们的。用敏捷一个月就能看到新做的东西。效果好,客户满意度高。你还是想想办法吧。“骨干:“我看还是换人吧。我是无法阻止别人不**的“领导:“……“问题出在哪里不知道读者读到这里是否感同身受了一下下,如果没有的话,那么恭喜你,你很幸运的加入到了一个优秀的团队或者公司。不过,可能你的IT生涯是不完整的……近些年来,整个IT圈子都在宣扬DevOps,也因此很多人都知道Dev的工作是给应用系统增加新的功能/修复Bug,而Ops的工作是要保持系统的稳定和高性能,而DevOps后就是要调和了Dev和Ops的矛盾、打破二者的壁垒,以更好的面对变化。大家满怀着希望开始了敏捷和DevOps,可是往往在新潮和流行的“上层建筑”往往发现了“形而下”的落地困难。比如Dev侧自身内部的问题。在上面举例中的开发的那波怒火和领导的无奈中,诚然有开发人员自身能力素质的问题,但这并不能算是问题,因为所有人都是从菜鸟过来了,没有人是天生的王者。“怒气”到底因为什么?为什么会有怒气呢?这个怒气几乎都来源于在团队协作中的“别人”,其实就是在沟通上产生了问题,这可以归结为工作方式方法的问题,说得更直白就是没有遵循一个良好的软件开发实践。在传统的瀑布开发的时候,开发往往会在最后“奋力一搏”完成了项目的部署工作,然后就进入了“休息”的状态,如果有bug就修改bug,如果有其他的(如文档补充,但愿你没有这样的经历)做其他的,处于被动触发这种相对轻松的姿态,所以他们从某种程度上说,是可以接受“别人”的问题的,毕竟忍耐一下就过去了。而在敏捷的迭代开发中,每次迭代都要产出潜在的可交付成果物,部署和发布是“永不止境”的,所以就没有仿佛能看到黎明吹响胜利号角的“奋力一搏”,合代码的人率先遭遇一波伤害,紧接着其他的开发一个个承受着伤害(如果出现Bug),然后大家最后再在一起承受某个或某些谁都不知道的问题带来的打击……所以往往每次的发布都是一次心志的磨练和煎熬,尤其以大工作量周期以月为单位迭代为最——这个背后的元凶其实就是“集成”!有什么好办法虽然相对传统制造业软件显得“年轻”,但是也经历了无数的大风大浪,这种问题并不专属于某些公司,这种烦恼和无奈也并非只有他们才经历过。早在软件开发的“上古”时代,软件界的大神——Martin Fowler就有过这样的经历:“我还可以生动记起第一次看到大型软件工程的情景。我当时在一家大型英国电子公司的QA部门实习。我的经理带我熟悉公司环境,我们进到一间巨大的,充满了压抑感和格子间的的仓库。我被告知这个项目已经 开发了好几年,现在正在集成阶段,并已经集成了好几个月。我的向导还告诉我没人知道集成要多久才能结束”。Martin Fowler不仅在他实习的期间认识到集成是一件很耗时并难以预测的过程,并且很多项目和团队并不把集成当回事。所以为了解决集成所带来的问题以及很多人思想上的不以为意,Martin Fowler 提出了——持续集成。持续集成 是一种软件开发实践。在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次。每次集成会经过自动构建(包括自动测试)的 检验,以尽快发现集成错误。从其定义上来看,持续集成可以很好的解决开发们的“怒气”的问题,开发的怒气根本上来说就是由于在协作中缺少“沟通”所造成的,进而将问题推到了“别人”身上,试想如果整个开发的过程中,每个团队的成员彼此做的功能,或者说所提交的代码是“透明”的,那么就可以很大程度上减少这种“别人”的问题了。并且这种“透明”化的周期无需太长时间,最长为一天,最短于几个小时内,从而可以很好的解决了开发团队集成的问题,降低了交付的风险。那么,具体的落地应该有哪些呢?应该如何落地欲善其功必先利其器,在谈落地实践之前,首先看看要实现持续集成需要有哪些工具。基础工具一:版本控制系统。持续集成最基本的前提条件是对其代码库的版本控制,即:对于代码库的每一项变更,都必须被安全地存放到专有的版本控制系统中,目前最主流的版本控制系统当属Git。基础工具二:构建工具。构建工具能够通过处理应用的源代码,自动生成所需的软件(包)。软件工具的构建步骤取决于所选用的技术栈。如,Java的应用,可使用Maven作为构建工具。讲完了持续集成的定义和基础工具后,那么持续集成的过程是怎么样的呢?我们一起看看Martin Fowler是怎么带着我们玩转持续集成的吧。(以下内容来自Marin Fowler的持续集成)举个简单的例子:现在假设要完成一个软件的一部分功能,具体任务是什么并不重要,我们先假设这个 feature 很小,只用几个小时就可以完成。一开始,将已集成的源代码复制一份到 本地计算机。这可以通过从源码管理系统的 mainline 上 check out 一份源代码做到。现在拿到了工作拷贝,接下来需要做一些事情来完成任务。这包括修改产品代码和添加修改自动化测试。在持续集成中,软件应该包含完善的可自动运行的测试——自测试代码。这一般需要用到某一个流行的 XUnit 测试框架。一旦完成了修改,就会在自己的计算机上启动一个自动化 build。这会将工作拷贝中的源代码编译并链接成为一个可执行文件,并在之上运行自动化测试。只有当所有的 build 和测试都完成并没有任何错误时,这个 build 过程才可以认为是成功的。当本地build 成功后,就可以考虑将改动提交到源码仓库。但麻烦的情况在于别人可能已经在我之前修改过 mainline。这时我需要首先把别人的修改更新到自己的工作拷贝中,再重新做 build。如果别人的代码和自己的有冲突,就会在编译或测试的过程中引起错误。自己有责任改正这些问题,并重复这一过程,直到自己的工作拷贝能通过 build 并和 mainline 的代码同步。一旦本地的代码能通过 build,并和 mainline 同步,就可以把我的修改提交到源码仓库。然而,提交完代码不表示就完事大吉了。还要做一遍集成 build,这次在集成计算机上并要基于 mainline 的代码。只有这次 build 成功了,修改才算告一段落。因为总有可能会忘了什么东西在自己的机器上而没有更新到源码仓库。只有提交的改动被成功的集成了,这次工作才能算结束。如果两个开发者的修改存在冲突,这通常会被第二个人提 交代码前本地做 build 时发现。即使这时侥幸过关,接下来的集成 build 也会失败掉。不管怎样,错误都会被很快检测出来。此时首要的任务就是改正错误并让 build 恢复正常。在持续集成环境里,必须尽可能快地修复每一个集成 build。好的团队应该每天都有多个成功的 build。错误的 build 可以出现,但必须尽快得到修复。这样做的结果是你总能得到一个稳定的软件,它可能有一些 bug,但可以正常工作。每个人都基于相同的稳定代码进行开发,而且不会离得太远,否则就会不得不花很长时间集成回去。Bug被发现得越快,花在改正上的 时间就越短。上述基本上就是持续集成的过程和步骤了。那么基于此持续集成又又哪些关键的实践呢?主要有如下几个:只维护一个源代码在软件项目里需要很多文件协调一致才能 build 出产品。跟踪所有这些文件是一项困难的工作,尤其是当有很多人一起工作时。所以,一点也不奇怪,软件开发者们这些年一直在研发这方面的工具。这些工具称为 源代码管理工具,或配置管理,或版本管理系统,或源码仓库,或各种其它名字。大部分开发项目中它们是不可分割的一部分。但可惜的是,并非所有项目都是如 此。虽然很罕见,但我确实参加过一些项目,它们直接把代码存到本地驱动器和共享目录中,乱得一塌糊涂。所以, 作为一个最基本的要求,你必须有一个起码的源代码管理系统。成本不会是问题,因为有很多优秀的开源工具可用。当前较好的开源工具是 Subversion。(更 老的同样开源的 CVS 仍被广泛使用,即使是 CVS 也比什么都不用强得多,但 Subversion 更先进也更强大。)有趣的是,我从与开发者们的交谈中了解到,很多商业源代码管理工具其实不比 Subversion 更好。只有一个商业软件是大家一致同意值得花钱的,这就是 Perforce。一旦你有了源代码管理系统,你要确保所有人都知道到哪里去取代码。不应出现这样的问题:“我应该到哪里去找xxx文件?” 所有东西都应该存在源码仓库里。即便对于用了源码仓库的团队,我还是观察到一个很普遍的错误,就是他们没有把 所有东西都放在源码仓库里。一般人们都会把代码放进去,但还有许多其它文件,包括测试脚本,配置文件,数据库Schema,安装脚本,还有第三方的库,所 有这些build时需要的文件都应该放在源码仓库里。我知道一些项目甚至把编译器也放到源码仓库里(用来对付早年间那些莫名其妙的C++编译器很有效)。 一个基本原则是:你必须能够在一台干净的计算机上重做所有过程,包括checkout和完全build。只有极少量的软件需要被预装在这台干净机器上,通 常是那些又大又稳定,安装起来很复杂的软件,比如操作系统,Java开发环境,或数据库系统。你必须把 build需要的所有文件都放进源代码管理系统,此外还要把人们工作需要的其他东西也放进去。IDE配置文件就很适合放进去,因为大家共享同样的IDE配 置可以让工作更简单。版本控制系统的主要功能之一就是创建 branch 以管理开发流。这是个很有用的功能,甚至可以说是一个基础特性,但它却经常被滥用。你最好还是尽量少用 branch。一般有一个mainline就够 了,这是一条能反映项目当前开发状况的 branch。大部分情况下,大家都应该从mainline出发开始自己的工作。(合理的创建 branch 的 理由主要包括给已发布的产品做维护和临时性的实验。)一般来说,你要把build依赖的所有文件放进代码管理 系统中,但不要放build的结果。有些人习惯把最终产品也都放进代码管理系统中,我认为这是一种坏味道——这意味着可能有一些深层次的问题,很可能是无 法可靠地重新build一个产品。自动化Build通常来 说,由源代码转变成一个可运行的系统是一个复杂的过程,牵扯到编译,移动文件,将 schema 装载到数据库,诸如此类。但是,同软件开发中的其它类似任务一样,这也可以被自动化,也必须被自动化。要人工来键入各种奇怪的命令和点击各种对话框纯粹是 浪费时间,也容易滋生错误。在大部分开发平台上都能找到自动化 build 环境的影子。比如 make,这在 Unix 社区已经用了几十年了,Java 社区也开发出了 Ant,.NET 社区以前用 Nant,现在用 MSBuild。不管你在什么平台上,都要确保只用一条命令就可以运行这些脚本,从而 build 并运行系统。一 个常见的错误是没有把所有事都放进自动化 build。比如:Build 也应该包括从源码仓库中取出数据库 schema 并在执行环境中设置的过程。我要重申一下前面说过的原则:任何人都应该能从一个干净的计算机上 check out 源代码,然后敲入一条命令,就可以得到能在这台机器上运行的系统。Build 脚本有很多不同的选择,依它们所属的平台和社区而定,但也没有什么定势。尽管大部分的 Java 项目都用 Ant,还是有一些项目用 Ruby(Ruby Rake 是一个不错的 build 脚本工具)。我们也曾经用 Ant 自动化早期的 Microsoft COM 项目,事实证明很有价值。一个大型 build 通常会很耗时,如果只做了很小的修改,你不会想花时间去重复所有的步骤。所以一个好的 build 工具应该会分析哪些步骤可以跳过。一个通用的办法是比较源文件和目标文件的修改时间,并只编译那些较新的源文件。处理依赖关系要麻烦一些:如果一个目标文 件修改了,所有依赖它的部分都要重新生成。编译器可能会帮你处理这些事情,也可能不会。根据你的需要,你可能 会想 build 出各种不同的东西。你可以同时 build 系统代码和测试代码,也可以只 build 系统代码。一些组件可以被单独 build。Build 脚本应该允许你在不同的情况中 build 不同的 target。我们许多人都用 IDE,许多 IDE 都内置包含某种 build 管理功能。然而,相应的配置文件往往是这些 IDE 的专有格式,而且往往不够健壮,它们离了 IDE 就无法工作。如果只是 IDE 用户自己一个人开发的话,这还能够接受。但在团队里,一个工作于服务器上的主 build 环境和从其它脚本里运行的能力更重要。我们认为,在 Java 项目里,开发者可以用自己的 IDE 做 build,但主 build 必须用 Ant 来做,以保证它可以在开发服务器上运行。让你的Build自行测试传统意义上的 build 指编译,链接,和一些其它能让程序运行起来的步骤。程序可以运行并不意味着它也工作正常。现代静态语言可以在编译时检测出许多 bug,但还是有更多的漏网之鱼。一种又快又省的查 bug 的方法是在 build 过程中包含自动测试。当然,测试并非完美解决方案,但它确实能抓住很多 bug——多到可以让软件真正可用。极限编程(XP)和测试驱动开发(TDD)的出现很好地普及了自测试代码的概念,现在已经有很多人意识到了这种技巧的 价值。经常读我的著作的读者都知道我是 TDD 和 XP 的坚定追随者。但是我想要强调你不需要这两者中任何一个就能享受自测试代码的好处。两者都要求你先写测试,再写代码以通过测试,在这种工作模式里测试更多 着重于探索设计而不是发现 bug。这绝对是一个好方法,但对于持续集成而言它并不必要,因为这里对自测试代码的要求没有那么高。(尽管我肯定会选择用 TDD 的方式。)自测试代码需要包含一套自动化测试用例,这些测试用例可以检查大部分代码并找出 bug。测试要能够从一条简单的命令启动。测试结果必须能指出哪些测试失败了。对于包含测试的 build,测试失败必须导致 build 也失败。在过去的几年里,TDD 的崛起普及了开源的 XUnit 系列工具,这些工具用作以上用途非常理想。对于我们在 ThoughWorks 工作的人来说,XUnit 工具已经证明了它们的价值。我总是建议人们使用它们。这些最早由 Kent Beck 发明的工具使得设置一个完全自测试环境的工作变得非常简单。毋庸置疑,对于自动测试的工作而言,XUnit 工具只是一个起点。你还必须自己寻找其他更适合端对端测试的工具。现在有很多此类工具,包括FIT,Selenium,Sahi,Watir,FITnesse, 和许多其它我无法列在这里的工具。当然你不能指望测试发现所有问题。就像人们经常说的:测试通过不能证明没有 bug。然而,完美并非是你要通过自测试 build 达到的唯一目标。经常运行不完美的测试要远远好过梦想着完美的测试,但实际什么也不做。每人每天要向mainline提交代码集成的主要工作其实是沟 通。集成可以让开发者告诉其他人他们都改了什么东西。频繁的沟通可以让人们更快地了解变化。让开发者提交到 mainline 的一个先决条件是他们必须能够正确地 build 他们的代码。这当然也包括通过 build 包含的测试。在每个提交迭代里,开发者首先更新他们的工作拷贝以与 mainline 一致,解决任何可能的冲突,然后在自己的机器上做 build。在 build 通过后,他们就可以随便向 mainline 提交了。通过频繁重复上述过程,开发者可以发现 两个人之间的代码冲突。解决问题的关键是尽早发现问题。如果开发者每过几个小时就会提交一次,那冲突也会在出现的几个小时之内被发现,从这一点来说,因为 还没有做太多事,解决起来也容易。如果让冲突待上几个星期,它就会变得非常难解决。因为你在更新工作拷贝时也 会做 build,这意味着你除了解决源代码冲突外也会检查编译冲突。因为 build 是自测试的,你也可以查出代码运行时的冲突。后者如果在一段较长的时间还没被查出的话会变得尤其麻烦。因为两次提交之间只有几个小时的修改,产生这些问题 只可能在很有限的几个地方。此外,因为没改太多东西,你还可以用 diff-debugging 的技巧来找 bug。总的来说,我 的原则是每个开发者每天都必须提交代码。实践中,如果开发者提交的更为频繁效果也会更好。你提交的越多,你需要查找冲突错误的地方就越少,改起来也越快。频繁提交客观上会鼓励开发者将工作分解成以小时计的小块。这可以帮助跟踪进度和让大家感受到进展。经常会有人一开始根 本无法找到可以在几小时内完成的像样的工作,但我们发现辅导和练习可以帮助他们学习其中的技巧。每次提交都 应在集成计算机上重新构建 mainline使用每日提交的策略后,团队就能得到很多经过测试的 build。这应该意味着 mainline 应该总是处于一种健康的状态。但在实践中,事情并非总是如此。一个原因跟纪律有关,人们没有严格遵守在提交之前在本地更新并做 build 的要求。另一个原因是开发者的计算机之间环境配置的不同。结论是你必须保证日常的 build 发生在专用的集成计算机上,只有集成 build 成功了,提交的过程才算结束。本着“谁提交,谁负责”的原则,开发者必须监视 mainline 上的 build 以便失败时及时修复。一个推论是如果你在下班前提交了代码,那你在 mainline build 成功之前就不能回家。我知道主要有两种方法可以使用:手动 build,或持续集成服务器软件。手动 build 描述起来比较简单。基本上它跟提交代码之前在本地所做的那次 build 差不多。开发者登录到集成计算机,check out 出 mainline 上最新的源码(已包含最新的提交),并启动一个集成 build。他要留意 build 的进程,只有 build 成功了他的提交才算成功。(请查看 Jim Shore 的描述。)持续集成服务器软件就像一个监视着源码仓库的监视器。每 次源码仓库中有新的提交,服务器就会自动 check out 出源代码并启动一次 build,并且把 build 的结果通知提交者。这种情况下,提交者的工作直到收到通知(通常是 email)才算结束。在 ThoughtWorks,我们都是持续集成服务器软件的坚定支持者,实际上我们引领了 CruiseControl 和 CruiseControl.NET 最 早期的开发,两者都是被广泛使用的开源软件。此后,我们还做了商业版的 Cruise 持续集成服务器。我们几乎在每一个项目里都会用持续集成服务器,并且对结果非常满意。不是每个人都会用持续集成服务器。Jim Shore 就清楚地表达了为什么他更偏好手动的办法。我同意他的看法中的持续集成并不仅仅是安装几个软件而已,所有的实践 都必须为了能让持续集成更有效率。但同样的,许多持续集成执行得很好的团队也会发现持续集成服务器是个很有用的工具。许多组织根据安排好的日程表做例行 build,如每天晚上。这其实跟持续集成是两码事,而且做得远远不够。持续集成的最终目标就是要尽可能快地发现问题。Nightly build 意味着 bug 被发现之前可能会待上整整一天。一旦 bug 能在系统里呆这么久,找到并修复它们也会花较长的时间。做好持续集成的一个关键因素是一旦 mainline 上的 build 失败了,它必须被马上修复。而在持续集成环境中工作最大的好处是,你总能在一个稳定的基础上做开发。mainline 上 build 失败并不总是坏事,但如果它经常出错,就意味着人们没有认真地在提交代码前先在本地更新代码和做 build。当 mainline 上 build 真的失败时,第一时间修复就成了头等大事。为了防止在 mainline 上的问题,你也可以考虑用 pending head 的方法。当团队引入持续集成时,这通常是最难搞定的事情之一。在初期,团队会非常难以接 受频繁在 mainline 上做 build 的习惯,特别当他们工作在一个已存在的代码基础上时更是如此。但最后耐心和坚定不移的实践常常会起作用,所以不要气馁。保持快速 build持续集成的重点就是快速反馈。没有什么比缓慢的 build 更能危害持续集成活动。这里我必须承认一个奇思怪想的老家伙关于 build 快慢标准的的玩笑(译者注:原文如此,不知作者所指)。我的大部分同事认为超过1小时的 build 是不能忍受的。团队们都梦想着把 build 搞得飞快,但有时我们也确实会发现很难让它达到理想的速度。对大多数项目来说,XP 的10分钟 build 的指导方针非常合理。我们现在做的大多数项目都能达到这个要求。这值得花些力气去做,因为你在这里省下的每一分钟都能体现在每个开发者每次提交的时候。持 续集成要求频繁提交,所以这积累下来能节省很多时间。如果你一开始就要花1小时的时间做 build,想加快这个过程会相当有挑战。即使在一个从头开始的新项目里,想让 build 始终保持快速也是很有挑战的。至少在企业应用里,我们发现常见的瓶颈出现在测试时,尤其当测试涉及到外部服务如数据库。也许最关键的一步是开始使用分阶段build(staged build)。分阶段 build(也被称作 build 生产线)的基本想法是多个 build 按一定顺序执行。向 mainline 提交代码会引发第一个 build,我称之为提交 build(commit build)。提交 build 是当有人向 mainline 提交时引发的 build。提交 build 要足够快,因此它会跳过一些步骤,检测 bug 的能力也较弱。提交 build 是为了平衡质量检测和速度,因此一个好的提交 build 至少也要足够稳定以供他人基于此工作。一旦提交 build 成功,其他人就可以放心地基于这些代码工作了。但别忘了你还有更多更慢的测试要做,可以另找一台计算机来运行运行这些测试。一个简单的例子是两阶段 build。第一阶段会编译和运行一些本地测试,与数据库相关的单元测试会被完全隔离掉(stub out)。这些测试可以运行得非常快,符合我们的10分钟指导方针。但是所有跟大规模交互,尤其是真正的数据库交互的 bug 都无法被发现。第二阶段的 build 运行一组不同的测试,这些测试会调用真正的数据库并涉及更多的端到端的行为。这些测试会跑上好几小时。这种情况下,人们用第一阶段作为提交 build,并把这作为主要的持续集成工作。第二阶段 build 是次级build,只有 在需要的时候才运行,从最后一次成功的提交 build 中取出可执行文件作进一步测试。如果次级 build 失败了,大家不会立刻停下手中所有工作去修复,但团队也要在保证提交 build 正常运行的同时尽快修正 bug。实际上次级 build 并非一定要正常运行,只要 bug 都能够被检查出来并且能尽快得到解决就好。在两阶段 build 的例子里,次级 build 经常只是纯粹的测试,因为通常只是测试拖慢了速度。如果次级 build 检查到了 bug,这是一个信号,意味着提交 build 需要添加一个新测试了。你应该尽可能把次级 build 失败过的测试用例都添加到提交 build 中,使得提交 build 有能力验证这些 bug。每当有 bug 绕过提交测试,提交测试总能通过这种方法被加强。有时候确实无法找到测试速度和 bug 验证兼顾的方法,你不得不决定把这个测试放回到次级 build 里。但大部分情况下都应该可以找到合适加入提交 build 的测试。上面这个例子是关于两阶段 build,但基本原则可以被推广到任意数量的后阶段 build。提交 build 之后的其它 build 都可以同时进行,所以如果你的次级测试要两小时才能完成,你可以通过用两台机器各运行一半测试来快一点拿到结果。通过这个并行次级 build 技巧,你可以向日常 build 流程中引入包括性能测试在内的各种自动化测试。(当我过去几年内参加 Thoughtworks 的各种项目时,我碰到了很多有趣的技巧,我希望能够说服一些开发者把这些经验写出来。)在模拟生产环境中进 行测试测试的关键在于在受控条件下找出系统内可能在实际生产中出现的任何问题。这里一个明显的因素是生产系 统的运行环境。如果你不在生产环境做测试,所有环境差异都是风险,可能最终造成测试环境中运行正常的软件在生产环境中无法正常运行。自然你会想到建立一个与生产环境尽可能完全相同的测试环境。用相同的数据库软件,还要同一个版本;用相同版本的操作系统;把所有生产环 境用到的库文件都放进测试环境中,即使你的系统没有真正用到它们;使用相同的IP地址和端口;以及相同的硬件;好 吧,现实中还是有很多限制的。如果你在写一个桌面应用软件,想要模拟所有型号的装有不同第三方软件的台式机来测试显然是不现实的。类似的,有些生产环境可 能因为过于昂贵而无法复制(尽管我常碰到出于经济考虑拒绝复制不算太贵的环境,结果得不偿失的例子)。即使有这些限制,你的目标仍然是尽可能地复制生产环 境,并且要理解并接受因测试环境和生产环境不同带来的风险。如果你的安装步骤足够简单,无需太多交互,你也许 能在一个模拟生产环境里运行提交 build。但事实上系统经常反应缓慢或不够稳定,这可以用 test double 来解决。结果常常是提交测试为了速度原因在一个假环境内运行,而次级测试运行在模拟真实的生产环境中。我注意到越来越多人用虚拟化来搭建测试环境。虚拟机的状态可以被保存,因此安装并测试最新版本的build相对简单。此外,这可以让你 在一台机器上运行多个测试,或在一台机器上模拟网络里的多台主机。随着虚拟化性能的提升,这种选择看起来越来越可行。让每个人都能轻易获得最新的可执行文件软件开发中最困难的部分是确定你的软件行为符合预期。我们 发现事先清楚并正确描述需求非常困难。对人们而言,在一个有缺陷的东西上指出需要修改的地方要容易得多。敏捷开发过程认可这种行为,并从中受益。为了以这种方式工作,项目中的每个人都应该能拿到最新的可执行文件并运行。目的可以为了 demo,也可以为了探索性测试,或者只是为了看看这周有什么进展。这做起来其实相当简单:只要找到一个大家 都知道的地方来放置可执行文件即可。可以同时保存多份可执行文件以备使用。每次放进去的可执行文件应该要通过提交测试,提交测试越健壮,可执行文件就会越 稳定。如果你采用的过程是一个足够好的迭代过程,把每次迭代中最后一个 build 放进去通常是明智的决定。Demo 是一个特例,被 demo 的软件特性都应该是演示者熟悉的特性。为了 demo 的效果值得牺牲掉最新的 build,转而找一个早一点但演示者更熟悉的版本。每个人都能看到进度持续集成中最重要的是沟通。你需要保证每个人都能轻易看到系统的状态和最新的修改。沟通的最重要的途 径之一是 mainline build。如果你用 Cruise,一个内建的网站会告诉你是否正有 build 在进行,和最近一次 mainline build 的状态。许多团队喜欢把一个持续工作的状态显示设备连接到 build 系统来让这个过程更加引人注目,最受欢迎的显示设备是灯光,绿灯闪亮表示 build 成功,红灯表示失败。一种常见的选择是红色和绿色的熔岩灯,这不仅仅指示 build 的状态,还能指示它停留在这个状态的时间长短,红灯里出现气泡表示 build 出问题已经太长时间了。每一个团队都会选择他们自己的 build 传感器。如果你的选择带点幽默性和娱乐性效果会更好(最近我看到有人在实验跳舞兔)。即使你在使用手动持续集 成,可见程度依然很重要。Build 计算机的显示器可以用来显示 mainline build 的状态。你很可能需要一个 build 令牌放在正在做 build 那人的桌子上(橡皮鸡这种看上去傻傻的东西最好,原因同上)。有时人们会想在 build 成功时弄出一点噪音来,比如摇铃的声音。持续集成服务器软件的网页可以承载更多信息。Cruise 不仅显示谁在做 build,还能指出他们都改了什么。Cruise 还提供了一个历史修改记录,以便团队成员能够对最近项目里的情况有所了解。我知道 team leader喜欢用这个功能了解大家手头的工作和追踪系统的更改。使用网站的另一大优点是便于那些 远程工作的人了解项目的状态。一般来说,我倾向于让项目中发挥作用的成员都坐在一起工作,但通常也会有一些外围人员想要了解项目的动态。如果组织想要把多 个项目的 build情况聚合起来以提供自动更新的简单状态时,这也会很有用。好的信息展示方式不仅仅依赖于 电脑显示器。我最喜欢的方式出现于一个中途转入持续集成的项目。很长时间它都无法拿出一个稳定的 build。我们在墙上贴了一整年的日历,每一天都是一个小方块。每一天如果 QA 团队收到了一个能通过提交测试的稳定 build,他们都会贴一张绿色的贴纸,否则就是红色的贴纸。日积月累,从日历上能看出 build 过程在稳定地进步。直到绿色的小方块已经占据了大部分的空间时,日历被撤掉了,因为它的使命已经完成了。自动化部署自动化集成需要多个环境,一个运行提交测试,一个或多个运行次级测试。每天在这些环境之间频繁拷贝 可执行文件可不轻松,自动化是一个更好的方案。为实现自动化,你必须有几个帮你将应用轻松部署到各个环境中的脚本。有了脚本之后,自然而然的结果是你也要 用类似的方式部署到生产环境中。你可能不需要每天都部署到生产环境(尽管我见过这么做的项目),但自动化能够加快速度并减少错误。它的代价也很低,因为它 基本上和你部署到测试环境是一回事。如果你部署到生产环境,你需要多考虑一件事情:自动化回滚。坏事情随时可 能发生,如果情况不妙,最好的办法是尽快回到上一个已知的正常状态。能够自动回滚也会减轻部署的压力,从而鼓励人们更频繁地部署,使得新功能更快发布给用 户。(Ruby on Rails 社区开发了一个名为 Capistrano 的工具,是这类工具很好的代表。)我还在服 务器集群环境中见过滚动部署的方法,新软件每次被部署到一个节点上,在几小时时间内逐步替换掉原有的软件。在 web 应用开发中,我碰到的一个有趣的想法是把一个试验性的 build 部署到用户的一个子集。团队可以观察这个试验 build 被使用的情况,以决定是否将它部署到全体用户。你可以在做出最终决定之前试验新的功能和新的 UI。自动化部署加上良好的持续集成的纪律是这项工作的基础。(以上内容来自Marin Fowler的持续集成)写在最后“我的脑海中还是会浮现出第一段描述的早期软件项目。他们已经到了一个漫长项 目的末期(至少他们期望如此),但还是不知道距离真正的结束有多远。”这是来自Martin Fowler曾经历过的感受。而文中的第二段的那些开发们的“怒气”是笔者从十年前做开发的时候,所经历过的几个团队所发生过的。在集成的过程中,总会有种种无法预测的事情发生,不论是人还是事,你根本无法预测其进展从而很容易进入到迷茫地带,每一个处在迷茫地带的人都很难去做到轻松应对,久而久之开发人员会产生疲于奔命之感,导致团队无法凝聚成“拳头”打出强有力的一拳。基于这种情况,笔者认为这正是我们引入持续集成的原因所在。笔者认为Martin Fowler关于持续集成的落地实践部分已经比较详尽完全可以用来大家公共参考学习,所以没有在关公面前耍大刀,故引用于此文章。但是在我们持续集成实际的过程中一定会遇到很多问题,比如提升build效率的分段build策略或者其他实际的需求等,这都需要我们在日常工作中,通过迭代不断的来研究和完善其实践的方法,并在回顾的过程中加以讨论、分析总结,最终提升团队的研发效率。也可以使用一些大厂如华为云DevCloud作为持续集成的工具,其提供专业的一站式解决方案,方便了中小企业的DevOps落地。文章博客地址:https://bbs.huaweicloud.com/blogs/196464
  • [华为动态] 华为云应用平台ROMA融入全栈创新力量 助力企业应用数字化转型
    【中国,8月26日】华为云TechWave企业应用数字化专题日成功举办,华为云多位应用平台专家分享了华为自身多年数字化转型的探索和实践,深度解读应用平台ROMA的技术能力,并正式发布低代码开发平台ROMA AppCube。此外,深圳竹云科技、浙江讯盟科技分享了基于华为云ROMA助力企业数字化转型的技术实践。华为开放自身数字化实践助力全行业高效数字化转型华为云TechWave企业应用数字化专题日高端对话,IDC副总裁兼首席分析师武连峰、华为云应用平台领域总裁徐峰、华为云应用平台领域副总裁康宁等围绕“华为云应用平台ROMA使能全行业高效数字化转型”话题进行交流。IDC副总裁兼首席分析师武连峰表示:“ 数字化转型2.0时代下,加速实现模块化创新是核心,数字化转型已经变成企业的一个核心战略,这势必需要数字应用平台的支持。华为云专家分享了华为云应用平台ROMA是如何助力华为数十年的数字化转型变革、差异化竞争优势、给行业用户带来的价值及案例。”华为云TechWave企业应用数字化专题日高端对话华为从2003年开始启动了自身数字化转型的征程,数字化转型关键在于逐步重构出基于云服务的新型企业应用。在数字化转型过程中,华为面临IT建设如何支持华为全球业务的快速发展和扩张、如何保证传统业务系统和新业务系统的互联互通、如何实现业务系统的快速适应业务变化等困难。为此,华为公司打造了统一的IT数字化平台,端到端支撑华为公司。华为历经多年的探索和实践,陆续改造了1300多个企业应用上云,并将这些企业应用从开发、上线、运营到下架全生命周期管理的经验承载到了ROMA平台。对外提供服务以来,ROMA在各个行业取得了显著成绩,包括园区、电力、金融、交通等很多TOP级客户的鼎力推荐。面对行业数字化转型新的需求,华为云将ROMA升级,发布华为云应用平台ROMA,并提出了统筹治理、共建共享、立而不破,敏捷可信四个关键成功要素,使能行业高效率的数字化转型。企业如何实现数字化转型,华为云应用平台领域总裁徐峰建议“ 在数字化转型的道路上,要有自上而下的战略决心,去面对组织、业务、系统等的调整。在战略维度上坚定地投资数字化转型。”华为云ROMA赋能应用加速创新华为云应用平台ROMA聚焦数字化资产全生命周期治理,支持企业集成多类型应用及数据,为政企客户提供应用的开发、托管、运维和集成一站式能力,帮助客户构筑数字化应用平台,赋能应用,加速创新。会上,华为云正式发布Low Code/No Code开发模式- ROMA AppCube, ROMA AppCube源自华为数字化转型的最佳实践,能为企业提供全员参与应用开发、构建自主技术平台敏捷开发、预置30+组件和多种编排能力、云上开发和多端发布等能力,帮助客户沉淀行业资产和构建行业生态,使能各行各业,低成本的快速构建应用。 ROMA Factory聚焦全流程DevOps、全场景微服务、全生命周期API管理和Low Code/No Code四大能力,打通研发态、运行态、运维态,满足企业多种应用简单、敏捷的开发上线。 ROMA Connect融合集成平台,打破数据孤岛,连接企业一切应用与数据,实现跨云、跨地域集成,达到内部互通、内外互通、多云互通,简化上云,消除数字鸿沟,驱动企业数字化转型,连接合作伙伴。 ROMA Service Core聚焦重点行业场景提供的公共服务能力的合集,帮助客户和伙伴高效构建精品应用和解决方案。深圳竹云科技有限公司董事长董宁表示:“ 基于ROMA Service Core技术,竹云联合华为打造安全可信的行业解决方案,统一入口、鉴权、身份管理和AI生物认证,为政府、企业数字化转型提供端到端安全和可信支持。”浙江讯盟科技有限公司CTO 俞小浩表示:“ 基于ROMA Service Core-OneMobile架构,在赋能政企数字化的移动平台领域,华为联合讯盟科技打造移动使能能力,引入各类主流行业生态伙伴,提升客户办公与生产效率,支撑数字化转型成功。” 华为云区块链服务BCS推出数据可信共享解决方案,基于区块链等技术实现共享前数据发布,共享过程中申请授权,以及数据共享完成后评价等动作的可信追溯和记录,利用ROMA实现应用集成和数据高效共享。目前,华为云应用平台ROMA已落地政务、电力、交通、财政、金融等各9大行业,服务2000+家政企,15万+应用连接,成功助力政企和行业实现数字化转型。未来,华为云应用平台ROMA将聚焦数字化资产治理,使能行业、大型政企资产复用和数字化转型,与伙伴一起重塑传统政企上云路径,真正实现“条条大路”通云端。2020年9月23-26日,华为将于上海举办第五届HUAWEI CONNECT,携手来自全球的业界思想领袖、商业精英、技术大咖、先锋企业、生态合作伙伴、应用服务商以及开发者等,共同探讨行业数字化的发展方向,展示ICT领域的领先技术、产品和解决方案,分享成功实践,构筑开放、共赢的健康产业生态,共创行业新价值。
  • [技术干货] 【转载】项目管理之敏捷开发之道(三)
    项目管理之敏捷开发之道(三)
  • [技术干货] 【转载】项目管理之敏捷开发之道(二)
    项目管理之敏捷开发之道(二)
  • [技术干货] 【转载】项目管理之敏捷开发之道(一)
    敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。 敏捷开发原则 敏捷建模(AM)定义了一系列的核心原则和辅助原则,它们为软件开发项目中的建模实践奠定了基石。其中一些原则是从XP中借鉴而来,在Extreme Programming Explained中有它们的详细描述。而XP中的一些原则又是源于众所周知的软件工程学。复用的思想随处可见!基本上,本文中对这些原则的阐述主要侧重于它们是如何影响着建模工作;这样,对于这些借鉴于XP的原则,我们可以从另一个角度来看待。核心原则 ◆主张简单当从事开发工作时,你应当主张最简单的解决方案就是最好的解决方案。不要过分构建(overbuild)你的软件。用AM的说法就是,如果你现在并不需要这项额外功能,那就不要在模型中增加它。要有这样的勇气:你现在不必要对这个系统进行过分的建模(over-model),只要基于现有的需求进行建模,日后需求有变更时,再来重构这个系统。尽可能的保持模型的简单。◆拥抱变化需求时刻在变,人们对于需求的理解也时刻在变。项目进行中,Project stakeholder可能变化,会有新人加入,也会有旧人离开。Project stakeholder的观点也可能变化,你努力的目标和成功标准也有可能发生变化。这就意味着随着项目的进行,项目环境也在不停的变化,因此你的开发方法必须要能够反映这种现实。◆你的第二个目标是可持续性即便你的团队已经把一个能够运转的系统交付给用户,你的项目也还可能是失败的--实现项目投资者的需求,其中就包括你的系统应该要有足够的鲁棒性(robust ),能够适应日后的扩展。就像Alistair Cockburn常说的,当你在进行软件开发的竞赛时,你的第二个目标就是准备下一场比赛。可持续性可能指的是系统的下一个主要发布版,或是你正在构建的系统的运转和支持。要做到这一点,你不仅仅要构建高质量的软件,还要创建足够的文档和支持材料,保证下一场比赛能有效的进行。你要考虑很多的因素,包括你现有的团队是不是还能够参加下一场的比赛,下一场比赛的环境,下一场比赛对你的组织的重要程度。简单的说,你在开发的时候,你要能想象到未来。◆递增的变化和建模相关的一个重要概念是你不用在一开始就准备好一切。实际上,你就算想这么做也不太可能。而且,你不用在模型中包容所有的细节,你只要足够的细节就够了。没有必要试图在一开始就建立一个囊括一切的模型,你只要开发一个小的模型,或是概要模型,打下一个基础,然后慢慢的改进模型,或是在不在需要的时候丢弃这个模型。这就是递增的思想。◆令投资最大化你的项目投资者为了开发出满足自己需要的软件,需要投入时间、金钱、设备等各种资源。投资者应该可以选取最好的方式投资,也可以要求你的团队不浪费资源。并且,他们还有最后的发言权,决定要投入多少的资源。如果是这些资源是你自己的,你希望你的资源被误用吗。◆有目的的建模对于自己的产出,例如模型、源代码、文档,很多开发人员不是担心它们是否够详细,就是担心它们是否太过详细,或担心它们是否足够正确。你不应该毫无意义的建模,应该先问问,为什么要建立这个产出,为谁建立它。和建模有关,也许你应该更多的了解软件的某个方面,也许为了保证项目的顺利进行,你需要和高级经理交流你的方法,也许你需要创建描述系统的文档,使其他人能够操作、维护、改进系统。如果你连为什么建模,为谁建模都不清楚,你又何必继续烦恼下去呢?首先,你要确定建模的目的以及模型的受众,在此基础上,再保证模型足够正确和足够详细。一旦一个模型实现了目标,你就可以结束工作,把精力转移到其它的工作上去,例如编写代码以检验模型的运作。该项原则也可适用于改变现有模型:如果你要做一些改变,也许是一个熟知的模式,你应该有做出变化的正确理由(可能是为了支持一项新的需求,或是为了重构以保证简洁)。关于该项原则的一个重要暗示是你应该要了解你的受众,即便受众是你自己也一样。例如,如果你是为维护人员建立模型,他们到底需要些什么?是厚达500页的详细文档才够呢,还是10页的工作总览就够了?你不清楚?去和他们谈谈,找出你想要的。◆多种模型开发软件需要使用多种模型,因为每种模型只能描述软件的单个方面,“要开发现今的商业应用,我们该需要什么样的模型?”考虑到现今的软件的复杂性,你的建模工具箱应该要包容大量有用的技术(关于产出的清单,可以参阅AM的建模工件)。有一点很重要,你没有必要为一个系统开发所有的模型,而应该针对系统的具体情况,挑选一部分的模型。不同的系统使用不同部分的模型。比如,和家里的修理工作一样,每种工作不是要求你用遍工具箱里的每一个工具,而是一次使用某一件工具。又比如,你可能会比较喜欢某些工具,同样,你可会偏爱某一种模型。有多少的建模工件可供使用呢,如果你想要了解这方面的更多细节,我在Be Realistic About the UML中列出了UML的相关部分,如果你希望做进一步的了解,可以参阅白皮书The Object Primer -- An Introduction to Techniques for Agile Modeling。◆高质量的工作没有人喜欢烂糟糟的工作。做这项工作的人不喜欢,是因为没有成就感;日后负责重构这项工作(因为某些原因)的人不喜欢,是因为它难以理解,难以更新;最终用户不喜欢,是因为它太脆弱,容易出错,也不符合他们的期望。◆快速反馈从开始采取行动,到获得行动的反馈,二者之间的时间至关紧要。和其他人一共开发模型,你的想法可以立刻获得反馈,特别是你的工作采用了共享建模技术的时候,例如白板、CRC卡片或即时贴之类的基本建模材料。和你的客户紧密工作,去了解他们的的需求,去分析这些需求,或是去开发满足他们需求的用户界面,这样,你就提供了快速反馈的机会。◆软件是你的主要目标软件开发的主要目标是以有效的方式,制造出满足投资者需要的软件,而不是制造无关的文档,无关的用于管理的工件,甚至无关的模型。任何一项活动(activity ),如果不符合这项原则,不能有助于目标实现的,都应该受到审核,甚至取消。◆轻装前进你建立一个工件,然后决定要保留它,随着时间的流逝,这些工件都需要维护。如果你决定保留7个模型,不论何时,一旦有变化发生(新需求的提出,原需求的更新,团队接受了一种新方法,采纳了一项新技术...),你就需要考虑变化对这7个模型产生的影响并采取相应的措施。而如果你想要保留的仅是3个模型,很明显,你实现同样的改变要花费的功夫就少多了,你的灵活性就增强了,因为你是在轻装前进。类似的,你的模型越复杂,越详细,发生的改变极可能就越难实现(每个模型都更“沉重”了些,因此维护的负担也就大了)。每次你要决定保留一个模型时,你就要权衡模型载有的信息对团队有多大的好处(所以才需要加强团队之间,团队和项目投资者之间的沟通)。千万不要小看权衡的严重性。一个人要想过沙漠,他一定会携带地图,帽子,质地优良的鞋子,水壶。如果他带了几百加仑的水,能够想象的到的所有求生工具,一大堆有关沙漠的书籍,他还能过得去沙漠吗?同样的道理,一个开发团队决定要开发并维护一份详细的需求文档,一组详细的分析模型,再加上一组详细的架构模型,以及一组详细的设计模型,那他们很快就会发现,他们大部分的时间不是花在写源代码上,而是花在了更新文档上。宣言原则 最重要的是通过尽早和不断交付有价值的软件满足客户需要。我们欢迎需求的变化,即使在开发后期。敏捷过程能够驾驭变化,保持客户的竞争优势。经常交付可以工作的软件,从几星期到几个月,时间尺度越短越好。业务人员和开发者应该在整个项目过程中始终朝夕在一起工作。围绕斗志高昂的人进行软件开发,给开发者提供适宜的环境,满足他们的需要,并相信他们能够完成任务。在开发小组中最有效率也最有效果的信息传达方式是面对面的交谈。可以工作的软件是进度的主要度量标准。敏捷过程提倡可持续开发。出资人、开发人员和用户应该总是维持不变的节奏。对卓越技术与良好设计的不断追求将有助于提高敏捷性。简单——尽可能减少工作量的艺术至关重要。最好的架构、需求和设计都源自自我组织的团队。每隔一定时间,团队都要总结如何更有效率,然后相应地调整自己的行为。敏捷成功之道 随机应变 要达到敏捷的成功—交付支撑业务的最佳软件—软件专家也可以引用这些规则。自主权 专注于工作,交付正确的软件,而不是被他人的愤怒情绪所影响。分享经验 构建完美软件开发流程,并没有统一的模式。但是在这个领域,敏捷技术,加上持续的应用和改进,都能够达到敏捷的成功。敏捷开发相关工具 Visual Studio Team Foundation ServerTFS,即团队基础服务器是微软应用程序生命周期管理服务器,用于帮助团队在Visual Studio的协作开发。最近,它进有了升级包括工作项目执行改进、富文本编辑器的改进,以及富文本编辑器中改善的超链接体验。 TFS中的Kanban面板也做了改善,提升了可以录入和跟踪的项目数量,该服务器现在有一个“利益相关者”许可,来规范服务器的访问权限。Atlassian JiraAtlassian的是一个很流行的工具,主要用于跟踪产品开发、帮助团队整理问题、安排工具,以及记录团队行为。它Jira Agile插件使开发人员更容易部署关键敏捷策略,这包括用户故事开发、冲刺模块构建,以及可视化的团队活动。AxosoftAxosoft以前被称为Axosoft OnTime Scrum,这一软件套件有四个功能模块:Scrum、Bug追踪器、帮助台和Wiki。它是基于HTML5构建的,帮助开发团队管理待办事项列表、发布和冲刺,带有燃尽图功能,有一个 管理仪表板用于跟踪编码和修改BUG的时间。LeanKit使用 LeanKit的团队可以看到工作负载的分布并导出历史数据。最近 LeanKit 进行了一次升级,包含单点登录功能 和附加报告功能,从而提供更细粒度的数据详细信息。PlanboxPlanbox 敏捷管理工具通过燃尽图跟踪进程,集成客户反馈,它的目标人群很广泛。最近它对应用的前端和后端都做的升级,添加了更强大的报告功能和新仪表盘,来提升项目速度。时间跟踪特性和工具允许用户得到所有他们在Planbox产生的数据。敏捷开发实践 敏捷建模(AM)在AM原则的基础上定义了一组核心实践(practice)和补充实践,其中的某些实践已经是极限编程(XP)中采用了的,并在 Extreme Programming Explained一书中有详细的论述,和AM的原则一样,我们在描述这组实践时,将会注重于建模的过程,这样你可以从另外一个角度来观察这些已或XP采用的素材。核心实践◆Stakeholder的积极参与 我们对XP的现场客户(On-Site Customer)的概念做了一个扩充:开发人员需要和用户保持现场的接触;现场的用户要有足够的权限和能力,提供建构中的系统相关的信息;及时、中肯的做出和需求相关的决策;并决定它们的优先级。AM把XP的“现场客户”实践扩展为“使project stakeholder积极参与项目”,这个project stakeholder的概念包括了直接用户、他们的经理、高级经理、操作人员、支持人员。这种参与包括:高级经理及时的资源安排决策,高级经理的对项目的公开和私下的支持,需求开发阶段操作人员和支持人员的积极参与,以及他们在各自领域的相关模型。◆正确使用artifact 每个artifact都有它们各自的适用之处。例如,一个UML的活动图(activity diagram)适合用于描述一个业务流程,反之,你数据库的静态结构,最好能够使用物理数据(physical data)或数据模型(persistence model)来表示。在很多时候,一张图表比源代码更能发挥作用,一图胜千言,同样,一个模型也比1K的源代码有用的多,前提是使用得当(这里借用了 Karl Wieger的Software Requirements中的词汇)。因为你在研究设计方案时,你可和同伴们和在白板上画一些图表来讨论,也可以自己坐下来开发一些代码样例,而前一种方法要有效的多。这意味着什么?你需要了解每一种artifact的长处和短处,当你有众多的模型可供选择的时候,要做到这一点可没有那么容易。◆集体所有制 只要有需要,所有人都可以使用、修改项目中的任何模型、任何artifact。◆测试性思维 当你在建立模型的时候,你就要不断的问自己,“我该如何测试它?”如果你没办法测试正在开发的软件,你根本就不应该开发它。在现代的各种软件过程中,测试和质保(quality assurance)活动都贯穿于整个项目生命周期,一些过程更是提出了“在编写软件之前先编写测试”的概念(这是XP的一项实践:“测试优先”)。◆并行创建模型 由于每种模型都有其长处和短处,没有一个模型能够完全满足建模的需要。例如你在收集需求时,你需要开发一些基本用例或用户素材,一个基本用户界面原型,和一些业务规则。再结合实践切换到另外的Artifact,,敏捷建模者会发现在任何时候,同时进行多个模型的开发工作,要比单纯集中于一个模型要有效率的多。◆创建简单的内容 你应该尽可能的使你的模型(需求、分析、架构、设计)保持简单,但前提是能够满足你的project stakeholder的需要。这就意味着,除非有充分的理由,你不应该随便在模型上画蛇添足--如果你手头上没有系统认证的功能,你就不应该给你的模型增加这么一个功能。要有这样的勇气,一旦被要求添加这项功能,自己就能够马上做到。这和XP的实践“简单设计”的思想是一样的。◆简单地建模 当你考虑所有你能够使用的图表(UML图、用户界面图、数据模型等)时,你很快会发现,大部分时候你只需要这些图表符号的一部分。一个简单的模型能够展示你想要了解的主要功能,例如,一个类图,只要能够显示类的主要责任和类之间的关系就已经足够了。不错,编码的标准告诉你需要在模型中加入框架代码,比如所有的get和set操作,这没有错,但是这能提供多少价值呢?恐怕很少。◆公开展示模型 你应当公开的展示你的模型,模型的载体被称为“建模之墙”(modeling wall)或“奇迹之墙(wall of wonder)”。这种做法可以在你的团队之间、你和你的project stakeholder之间营造出开放诚实的沟通氛围,因为当前所有的模型对他们都是举手可得的,你没有向他们隐藏什么。你把你的模型贴到建模之墙上,所有的开发人员和project stakeholder都可以看建模之墙上的模型,建模之墙可能是客观存在的,也许是一块为你的架构图指定的白板,或是物理数据模型的一份打印输出,建模之墙也可能是虚拟的,例如一个存放扫描好的图片的internet网页。如果你想要多了解一些相关的资料,你可以看看Ellen Gottesdiener的Specifying Requirements With a Wall of Wonder。◆切换到另外的Artifact 当你在开发一个artifact(例如用例、CRC卡片、顺序图、甚至源码),你会发现你卡壳了,这时候你应当考虑暂时切换到另一个artifact。每一个artifact都有自己的长处和短处,每一个artifact都适合某一类型的工作。无论何时你发现你在某个artifact上卡壳了,没办法再继续了,这就表示你应该切换到另一个artifact上去。举个例子,如果你正在制作基本用例,但是在描述业务规则时遇到了困难,你就该试着把你的注意力转移到别的artifact上去,可能是基本用户界面原型、CRC模型,可能是业务规则、系统用例、或变化案例。切换到另一个artifact上去之后,你可能就立刻不再卡壳了,因为你能够在另一个artifact上继续工作。而且,通过改变你的视角,你往往会发现原先使你卡壳的原因。◆小增量建模 采用增量开发的方式,你可以把大的工作量分成能够发布的小块,每次的增量控制在几个星期或一两个月的时间内,促使你更快的把软件交付给你的用户,增加了你的敏捷性。◆和他人一起建模 当你有目的建模时你会发现,你建模可能是为了了解某事,可能是为了同他人交流你的想法,或是为了在你的项目中建立起共同的愿景。这是一个团体活动,一个需要大家有效的共同工作才能完成的活动。你发现你的开发团队必须共同协作,才能建立一组核心模型,这对你的项目是至关重要的。例如,为了建立系统的映像和架构,你需要和同组成员一起建立所有人都赞同的解决方案,同时还要尽可能的保持它的简单性。大多数时候,最好的方法是和另一些人讨论这个问题。◆用代码验证 模型是一种抽象,一种能够正确反映你正在构建的系统的某个方面的抽象。但它是否能运行呢?要知道结果,你就应该用代码来验证你的模型。你已经用一些HTML页面建立了接受付款地址信息的草图了吗?编码实现它,给你的用户展示最终的用户界面,并获取反馈。你已经做好了表示一个复杂业务规则逻辑的UML顺序图了吗?写出测试代码,业务代码,运行测试以保证你做的是对的。永远也别忘了用迭代的方法开发软件(这是大多数项目的标准做法),也别忘了建模只是众多任务中的一个。做一会儿建模、做一会儿编码、做一会儿测试(在其它的活动之中进行)。◆使用最简单的工具 大多数的模型都可以画在白板上,纸上,甚至纸巾的背面。如果你想要保存这些图标,你可以用数码相机把它们拍下来,或只是简单的把他们转录到纸上。这样做是因为大多数的图表都是可以扔掉的,它们只有在你画出模型并思考一个问题的时候才有价值,一旦这个问题被解决了它们就不再有意义了。这样,白板和标签往往成为你建模工具的最佳选择:使用画图工具来创建图表,给你重要的project stakeholder看。只有建模工具能够给我们的编程工作提供价值(例如代码自动生成)时才使用建模工具。你可以这样想:如果你正在创建简单的模型,这些模型都是可以抛弃的。你建模的目的就是为了理解,一旦你理解了问题,模型就没有存在的必要了,因此模型都是可以丢弃的,这样,你根本就不必要使用一个复杂的建模工具。补充实践◆使用建模标准 这项实践是从XP的编码标准改名而来,基本的概念是在一个软件项目中开发人员应该同意并遵守一套共同的建模标准。遵守共同的编码惯例能够产生价值:遵守你选择的编码指南能够写出干净的代码,易于理解,这要比不这么做产生出来的代码好得多。同样,遵守共同的建模标准也有类似的价值。可供选择的建模标准有很多,包括对象管理组织(OMG)制定的统一建模语言ML),它给通用的面向对象模型定义了符号和语义。UML开了一个好头,但并不充分-就像你在Be Realistic About The UML中看到的,UML并没有囊括所有可能的的建模artifact。而且,在关于建立清楚可看的图表方面,它没有提供任何建模风格指南。那么,风格指南和标准之间的差别在何处呢。对源代码来说,一项标准可能是规定属性名必须以attributeName的格式,而风格指南可能是说在一个单元中的一段控制结构(一个if语句,一段循环)的代码缩进。对模型来说,一项标准可能是使用一个长方形对类建模,一项风格指南可能是图中子类需要放在父类的下方。◆逐渐应用模式 高效的建模者会学习通用的架构模式、设计模式和分析模式,并适当的把它们应用在模型之中。然而,就像Martin Fowler在Is Design Dead中指出的那样,开发人员应当轻松的使用模式,逐渐的应用模式。这反映了简单的价值观。换言之,如果你猜测一个模式可能适用,你应当以这样的方式建模:先实现目前你需要的最小的范围,但你要为日后的重构留下伏笔。这样,你就以一种可能的最简单的方式实现了一个羽翼丰满的模式了。就是说,不要超出你的模型。举一个例子,在你的设计中,你发现有个地方适合使用GoF的Strategy模式,但这时候你只有两个算法要实现。最简单的方法莫过于把算法封装为单独的类,并建立操作,能够选择相应的算法,以及为算法传递相关的输入。这是Strategy模式的部分实现,但你埋下了伏笔,日后如有更多的算法要实现,你就可以重构你的设计。并没有必要因为Strategy模式需要,就建立所有的框架。这种方法使你能够轻松的使用模式。◆丢弃临时模型 你创建的大部分的模型都是临时使用的模型--设计草图,低精度原型,索引卡片,可能架构/设计方案等等--在它们完成了它们的目的之后就再不能提供更多的价值了。模型很快就变得无法和代码同步,这是正常的。你需要做出决定:如果“同步更新模型”的做法能够给你的项目增添价值的话,那就同步更新模型;或者,如果更新它们的投入将抵消它们能够提供的所有价值(即负收益),那就丢弃它们。◆合同模型要正式 在你的系统需要的信息资源为外部组织所控制的时候,例如数据库,旧有系统和信息服务,你就需要合同模型。一个合同模型需要双方都能同意,根据时间,根据需要相互改变。合同模型的例子有API的细节文档,存储形式描述,XML DTD或是描述共享数据库的物理数据模型。作为法律合同,合同模型通常都需要你投入重要资源来开发和维护,以确保它的正确、详细。你的目标是尽量使你系统的合同模型最少,这和XP的原则traveling light是一致的。注意你几乎总是需要电子工具来建立合同模型,因为这个模型是随时需要维护的。◆为交流建模 建模的次要原因是为了和团队之外的人交流或建立合同模型。因为有些模型是给团队之外的客户的,你需要投入时间,使用诸如文字处理器,画图工具包,甚至是那些“被广告吹得天花乱坠”的CASE工具来美化模型。◆为理解建模 建模的最重要的应用就是探索问题空间,以识别和分析系统的需求,或是比较和对照可能的设计选择方法,以识别可能满足需求的、最简单的解决方案。根据这项实践,你通产需要针对软件的某个方面建立小的、简单的图表,例如类的生命周期图,或屏幕顺序,这些图表通常在你完成目的(理解)之后就被丢弃。◆重用现有的资源 这是敏捷建模者能够利用的信息财富。例如,也许一些分析和设计模式适合应用到系统上去,也许你能够从现有的模型中获利,例如企业需求模型,业务过程模型,物理数据模型,甚至是描述你用户团体中的系统如何部署的模型。但是,尽管你常常搜索一些比较正确的模型,可事实是,在大多数组织中,这些模型要么就不存在,要么就已经过期了。◆非到万不得已不更新 你应当在你确实需要时才更新模型,就是说,当不更新模型造成的代价超出了更新模型所付出的代价的时候。使用这种方法,你会发现你更新模型的数量比以前少多了,因为事实就是,并不是那么完美的模型才能提供价值的。我家乡的街道图已经使用了5年了,5年我自己街道并没有改变位置,这张地图对我来说还是有用的。不错,我可以买一张新地图,地图是每年出一次的,但为什么要这么麻烦呢?缺少一些街道并没有让我痛苦到不得不投资买一份新地图。简单的说,当地图还管用的时候,每年花钱买新地图是没有任何意义的。为了保持模型、文档和源代码之间的同步,已经浪费了太多太多的时间和金钱了,而同步是不太可能做到的。时间和金钱投资到新的软件上不是更好吗?确实不错的主意以下的实践虽然没有包括在AM中,但是可以做为AM的一份补充:◆重构 这是一项编码实践。重构,就是通过小的变化,使你的代码支持新的功能,或使你的设计尽可能的简单。从AM的观点来看,这项实践可以保证你在编码时,你的设计干净、清楚。重构是XP的一个重要部分。◆测试优先设计 这是一项开发实践。在你开始编写你的业务代码之前,你要先考虑、编写你的测试案例。从AM的观点来看,这项实践强制要求你在写代码之前先通盘考虑你的设计,所以你不再需要细节设 计建模了。测试优先设计是XP的一个重要部分。敏捷开发名词详解 AM是一种态度,而不是一个说明性的过程。AM是敏捷建模者们坚持的价值观、敏捷建模者们相信的原则、敏捷建模者们应用的实践组成的集合。AM描述了一种建模的风格。当它应用于敏捷的环境中时,能够提高开发的质量和速度,同时能够避免过度简化和不切实际的期望。AM可不是开发的“食谱”,如果你寻觅的是一些细节的指导,如建立UML顺序图或是画出用户界面流图,你可以看看在建模Artifacts中列出的许多建模书籍,我特别推荐我的书The Object Primer 2/e(尽管这有失公允)。AM是对已有方法的补充,而不是一个完整的方法论。AM的主要焦点是在建模上,其次是文档。也就是说,AM技术在你的团队采用敏捷方法(例如eXtreme Programming,Dynamic Systems Development Method (DSDM),Crystal Clear)的基础上能够提高建模的效果。AM同样也可以用于那些传统过程(例如Unified Process),尽管这种过程较低的敏捷性会使得AM不会那么成功。AM是一种有效的共同工作的方法,能够满足Project Stakeholder的需要。敏捷开发者们和Project Stakeholder进行团队协作,他们轮流在系统开发中扮演着直接、主动的角色。在“敏捷”的字典中没有“我”这个单词。AM是有效的,而且也已开始有效。当你学习到更多的AM知识时,有件事对你来说可能不好接受,AM近乎无情的注重有效性。AM告诉你:要使你的 Project Stakeholder的投资最大化;当有清晰的目的以及需要了解受众的需要时要建立模型或文档;运用合适的工件来记录手头的情形;不论何时都尽可能创建简单的模型。AM不是灵丹妙药。敏捷建模是改进众多专家软件开发成果的有效技术,充其量也就是这样了。它并不是什么了不得的灵丹妙药,能够解决你开发中的所有问题。如果你努力的工作;如果你专注其上;如果打心眼儿里接受它的价值观、它的原则、它的实践;你就可以改进你做为一个开发人员的效果。AM是面向一般的开发人员的,但并不是要排斥有能力的人。AM的价值观、原则和实践都简单易懂,其中的很多内容,可能你都已经采用或期待多年了。应用AM技术并不是要你去练水上飘,但你需要有一些基本的软件开发技能。AM最难的就是它逼着你去学习更广泛的建模技术,这是个长期的、持续性的活动。学习建模在一开始可能很难,但你可以试着一次学习一样技术来完成你的学习。AM并不是要反对文档。文档的创建和维护都会增大项目涉众的投资。敏捷文档尽可能的简单,尽可能的小,目的只集中在和开发的系统有直接关系的事情上,充分了解受众的需要。AM也不是要反对CASE工具。敏捷建模者使用那些能够帮助开发人员提高效果,提升价值的工具。而且,他们还尽力使用那些能够胜任工作的最简单的工具。何时是敏捷的?要想了解AM,你需要了解模型和敏捷模型之间的区别。模型是一个抽象的概念,它描述了一个的问题的一个或多个方面,或是处理这个问题可能的解决方案。传统意义上,模型被认为是图表加上相应的文档。然而那不够直观的artifact,也可以被视为模型,例如CRC卡片集,单条或多条业务规则的文字描述,或是业务流程的一段结构化英文描述。一个敏捷模型就是一个刚刚足够好的模型。但是你怎么知道什么时候模型才是刚刚足够好呢?当敏捷模型显现出如下的特性时,它就是刚刚足够好的:敏捷模型实现了它们的目的。有时你为沟通而建模,或许你需要把你工作的范围告诉高级经理;有时你为理解而建模,或许你需要确定一个设计策略,实现一组Java类。一个敏捷模型是否足够好,要看它是不是满足了创建它时的初衷。敏捷模型是可理解的。敏捷模型要能为其预期听众所理解。使用用户能够理解的业务语言来描述需求模型,反之,技术架构模型则需要使用开发人员熟悉的技术术语。你所使用的建模符号会影响易懂性--如果你的用户不了解UML用例图中的符号的含义,那用例图对用户就没有任何价值。这样的话,要么使用另一种方法,要么教授用户学习建模技术。风格问题同样也会影响易懂性,例如避免交叉线。杂乱的图表比清晰的图表难懂。模型的细节程度(见下文),也会影响易懂性,因为相较一个不那么详细的模型来说,一个过于详细的模型要难于理解。简单(见下文)同样是影响易懂性的一个因素。敏捷开发敏捷模型是足够正确的。模型通常都不需要100%正确,只要足够正确就行了。举个例子,如果一张街道地图漏画了一条街道,或是它标示某条街道是通行的,但你发现它已经关闭维修了,那你会不会扔掉你的地图开始在城里飙车犯罪呢?不太可能。你会考虑更新你的地图,你可能会拿出笔来自己做修改或是去当地的商店买一张最新版的地图(你原来的那张过期了)。也许你还是会接受那张虽不完美但仍可使用的地图,因为它对你来说已经足够好了。你还是可以用这张地图四处转转,因为它还是个正确的模型,标记出了大部分街道的位置。你在发现这张地图不正确的时候,你没有立刻扔掉它,原因是你根本不在乎它是否完美。类似的,当你在需求模型、数据模型中发现错误的时候,你也会选择更新或是接受--虽不完美但已经足够好了。有些项目成员能够容忍这种不正确而有些则不能:这取决于项目的特性,每个团队成员的特性,组织的特性。充分正确性既和模型的听众有关,也和你要处理的问题有关。敏捷模型是足够一致的。一个敏捷模型并不需要和自己(或其它有用的artifact)保持完全的一致。如果一个用例在它的一个步骤中显式的调用了另一个用例,那么相应的用例图需要用UML的 <> 版型来标记这两个用例之间的关系。然而,你看了看图表,发现它们并没有这样做,天哪!用例和图之间不一致!危险!太危险了!红色警报!快逃命呀!等一下,你的用例模型是有不一致的地方,但也没到世界末日啊。是的,理想情况下,你的所有artifact最好是能够完全一致,但这通常是不可能的。当我开发一个简单的商用系统时,我通常都可以容忍部分的不一致。但有时我是不能容忍这种不一致的。最有力的佐证就是1999年 NASA发射火星太空探测器时采用了精密的测量系统。要树立一个观点,敏捷模型只要足够一致就行了,你通常不需要使用那么完美的模型。关于正确性和一致性,很明显要考虑权衡问题。如果你要维护一个artifact(我们称之为“保管”),随着时间的流逝,你需要投入资源来更新它。否则它很快会就会过期,对你就没用了。例如,我可以容忍一张地图标错了一两条街道,但是我绝对无法容忍一张地图中四分之三的街道都标错了。这就需要权衡了,进行足够的努力,保证artifact足够正确。过多不必要的努力反而会减缓项目的进度,而投入不足就没有办法保证artifact的有效性。敏捷模型有足够的细节。一张路线图并不需要标记出每条街道上的每栋房子。那会有太多的细节,使得地图难以使用。然而,在修路的时候,我想施工人员一定会有这条街道的详细地图,包括每幢建筑、下水道、电线盒等足够的细节,这样的地图才是有用的。但是这张地图并不用标记出每个院子和通向它们的路线。因为这样又太繁琐了。足够的细节和听众有关,也和他们使用模型的目的有关--司机需要的是显示道路的地图,施工人员需要的是显示土木工程细节的地图。考虑一个架构模型,可能一组画在白板上的图表就足够了--项目的进行中再对它们更新,也许你需要用CASE 工具来生成一些图表,也许这些图表还需要有详细的文档,这依赖于环境。不同的项目有不同的需要。在每一个例子中,实际上你都是在开发、维护一个有足够的细节的架构模型,只是这个“足够的细节”的概念和环境有关。敏捷模型能提供正面价值。对项目中的任一artifact,一个基本的要求是它们能够提供正面价值。一个架构模型给你的项目带来的价值是不是能够超过开发它、维护它(可选)的总成本?一个架构模型能够坚定你们团队为之努力的愿景,所以它当然是有价值的。但是,如果它的成本超过了这个价值,那就是说,它无法提供正面价值。投入100,000美元去开发一个详细的、重量级的文档化架构模型,而它的效用,只需一些画在白板上的图表就能够达到,这些图只需要花你 5,000美元,看看,这是多么轻率的做法。敏捷模型要尽可能的简单。只要能够达到目的,你应当努力让你的模型尽可能保持简单。模型的详细程度会影响简单性,而所使用的符号范围也会影响简单性。例如,UML的类图就包括了无数的符号,包括对象约束语言 (Object Constraint Language OCL) ,但大多数的图使用符号的一部分就能够完成。所以你常常不需要使用所有的符号,你可以限制自己使用符号的一个子集,当然,这个子集是足够让你完成工作的。因此呢,一个敏捷模型的定义就是一个实现它的目的,没有画蛇添足的模型;为你的预期听众所理解的模型;简单的模型;足够正确、足够一致、足够详细的模型;创建和维护它的投资能够给项目提供正面价值的模型。一个普遍的哲学问题是源代码是不是一个模型,更重要的,它是不是一个敏捷模型。如果你是在我们这篇文章之外问我这个问题,我会回答说,是,源代码是一个模型,虽然是一个高度细节化的模型,因为它是软件的一个抽象。同时我还认为,优秀的代码是一个敏捷模型。但在这里,我还需要把两者区分开来,源代码和敏捷模型还是有区别的——敏捷模型帮助你得到源代码。敏捷开发建模者 敏捷建模者的个性Alistair Cockburn指出:很多的方法学都定义了软件开发项目中开发人员所担任的角色,同时还定义各个角色执行的任务,尽管入席,这些方法并没有定义这些角色最适合的人选。一个人要想成功的担任某个角色,他应当很好的适应它--虽然这并不需要人们掌握所有的技能,但人们必须要慢慢的熟悉这些技术。我的经验告诉我,要成为一个成功的敏捷建模者,下面的列出的个性是必要的:团队竞赛 第一点,也是最重要的一点,敏捷建模者总是积极的寻求协作,因为他们意识到他们不是万事通,他们需要不同的观点,这样才能做到最好。软件开发可不是游泳,单干是非常危险的。在敏捷的字典中没有“我”这个词。畅所欲言 敏捷建模者都有良好的沟通技巧--他们能够表达出他们想法,能够倾听,能够主动获取反馈,并且能够把需要的写出来。脚踏实地 敏捷建模者应当脚踏实地 他们的精力都集中在满足用户的需求上,他们不会在模型上画蛇添足,即便那双足是多么的好看。他们满足于提供可能的方案中最简单的一种,当然,前提是要能够完成工作。好奇 敏捷建模者乐衷于研究问题,解决问题。凡是都问个为什么敏捷建模者看问题从不会至于表面,而是会打破沙锅问到底。他们从不会就想当然的认为一个产品或一项技术和它们的广告上说的那样,他们会自己试一试。实事求是敏捷建模者都非常的谦逊,他们从不认为自己是个万事通,所以他们会在建立好模型之后,用代码来小心的证明模型的正确。根据实验敏捷建模者应当愿意尝试新的方法,例如一项新的(或是已有的)建模技术。一般而言,他们也会接受敏捷建模开发技术,必要时,为了验证想法,他们愿意同传统的思想做斗争,例如在一个项目中减少文档数量。有纪律要坚持不懈的遵循敏捷建模的实践。对你来说,你可能会在不经意间说,“加上这个功能吧!无伤大雅。”或是,“我比project stakeholder更了解。”在AM的道路上要想不偏离方向,是需要一定的纪律性的。
  • [技术干货] 敏捷团队的创新能力困境——利用“最小必要知识”,提升团队成员的跨域创造能力
    作者邹骏,上海惠艾信息科技有限公司敏捷咨询师。他具备16年的互联网和IT行业的产品管理和研发经验,曾先后就职于大唐电信、诺基亚中国、惠普、Tieto等IT公司,担任过架构师、项目管理、产品管理、研发顾问、产品总监等多种角色。2013年开始,他进入到互联网创业的浪潮中。将工作重点从敏捷研发转型转向了企业的精益创新、产品的互联网转型、运营,以及线上业务模式的探索实践。他以产品负责人和StartupCoach的身份,指导端到端产品团队在数字化转型领域实践精益创新的理念。数字化转型需要跨职能的特性团队随着互联网企业的崛起,对整个社会、经济带来了巨大的影响。吃了不少互联网企业的跨界降维打击的苦头之后,近几年各大领域的传统企业们,纷纷开始了一场轰轰烈烈的“数字化转型”运动,大有“锣鼓喧天,鞭炮齐鸣”之式,席卷华夏大地,愈演愈烈。说到“数字化”,那必然少不了科技的力量。在传统企业中,通常“业务”和“技术”各立山头,业务部门主要负责“开源”,而科技部门主要解决“节流”。换句话说,业务部门关注企业的产品、市场、运营问题,形成持续的商业模式为企业获取营收;科技部门利用IT设施,研发和集成线上化服务,一方面提升企业对外的规模化服务能力,一方面优化对内的组织运作效率,从而让企业能以更少的资源,获取更大的回报。但如今,科技的发展改变着人们的生活模式。随着用户流量和场景迁移到线上,规模化、扁平化、碎片化的用户特征,让线下业务的模式无法简单照搬到线上,传统企业的业务拓展在网络冲击下面临不少的挑战。而随着科技更新越来越快,新的产品和运营模式越来越五花八门,业务部门很难独自面对这巨大的市场变化,把业务和技术融合在一起,围绕科技来重新解构商业模式,才能更好地融入网络时代的商业形态(连街边的烧烤摊都用起了二维码菜单、建起了微信群,做起了CRM……)。这是企业转变的必经之路。毫无疑问,这个时代的企业要更加“敏捷”。打破部门壁垒、形成统一组织虽然不是敏捷的独自创新,但是,把市场、产品、运营、技术各部门角色集合在一起,形成端到端的“全职能特性团队”这一概念,确实是在2001年之后的敏捷转型浪潮中不断发扬光大,被各路企业借鉴和效仿。可惜敏捷只发掘了业务和技术融合的冰山的一角,很多企业组建了特性团队之后,却面临着困惑:业务、设计、架构、研发、测试,各路角色都有了,大家围坐在一起,除了交流更顺畅之外,和之前有什么区别呢?老板们也充满疑惑,“敏捷小组成立了,说好的创新在哪里?”“领域知识差异”是特性团队面临的一大障碍连左手事业、右手家庭,喜提过和谐号和波音七四七的微商们都早已明白答案,“人在一起叫团伙,心在一起才叫团队!”。把不同职位的人聚在一起工作,只是团队迈出的第一步。人心不齐,队伍断然是不好带的。要真正融合为一个有创造力的敏捷Team,横在特性团队成员们面前的,还有几座需要跨越的大山,其中一座,叫做领域知识差异。做业务的不懂技术,做技术的不懂业务,这几乎是当前社会分工的一个普遍现象。当然,随着社会分工的愈发精细化,术业各有专攻,一个人不可能精通行业所需技能的方方面面,但这也不应成为人们停止学习的借口。学海确实无涯,但事实上,理解一个问题所需的知识层面,和解决这个问题所需的知识层面是非常不同的。在你的非专业领域,只需要很少的知识,帮助你正常理解相关的问题概念,完成有效沟通即可。这样不但花费的额外学习时间会少得多,通过不断积累对专业上下游领域问题的理解,你的专业边界也在不断扩充,从而逐渐形成一个更加全面的视角,还能更好提升你在专业上的工作效率。最小必要知识李笑来在《财富自由之路》里面提出一个概念:最小必要知识。比如,做设计的最少必要知识是懂得两点:简洁、留白;学习英文的最少必要知识是了解字母、音标、基本语法,会查字典和使用搜索。对敏捷特性团队的成员来说,各自来自不同的组织,大家从不同工作领域汇聚到一起。用较少的时间,快速建立起各个角色领域沟通的最小必要知识,形成团队未来共同分析和讨论的基础共识,对特性团队的工作和协同效率来说,将是大有裨益的。同时,在团队内形成知识领域之间的跨界融合,会在极大程度上激发个体的创造思维,提升团队的融汇创新能力!其实在不少组织的敏捷转型过程中,已经在成员的能力融合方面迈出了第一步。敏捷特性团队成立以后,会定期举行各式各样的经验分享活动,涉及业务背景、设计知识、技术能力等多个方面的知识,希望通过这种形式,帮助特性团队成员在自身本职之外,扩展对上下游领域的理解,成长为优秀的复合型创新人才。遗憾的是,如果仅仅是“知识大杂汇”式的分享,粗旷地把多个领域的知识碎片堆积在一起,成员花费不少学习时间后,却难以真正形成到对团队工作有价值基础共识,导致知识共享学习逐渐沦为鸡肋。用“最小必要知识”,提升团队成员的跨域融合能力要做到高效的跨领域知识共享,建立特性团队的基础能力共识,应该按“最小必备知识”的原则,去针对性地设计不同内容。一个业务领域的最小必备知识是什么?用户是谁,他们有什么特征?我们的业务解决用户的什么问题?我们通常如何吸引新用户的关注?他们担心的问题常常有哪些,我们在业务产品中如何去思考这些问题的?我们如何服务好我们的现存客户的?业务开展有什么考量的限制条件?套用一个时髦的用语,这就是我们业务架构的框架雏形。而技术领域的最小必备知识呢?试试从系统基础架构开始,拿出一个真实的业务实现场景案例,上层的UI展现如何达成的,常见问题是什么?业务逻辑层的设计理念是怎样,业务之间关联性最大的部分在哪里,开发过程中常常遇到什么坑?底层数据为什么要这么存储,数据查询修改的难点在哪里?我们的系统里面常常提到的技术概念是什么,业务常见十大问题是什么?在敏捷的理念中,强调团队自组织的方式,去涌现出团队自身的工作和成长方法,团队的学习社区建设也通常是由下而上的方式,调动普通成员的积极性来贡献话题。但是凡事都有两面性,至下而上同样也是导致知识碎片化的重要因素。烧出一锅好菜的最小必备知识是什么?食材搭配、火候控制,还有佐料配比?对厨艺领域的专家人士来说,这些答案可能是肤浅可笑的,在他们的心中早已有一套完整的框架体系,给出最小必备知识只是信手拈来的事情(但表达能力可能是个坎)。而对于这个领域的新手和还在实践中成长的人,没有自己实践总结出的完整体系,要设计出最小必备的知识框架,是非常困难的事情。所以,好的团队知识共享,并不是简单地知识堆积,还需要这个领域专家的上层设计。在团队中高手往往又是紧缺资源,要面临各种重要不紧急或者重要且紧急的事情,而组织内的知识共享和能力建设,又容易被当成“不重要(相对于KPI而言)且不紧急”那类事情。要让团队内的专家抽出时间来,帮助整个团队建立最小必备知识框架,是留给团队管理者的一道重要的思考题。加强团队的能力培养不应该成为一句口号,而应该把建立团队内思考框架和共识、提升成员的跨域协作能力作为团队管理的正式目标,甚至有效地融合到团队的目标管理机制当中去,为建设一支真正跨职能、有创造性的“特性团队”打下坚实的基础。
  • [分享交流] Wings企业级单元测试自动编码引擎白皮书
    第一章Wings企业级单元测试自动编码引擎诞生的背景 (附Wings讲解视频和白皮书pdf下载)随着科技的飞速发展,软件系统越来越复杂,在系统测试阶段不断遇到的瓶颈,迫使行业逐步追根溯源到了单元测试阶段。软件缺陷发现得越晚,其处理费用就越呈几何激增,因此测试左移概念已经成为趋势。单元测试面临的最大问题是单元测试用例编写工作量巨大,极端情况下与开发工作量比达到1:1,甚至更高,这使大部分开发团队要么主动忽视单元测试,要么象征性的走个流程。如果可以让计算机先对被测试程序进行全局分析和深度理解,再由计算机进行全自动的完成单元测试编码,同时还能确保自动编写的代码无语法、语义错误的直接运行起来,这种用计算机智能算法全自动产生的测试编码去验证开发人员编写的源代码逻辑输入输出对错的高端测试模式,无疑是未来软件测试领域最为璀璨的“明珠”技术。国外软件诸如c++ test完成了这个领域的初步技术探索,星云测试研发的Wings(目前商用产品支持c/c++程序)产品,则大踏步完成了整体技术跨越和多方商用落地验证。Wings可以对程序参数进行深度解析,比如c++类、模板类、数组、结构体、指针、链表以及任意复杂结构的层级嵌套,同时对于面向对象的程序特性以及常用的容器库,能够完美识别和支持。对于一些void*、函数指针、模板类等无法直接静态分析进行类型确定的特殊情况,均有基于人工智能的程序分析辅助进行类型确定。Wings在基于深度参数解析的基础上,对于全局范围的程序进行理解分析后,第一步 按照内置规则,自动化构建被测程序的输入用例代码;第二步 构建测试代码用于调用被测程序的源代码;第三步 构建被测程序输出断言,完成调用被测试程序单元的全部环境准备。这个构建速度非常快,可以达到每分钟100万行左右的生成速度,编写的代码比程序开发人员手工编写的规范度高出一截,并确保100% 的语法语义正确,免去大量的调试时间。在驱动数据上,Wings实现了驱动代码和数据的分离。Wings基于深度参数解析基础上,可以根据参数的结构自动生成层级嵌套的测试数据结构,用图形界面可视化的展示给用户。用户只需要根据Wings提供的界面向导对测试数据进行填充即可,驱动程序会自动识别并读取这些数据,完成对被测试程序的调用。Wings还可以全自动生成参数捕获程序,并自动插装在被测试程序中。当被测试程序运行后,可以通过专用软件捕获程序中每个函数模块运行的具体参数值。Wings的测试代码驱动自动生成和参数捕获,相当于完成了一种全智能的闭环测试验证体系。Wings使测试数据不需要人工准备,只需要在前序轮次中通过参数捕获自动存储。若前序测试用例运行正常,那么这些数据都可以作为后续测试输入和进行校验的基础数据。第二章 单元测试自动生成技术2.1 测试左移后单元测试面临的问题测试左移后,传统的单元测试一般面临很多问题,主要如下:(1) 传统程序级测试用例的编写会耗费开发人员大量的工时,比如TDD测试驱动开发里面的单元测试无法有效实施,导致所有测试几乎全部依赖于系统级黑盒测试。程序级测试用例的开发成本是功能实现代码本身时间至少为1:1,绝大部分企业选择放弃开发程序级测试,而采用系统级测试方法。(2)     需求发生变化导致程序实现发生变化后,程序集用例也需要发生变化,和自动化面临的问题一样,单元测试本身的可维护性问题导致投入是持续的而不是一次性的,会打消其企业应用的热情。(3)     很多单元在未组装成系统的时候切入,如果需要进行测试需要进行大量的mock操作或者桩模拟,这个过程会造成单元测试的不精确性。(4)     程序集测试数据量很大,全部需要用户来进行准备无法全自动从前序系统测试过程中获取。      针对以上问题,很多业内人士提出了很多办法,例如自动生成测试用例、自动构建测试驱动、模糊测试方法等诸多方式,但是实际开发中程序输入参数十分复杂,简单的输入已经不能满足,如何能够构建复杂的参数输入,是要解决的重要问题。因此,星云测试研发了Wings产品--单元级的自动编码引擎,它不仅能够自动构建测试驱动,还能处理十分复杂的大型程序参数,帮助企业能够更好的进行单元测试。2.2 完成单元测试要素构成单元测试的要素如下:a.        测试数据b.        测试驱动代码例如针对以下程序,需要准备的测试输入以及测试代码① 全局变量:c② 参数:a、b③ 预期输出:320 30 int c = 100; int sum(int a, int b) {      return a + b + c; } int driver_sum() {      int a = 100, b = 20;      c = 200;      return sum(a, b); }                                                                                TEST(test, driver_sum) {      EXPECT_EQ(320, driver_sum);      EXPECT_EQ(30, driver_sum); }2.3构建测试数据和测试代码遇到的技术瓶颈编写测试代码比较繁琐开发编写驱动不难,但是浪费大量的时间,并且没有创造性。编写代码是否有良好的代码规范单元测试也需要一些规范支持,例如代码规范,注释规范等,有了这些规范能够为测试人员提供很好的功能测试用例设计的逻辑思考,也为其他开发熟悉代码提供极大的便利。数据类型比较复杂通常情况下,输入参数比较复杂,嵌套层析结构比较深入,例如类包含其他类等。能否支持多组测试数据一般代码中每个循环、分支判断以及输入输出都有可能产生缺陷。因此单元测试需要很多用例,满足不同的条件分支,达到满足覆盖率。第三章 Wings的基本架构介绍3.1 Wings测试用例驱动自动生成技术的特性l  Wings是智能的全自动测试用例驱动构建系统,能够在很短时间内完成对大型复杂程序的自动解析、构建。每分钟达到100万行代码的生成速率。l  可以将任意复杂类型逐步分解为基本数据类型,例如结构体嵌套,复杂类对象,c++标准容器,自定义模板类等。l  支持多层次的可视化的数据表格来对变量类型进行赋值,无需关注驱动程序本身。数据表格可以表达任意深度和多层次的数据关系,用户只需要关注表格数据,完成对输入数据的校对。l  能够区分系统数据类型和用户自定义类型,对于复杂的约定俗成系统类型可由用户自定义扁平式赋值模板,例如std::vector类型等,内部集成常用系统类型的模板。3.2 Wings的技术架构介绍Wings的技术架构:首先Wings利用代码静态分析技术,提取被测程序的主干信息并保存到Program Structure Description(PSD)结构中,PSD结构中主要存储函数的参数、全局变量以及返回值的信息,类的成员变量,成员函数,以及访问权限等信息。利用存储的信息,依据一定的编写规则,自动构建测试驱动、googletest 期望断言、测试输入、参数捕获等代码和值。                                             图 3.2 Wings总体架构图上述Wings的总体架构图,说明了Wings构建代码与测试输入的具体过程,整个核心技术是通过编译底层技术获取程序的信息,然后按照一定的规则构建需要的数据。第四章 程序结构信息描述程序结构信息(Program Structure Description)是指对源程序进行提取后的描述信息,主要包括类名、命名空间、类的成员变量信息、类的函数信息,以及各种类型信息等(程序结构信息,下文简称“PSD”)。描述信息的保存C语言是以一个文件为单元存储,C++提取所有的类信息存储在一个文件中。Wings的主要特性是能够对复杂的类型(结构体、类、模板类等)进行逐层展开分解到最基本数据类型(char、int、string等)。PSD结构存储在XML文件中,不同的XML文件存储不同的描述信息。Wings提取的程序结果都存储在Wingsprojects文件下的funxml与globalxml文件夹中,其中funxml文件中主要存储的文件以及作用如下:RecordDecl.xml: 结构体,联合体与类描述信息。ClassTemplateDecl.xml:模板类描述信息EnumDecl.xml:枚举描述信息funcPoint.txt: 存储函数参数为函数指针的分析结果。funcCount.txt: 存储分析到的全部函数,参数个数,参数类型信息。void.txt: 存储函数参数为void*的分析结果。filename.xml:存储c语言文件的信息。注:具体文件的描述信息,参看附录A。针对复杂类型,例如结构体类型location_s,成员变量中除了基本数据类型之外,还存在包含结构体类型的情况,如下所示的代码中,location_s中包含coordinate_s结构体,以及FILE等类型的信息,针对不同的类型进行标记区分。 源代码如下:typedef struct coordinate_s{     void(*setx)(double, int);     int mInt;     char *mPoi;     int mArr[2][3];     void *vo; } coordinate;   typedef struct location_s {     int **mPoi;     coordinate *coor;     FILE *pf;     struct location_s *next; }location;   coordinate *coordinate_create(void); int coordinate_destroy(location *loc,size_t length,char *ch); void func_point(double param1, int param2); 生成对应的PSD结构信息如下图4:图4:PSD描述信息C++的主要表示类型是类,因此测试是C++以一个类为单元做测试,类主要包括类的成员变量名以及类型信息,成员变量的访问权限信息。类的成员函数分为构造函数、内联函数、虚函数等,成员函数的参数信息以及类型信息等。具体描述信息可以登陆www.codeWings.net下载Wings试用版本进行学习。第五章 Wings构建程序描述Wings通过获取到的存储信息,依据一定的编码规则,构建不同的代码程序,如驱动程序、期望断言程序、参数捕获程序等。5.1 驱动程序构建驱动程序指单元测试代码,Wings针对函数参数的类型,自动完成单元测试代码的编写。为了更详细的说明驱动程序,以一个C++类作为具体的例子说明。 类的声明如下:class BlockBuilder { public:     explicit BlockBuilder(const Options* options);     BlockBuilder(const BlockBuilder&) = delete;     BlockBuilder& operator=(const BlockBuilder&) = delete;     void Reset();     void Add(const Slice& key, std::string & value);     Slice Finish();     size_t CurrentSizeEstimate() const; private:     const Options* options_;     std::string buffer_;     int counter_;     bool finished_; };针对如上BlockBuilder 类,构建一个对应的驱动类DriverBlockBuilder,驱动类中主要包含构造函数、析构函数、每个成员函数的驱动函数以及返回值函数。为了避免类中重名函数,对写入PSD需要对应生成驱动的函数进行顺序编号。驱动类声明:class DriverBlockBuilder { public:     DriverBlockBuilder(Json::Value Root, int times);     ~DriverBlockBuilder();     int DriverBlockBuilderReset1(int times);     int Reset1Times;     int DriverBlockBuilderAdd2(int times);     int Add2Times;     int DriverBlockBuilderFinish3(int times);     void ReturnDriver_Finish3(class Wings::Slice returnType);     int Finish3Times;     int DriverBlockBuilderCurrentSizeEstimate4(int times);     void ReturnDriver_CurrentSizeEstimate4(size_t returnType);     int CurrentSizeEstimate4Times; private:     Wings::BlockBuilder* _BlockBuilder; };在上述驱动类中,构造函数的作用是构造BlockBuilder的对象,用构造的对象,调用测试BlockBuilder中的成员函数。析构函数的作用是释放构建的对象。 构造函数与析构函数:DriverBlockBuilder::DriverBlockBuilder(Json::Value Root, int times){   Json::Value _BlockBuilder_Root = Root["BlockBuilder" + std::to_string(times)];   /* options_ */   Json::Value _options__Root = _BlockBuilder_Root["options_"];   int _options__len = _options__Root.size();   Wings::Options* _options_ = DriverstructOptionsPoint(_options__Root, _options__len);   /* buffer_ */   std::string _buffer_= _BlockBuilder_Root["buffer_"].asString();   /* counter_ */   int _counter_ = _BlockBuilder_Root["counter_"].asInt();   /* finished_ */   bool _finished_;   int _finished__value_ = _BlockBuilder_Root["finished_"].asInt();   if (_finished__value_ == 0) {     _finished_ = true;    }   else {     _finished_ = false;   }   _BlockBuilder = new Wings::BlockBuilder(_options_, _buffer_, _counter_, _finished_, false); } DriverBlockBuilder::~DriverBlockBuilder() {     if (_BlockBuilder != nullptr) {         delete _BlockBuilder; } }每个成员函数对应生成自己的驱动函数。类中的Add函数对应的驱动函数如下。Add驱动函数:int DriverBlockBuilder::DriverBlockBuilderAdd2(int times) {     Add2Times = times;     const char* jsonFilePath = "drivervalue/BlockBuilder/Add2.json";     Json::Value Root;     Json::Reader _reader;     std::ifstream _ifs(jsonFilePath);     _reader.parse(_ifs, Root);     Json::Value _Add2_Root = Root["Add2" + std::to_string(times)];     /*It is the 1 global variable: count    Add */     int _count = _Add2_Root["count"].asInt();     count = _count;     /*It is the 1 parameter: key Add2      * Parameters of the prototype:const Wings::Slice &key */     Json::Value _keykey_Root = _Add2_Root["key"];     /* data_ */     char* _keydata_;     {         std::string _keydata__str = _keykey_Root["data_"].asString();         _keydata_ = new char[_keydata__str.size()];         memcpy(_keydata_, _keydata__str.c_str(), _keydata__str.size());     }     /* size_ */     unsigned int _keysize_ = _keykey_Root["size_"].asUInt();     Wings::Slice _key(_keydata_, _keysize_, false);     /*It is the 2 parameter: value    Add2      * Parameters of the prototype:const std::string &value  */     string _value = _Add2_Root["value"].asString();       //The Function of Class    Call     _BlockBuilder->Add(_key, _value);     return 0; }构成以上驱动函数的主要包括全局变量、参数、调用被测函数的构建。以上是针对BlockBuilder类的驱动类的主要信息,而构建的程序遵守google的编码规范。一些命名规则如下:Wings生成的驱动代码,存储在drivercode文件夹中。(1)driver.cc与driver.h,针对程序中使用到的一些公共函数以及头文件。(2)同一个结构体或者联合体,可能会作为多个函数的参数使用,为了避免代码的重复,Wings针对所有的结构体和联合体的不同类型,封装成不同的驱动函数或者参数捕获函数。driver_structorunion.cc 存储结构体驱动函数的代driver_structorunion.h 对应的头文件。结构体实现函数的命名规则为:DriverStruct+结构体名字+类型,其中Point代表一级指针或者一维数组,PointPoint代表二级指针或者二维数组使用。源文件的命名规则为:driver_+源文件名/类名+.cc例如:driver_nginx.cc 或 driverBlockBuilder.cc驱动函数的命名规则:Driver_+函数名+(编号)例如:Driver_ngx_show_version_info(void);DriverBlockBuilderAdd2(int times)    (3)返回值的打印输出返回值的打印输出函数命名规则:Driver+Return+Print_+函数名。例如:DriverReturnPrint_ngx_show_version_info();(4)用户源代码中的main函数自动进行注释,重新生成一个main函数文件,来进行测试。Wings会生成驱动main的主函数文件为:gtest_auto_main.ccWings主要针对参数进行逐层展开,解析到最底层为基本类型进行处理。驱动的赋值部分,主要就是针对基本类型进行处理。(注:特殊类型,比如FILE等,后面会详细讲解如何赋值)以int类型举例,一般程序构成int的主要组成大概包括以下情况:int p; int *p; int **p; int ***p;int p[1]; int p[2][3]; int p[1][2][3];int(*p)[]; int(*p)[][3]; int *(*p)[]; int (**p)[];int *a[]; int **a[]; int *a[][3]; int (*a[])[];Wings会针对基本类型的以上15种类型,进行不同的赋值。构建完驱动程序之后,要对驱动程序进行运行,Wings构建googletest的框架,来进行测试。下面我们将针对期望断言的googletest程序进行构建。5.2 googletest程序的构建在构建完单元测试驱动程序之后,Wings将调用googletest的框架,完成对返回值的期望值验证代码,并且输出测试结果。Wings运行单元测试过程中,会构建返回值的保存代码,将程序的返回值结果进行存储,然后读取用户输入的预期值,进行结果对比,判断是否通过。针对具体的类,对应生成gtest类,每个gtest类中对每个函数构建期望代码。例如针对BlockBuilder类,生成的gtest类为 GtestBlockBuilder。GtestBlockBuilder类的声明:class GtestBlockBuilder : public testing::Test { protected:     virtual void SetUp()     {         const char* jsonFilePath = "../drivervalue/RecordDecl.json";         Json::Value Root;         Json::Reader _reader;         std::ifstream _ifs(jsonFilePath);         _reader.parse(_ifs, Root);         driverBlockBuilder = new DriverBlockBuilder(Root, 0);     }     virtual void TearDown()     {         delete driverBlockBuilder;     }       DriverBlockBuilder* driverBlockBuilder; }; BlockBuilder类中的每个函数对应一个gtest函数,每个函数负责调用DriverBlockBuilder编写的驱动函数,对于包含返回值信息的函数,则对应生成具体的期望值对比。 期望对比函数CurrentSizeEstimate:TEST_F(GtestBlockBuilder, DriverBlockBuilderCurrentSizeEstimate4) {     const char* jsonFilePath = "drivervalue/BlockBuilder/CurrentSizeEstimate4.json";     Json::Value Root;     Json::Reader _reader;     std::ifstream _ifs(jsonFilePath);     _reader.parse(_ifs, Root);     for (int i = 0; i < BLOCKBUILDER_CURRENTSIZEESTIMATE4_TIMES; i++) {         driverBlockBuilder->DriverBlockBuilderCurrentSizeEstimate4(i);         Json::Value _CurrentSizeEstimate4_Root = Root["CurrentSizeEstimate4" + std::to_string(i)];         /* return */         unsigned int _return_actual = _CurrentSizeEstimate4_Root["return"].asUInt();         /* return */         unsigned int _return_expected = _CurrentSizeEstimate4_Root["return"].asUInt();         /* return_expected */         EXPECT_EQ(_return_expected, _return_actual);     } }最后调用自动构建的main函数运行整个单元测试过程。5.3 参数捕获程序构建参数捕获是指在程序运行过程中获取程序的变量信息,主要包括函数的参数、全局变量、返回值等。Wings自动构建获取参数的程序,利用插装技术,将构建的捕获函数插入源代码中对应的位置,将获取的具体信息,写入值文件,可以将获取的数据作为单元测试的输入,在代码发生变更后,利用相同的输入判断是否得到相同的输出,进行回归测试。Wings的参数捕获代码存储在paramcaputrecode文件夹中。其中命名规则同驱动格式一样,将所有的driver替换为param即可。Wings针对每个类生成一个对应的参数捕获类,而参数捕获类中针对每个函数生成对应的捕获参数、全局变量以及返回值的函数。c++ 中类的成员变量是私有,无法从外部获取,Wings利用插桩技术,对每个类插入一个捕获函数,来获取类的私有成员变量。参数捕获类ParamCaptureBlockBuilder:class ParamCaptureBlockBuilder { public:   ParamCaptureBlockBuilder();   ~ParamCaptureBlockBuilder();   void ParamCapture_Reset1();   void GlobalCapture_Reset1();   void ReturnCapture_Reset1();   void ParamCapture_Add2(const Wings::Slice &key, const std::string &value);   void GlobalCapture_Add2();   void ReturnCapture_Add2();   void ParamCapture_Finish3();   void GlobalCapture_Finish3();   void ReturnCapture_Finish3(class Wings::Slice returnType);   void ParamCapture_CurrentSizeEstimate4();   void GlobalCapture_CurrentSizeEstimate4();   void ReturnCapture_CurrentSizeEstimate4(size_t returnType); };具体的捕获函数不再详细说明,具体信息可以在Wings官网下载试用版本查看。第六章 Wings类型以及面向对象语法特性的支持Wings能够支持任意的类型以及面向对象的语法特性。类型支持:l  基本类型,int、double、float、std::string等l  任意复杂的结构类型,结构体、联合体、枚举、链表、多级指针、数组、树、图等l  任意复杂的类对象,标准库容器、自定义模板类特殊模板:n  区分用户自定义的类型与系统变量类型(标准库头文件中包含的类型)n  类的运算符重载函数n  void *与函数指针n  识别类中包含delete与default关键字的函数进行特殊处理语法支持:u  处理static函数、保护和私有函数u  类中定义私有结构体u  类中包含delete与default关键字的函数进行特殊处理u  多态与复杂的类继承6.1链表针对链表类型,采用比较灵活的赋值方式,考虑到实际应用中的一些因素,针对链表类型,默认赋值两层结构,在实际测试过程中,用户可依据需要自动添加节点。6.2 标准库容器Wings能够支持c++的标准库容器,能够对容器进行逐层展开,利用不同容器的标准赋值函数进行赋值以取值。其他类似的容器例如QT中的容器以及boost库中的相关容器,我们在继续支持。6.3 自定义模板类一些用户自定义的模板类类型,Wings能够识别是用户自定义的模板类,Wings依据实际程序中的赋值类型,进行处理。6.4  void*与函数指针Void*与函数指针在实际程序中可以作为函数参数或者结构体与类的成员变量,针对不确定的赋值类型,Wings提供了具体的解决办法:① 利用编译底层技术,对源程序静态分析,获取真实类型,对真实类型进行赋值② 由用户在数据表格界面配置实际类型6.5 特殊模板在实际的代码程序中,会存在一些类型无法使用通用的模式全部展开,如一些系统变量(FILE、iostream)、第三方库以及一些用户需要特殊赋值。Wings是如何针对以上特殊类型进行赋值,举例如下:struct sockaddr_in {         short   sin_family;         u_short sin_port;         struct  in_addr sin_addr;         char    sin_zero[8]; };步骤如下:a.        识别sockaddr_in为系统变量类型,特殊标记b.        检测程序中的所有系统变量类型,显示在模板界面c.         用户配置特殊变量,如sin_familyd.        构建sockaddr_in对象e.        调用模板,生成驱动模板配置如下:图:6.5模板配置  第七章 数据表格Wings目前测试用例数据采用随机生成的方式,支持int、char、double、float、bool、char*类型。数据表格可以任意编辑以上类型的数值。(1)Wings数据表格将会针对参数进行展开,假如参数类型为结构类型,数据表格将分层展开结构的类型,到基本类型。(2) 针对基本类型的指针类型,例如int *p;Wings处理为不定长度的一维数组类型,int **p;处理为不定长度的二维数组类型,默认长度为3,数据表格界面可以点击进行添加和删除数据。(3) 针对不定长度的数组作为函数参数,例如int p[];Wings默认长度为1,用户依据需求,在数据表格界面进行任意添加和修改即可。图 7-1数据表格展示 附录A表一:type属性ZOA_CHAR_S/ZOA_UCHAR/ZOA_INT/ZOA_UINT/ZOA_LONG/ZOA_ULONG/ZOA_FLOAT/ZOA_UFLOAT/ZOA_SHOTR/ZOA_USHORT/ZOA_DOUBLE/ZOA_UDOUBLE基本类型StructureOrClassType结构体类型ZOA_FUNC函数指针类型ZOA_UNION联合体类型ZOA_ENUM枚举类型ClassType类类型  表二:basetype属性BuiltinType基本类型ArrayType数组类型PointerType指针类型StructureOrClassType结构体类型UnionType联合体类型EnumType枚举类型FunctionPointType函数指针类型 表三:其他属性Name代表结构体、类、联合体名字NodeType代表链表类型parmType代表函数参数类型parNum代表函数参数个数SystemVar代表此类型为系统头文件类型value代表枚举类型的值bitfield代表位域类型所占字节returnType代表返回值类型Field类成员变量Method类构造函数paramName类构造函数参数名paramType类构造函数参数类型TemplateArgumentTypeSTL结构参数类型WingsTemplateArgumentSTL结构嵌套参数名字TemplateArgumentValueSTL结构中参数为具体值FunctionModifiers函数访问权限FunctionAttribute函数是extern或者static函数FuncClassName函数所属类OperatorFundecl重载运算符函数Operator重载运算符类型
  • [分享交流] 精准测试白皮书2020版
    第一章 精准测试诞生的背景(附完整版精准测试讲解视频和白皮书pdf下载)20年前(2000年),上网是一件很酷的事,叫做“网上冲浪”,主要是几个门户网站占据绝大多数注意力;20年后(2020年),我们已经全方位“浸泡”在软件的海洋里,很多大型软件系统已经超过亿行,架构模型越来越复杂。未来的20年(2020-2040年),随着各种智能应用的层出不穷,软件系统内部逻辑会不可逆转的越来越复杂,而外部操作会越来越“傻瓜”。用户一个眼神或者一动脑,就能够切换出不同的功能需求。同时中国的软件产品化进程,近些年来正在蓬勃的进行,大量的公司开始研发自己的产品。伴随着关键核心软件的国产替代,使得原本应用级难度的开发正在向高复杂度和高质量的产品型研发转型。这个转型的过程,注定将产生对于高端测试工具的巨大需求。软件缺陷发现得越晚,其处理费用即呈几何性激增,而不是线性增长。如何从庞大复杂的系统中迅速及时地找到故障所在,一直是行业的一大难点。无法对大型软件进行有效的质量把控,就无法真正构建与维护大型软件。目前国内软件测试基本处于两种状态:一是绝大多数企业采用功能(黑盒)测试,二是小部分对软件产品有高可靠性要求的软件,企业会使用代码级的白盒测试工具。但这两种传统测试办法在目前的软件日趋智能化复杂化下,弊端越来越明显。功能(黑盒)测试技术**,使墨菲定律在所难免。**由于无法获知程序内部逻辑结构,这种测试办法对软件可靠性要求不高的应用来讲问题不是很大,但是对于大型金融机构、智能工业、航天军工等关键系统,就意味着时刻携带隐形的巨大风险。为此,功能测试后期需要极高的人力投入才能完成复杂逻辑的用例分析和设计。然而对于黑盒测试来说,程序越大,杀虫剂效应越明显。而行业内当作银弹的自动化测试,当自动化程序本身规模扩大以后,它的维护本身就存在了很严重的问题。低效的黑盒测试状态,最终将影响和制约未来整体软件发展。代码级(白盒)测试工具一般重点应用在研发阶段的单元测试上,满足了客户的部分高可靠性需求,但由于其价格高昂、技术老化,仅适合于小规模迭代瀑布式开发的软件,无法完成复杂的系统级别的测试以及分布式基于云的测试,更不适应敏捷迭代的开发模式。另外白盒测试工具基本都是国外产品,通常这些产品无法完成深度的定制化功能实现以及快速的用户响应,代码安全更是一个较大的问题。所有先进的科技都是具备前瞻性眼光的。随着国内军民各项大型核心软件系统的上马,研发一种面向高复杂度大型软件、自主可控的高性能智能精准测试平台的必要性,逐渐凸显。在这个时代背景下,2012年初,星云测试团队开始了筚路蓝缕、心无旁骛的研发征程。精准测试是个交叉学科,里面涉及到编译器、测试分析、图形技术、高性能通信与存储,软件的研发等多项底层技术。经历无数个不眠之夜对技术难点突破的煎熬与最佳解决方案的反复推敲,星云精准测试产品在诸多方面率先实现了重大技术创新,成功突破了白盒测试使用难度大、价格高昂的桎梏,有效消弭了国外高端测试产品垄断的壁垒。星云精准测试产品更偏向于软件测试业界的“灰盒测试”,即用简单的黑盒操作办法,可以同时得到单元级和系统级的精准测试数据。“星云精准测试”不负众望,在众多性能上大幅超越国外进口高端白盒测试工具产品,并在数据追溯、覆盖率可视化、智能回归、智能缺陷定位、分布式数据穿透与追踪等特性上有突出贡献。星云精准测试,既继承了传统功能测试前期的高效率运行区间,又能在后期通过系统的数据,让开发、测试充分协同,完成全程高效的测试与数据分析。(1)将测试团队的价值放大,能够将开发与测试更加紧密的连接起来,互为支撑。(2)采用精准、可信的测试技术,测试管理的难度大幅度降低。(3)降低企业对人员的过度依赖,通过系统适应人员的变更。(4)为企业实现测试数据资产的有效积累和分析,打下坚实基础。“星云精准测试VIP大企业离线版云平台”在整体测试试功能上的优异特性,成功获得了一批重要大型企业的高度认可及产品采购。星云测试的首发版本为:穿线测试 ThreadingTest,2014年6月6日上线,侧重于系统级白盒测试技术,测试用例和代码逻辑的双向追溯技术,测试示波器技术,覆盖率可视化技术。2015年8月6日,“穿线测试”正式更名为“星云测试”。在继承穿线测试整体技术上,星云精准测试增强了回归测试用例的自动选取技术,缺陷最后执行时序分析、智能缺陷定位、敏捷环境下多版本白盒测试数据的聚合、聚类分析、结合代码结构与动态数据的测试漏洞检出、代码安全特性,全面的测试管理特性等几十种优秀功能。目前有“星云精准测试VIP大企业离线版云平台”、“星云精准测试PASS在线云平台www.teststars.cc”、“全自动测试用例驱动生成系统Wings”等多种工具产品。星云精准测试旗下产品平台有Horn、Paw、Shell、Wings等系列产品。适用语言和平台暂为:为响应广大用户的需求,目前正在进一步扩展适应的语言和平台覆盖面。图1-1 精准测试在大型系统的效率运行分析星云精准测试,既保证了传统功能测试前期的高效率运行区间,又能在后期通过系统的数据,让开发、测试充分协同,完成全程高效的自动化精准测试。第一章 精准测试技术体系对软件测试技术的升级解析精准测试技术体系经过近6年的商业项目实践日臻成熟,大量商业应用案例的正面积极反馈,表明它已经成为新的软件测试技术方向体系。星云精准测试灵巧详细的功能设计和高度可靠的产品内核得到了市场的广泛认可,对于国际上原有的白盒测试工具来讲,是一种质的飞跃。2012年,精准测试的商用工具正式进入设计和研发阶段。与引进国外技术不一样,精准测试的核心技术体系是星云测试团队在国内的原创设计和研发。产品经过3年的悉心研发、反复内测、不断优化后,2014年精准测试在CSTQB会议上,发布了第一个商用版本ThreadingTest,引起了很大反响。6年前,行业上还全面沉浸在黑盒测试的大氛围中,从未见过精准测试的超前的运行方法和提供的强大智能的功能,由于理念与设计过于超前,早期有一些业内质疑的声音。但由于产品独到的优秀特点和巨大的潜在价值,诸多伯乐开始试用,给了产品在实际场景中不断优化、强化的宝贵机会。经过不同领域、不同客户的各种高复杂度大型系统的百般锤炼、验证后,自2016年开始,精准测试开始赢得全行业的重视和响应。优秀的商用落地性是精准测试技术流行的一个重要因素。由于精准测试把准了黑盒测试无法解决的难题和固有瓶颈,踏准了测试技术发展大的进程,并从设计一开始就特意注重了商业场景下使用要求复杂性,因此它从诞生之日起就不仅仅是一套理论,而是有着非常强的实用性基因和可扩展架构,多场景应用成果卓然。精准测试最底层的核心技术:“一种基于用例与源码双向追溯的测试装置及方法”,类似在重建量子纠缠的场景和数据。它成功的将功能用例和对应的代码二者之间的追溯路线,实现了精准无误的可视化。这彻底解决了在黑盒的状态下,软件工程师们无法获知程序内部运行轨迹的难题。自此开始,计算机处理海量测试数据的强大分析能力开始展现。我们知道,所有的黑盒测试都是人工进行的,它依赖的是人的算力,而软件正确性验证的工作量,主要是组合路径膨胀的问题,人的算力是远远跟不上的。那么精准测试如何从测试的角度对业务进行深度的测试辅助分析呢?我们用量子纠缠的形象类比来说明这个问题。量子纠缠理论我们可以简单理解为两个处在纠缠态的粒子一旦分开,不论分开多远,如果对其中一个粒子作用,另一个粒子会立即发生变化,且是瞬时变化。“一个粒子”会与“另一个粒子”产生相互作用,两个表面互相不关联的粒子,互相作用互相影响,他们对外是一个整体,无法单独描述“单个粒子”的性质,只能描述这“两个粒子”的整体性质,这就叫做“量子纠缠”。类比到软件测试上,我们的被测试软件中常见的软件界面和功能输入输出以及渲染它的复杂代码,他们之间就和两个纠缠在一起的粒子一样,具备强关联性。一个发生了变化,另一个必定发生变化。精准测试的另一核心功能是:“回归测试用例的自动选取”,就是基于用例和代码的追溯(量子纠缠)关系在进行运算之后全自动得出的。用例和代码精准的追溯机制,使数据开始可以实施大量的智能测试算法。在软件测试理论界,大量论文算法的基础都是默认建立在用例和代码的关系上进行分析的,但因其追溯机制工业实现难度极大,所以一直停留在学术理论阶段。星云测试引领的精准测试方法体系,落地在精确便捷的商用产品和大型解决方案中,让大量先进的测试分析方法和理论,得以实实在在的验证。精准测试首次明确的提出了:如何采集和应用双向追溯数据,进行测试辅助分析系统的构建。不管是纯软件系统还是运行在设备中的软件系统,用例与代码精准的数据可追溯性,都是基础性的强需求。比如金融转账业务、用手机拍照、机器人控制器的动作控制指令等,每个操作都有与之对应的代码。星云精准测试产品的强大之处在于:所有的分析算法不需要和被测系统的业务功能做特定的适配,因此可以应用于任意软件系统的测试辅助分析。而传统的白盒在产品实现上以采集和分析总体覆盖率为主,没有能力将覆盖细化到用例层级,因此传统的白盒测试囿于覆盖率的概念中,无法实现更高层次的测试辅助分析需求。星云测试产品的技术优越性及应用的易用性,使它成为新一代软件测试技术流的中坚力量。星云精准测试在企业应用场景中,为了方便客户还设计了完全静默的“傻瓜”运行模式,客户基本无需增加额外的学习成本。比如测试工程师打开测试用例的excel表格,当他准备执行某个用例的时候,只需点击这一项测试用例。随后通过VBA技术,直接调用星云精准测试的后台接口,再附加一整套深入应用后台执行线程的用户标签技术,就可以将用例和代码关联和分离出来(这里说的分离是指类似于J2EE服务端后台应用)。在对外提供多用户并发访问的情况下,可分离出每个用户执行的用例所对应的相应代码。前面我们提到功能和代码这两个量子数据的重建,以前主要出现在研发/开发人员相对比较零散的执行单步调试功能的时候(即单元测试),无法存储。国外白盒工具因其设计基因的限制,无法支撑超大型、高复杂度的系统级测试需求。在星云精准测试体系中,只要测试工程师执行测试用例,几乎不需要额外付出,在建立测试用例与数据的对应关系的同时,瞬间即可将海量数据实时采集并存储起来,用于后续测试大数据的分析和运算上。它的内核设计,使之可以轻松应用在数亿行的超大型应用上,实时采集、存储测试数据,而对原有系统的响应性能不产生干扰。星云精准测试对软件测试体系是重大的技术革新,它从以下几个层面改变并提升了测试:对软件测试的深度进行了大幅度的拓宽,让计算机有能力直接对测试用例进行辅助分析,给出更深入的测试决策分析依据。传统测试主要通过人工业务测试发现缺陷,定位缺陷必须由开发人员进行,二者信息没有精确的数据交互。精准测试主要基于测试人员标识的用例状态,以及自动记录的用例对应的代码路径进行频谱分析。它可以自动计算缺陷产生的代码位置,在发现缺陷的同时,同步产生缺陷定位的结果数据。精准测试提供的测试用例的聚类分析,是基于测试用例的路径空间距离进行聚类,聚类的结果可以直接对用例执行正确性进行审核,对用例进行等价类划分、分析缺陷密集区以及对用例执行分布进行评估等。精准测试提供的回归用例选取结果,经由海量的计算精准推荐而来,总体算法思路与人工分析的思路是类似的,采用人工智能算法模式把大量的计算完全交由计算机去总结分析,精准、稳定、可靠、高速。这个功能相当于解放了测试和开发团队大量的人力资源,彻底解决因团队成员变更而引入的未知风险。精准测试开辟的测试方法新体系,支撑了黑盒测试快速提升测试效能比的刚需。精准测试对于企业来讲,相对于比需要人工编写、维护庞大自动化脚本的自动化测试,工作量是低很多的。精准测试和自动化测试是并行的技术方向,企业应用可以根据各自团队的特点来选择,并没有绝对的应用时序依赖关系。自动化测试近些年的应用遇到一个广泛的批评就是:让测试团队疲于应付用例的编写而不是测试用例设计等测试核心技术。精准测试属于测试分析系统,着眼点和立意相对较高,在测试理论、方法和商业应用落地验证与成果上,形成较好的整体闭环。它把测试需要关注的核心,引领到一个正确方向上来。精准测试在技术特性上解决了测试结果可信性的问题。在精准测试之前,我们所见到的所有测试数据都是易伪造、易篡改的。例如我们通常使用的测试管理系统,一个用例是否被有效执行,绝大部分是在测试管理系统中被人工录入的。精准测试是在用例动态执行过程中,由计算机内部算法真实记录对应的程序运行逻辑,然后形成后面对测试数据进行精确分析的数据源基础。所以其底层程序运行的数据是没有办法也绝对不允许进行伪造和篡改的。精准测试果断去除了阻碍测试行业发展的重要障碍,让测试的结果精准化、可量化、可衡量化、可信化。此举,将大幅减低测试行业本身的管理成本,有效推动测试行业的快速、健康发展。精准测试大幅提升了开发和测试部门的协作效能。前面提到全景调试器,测试工程师执行完用例,即时产生代码层级的全景调试数据;测试完成后一旦用例存在缺陷,那么基于这个全景调试图以及高度可视化的数据路径追溯,开发人员可以直接对缺陷进行定位,不需要在开发环境下重现缺陷,再单步调试以解决问题。实施精准测试之前,开发人员苦于很难有效参与对测试用例进行审核;实施精准测试后,用例的执行结果都映射到了代码层,开发人员通过代码的覆盖视图很容易就可以协助测试人员补充和确认用例,开发和测试的协作变得非常简单和直接有效。      不可否认,在精准测试之前,开发和测试存在沟通不畅的问题。通过精准测试在项目中的有效实施我们会发现,精准测试可以帮助开发提供非常有价值的数据: 例如代码和用例的反向追溯可以帮助开发人员修改代码做参考,精准测试自动计算回归范围减轻了开发人员必须协助测试进行分析的工作量,因此,精准测试对开发和测试来讲,是一举两得、相得益彰的。星云精准测试发明了多个全新的、适应敏捷迭代开发模型下的覆盖率计算方法。覆盖率是白盒测试最基本的技术,但是随着敏捷迭代的开发模式,即使最高端的白盒测试工具已经几乎没有用武之地,原因就在于由于迭代很快,在某个版本上通常只能采集少量的覆盖率后新版本就发布了。本应在一个版本上分析的覆盖数据,分布到了数个代码结构不一样的程序版本上,因此原有的统计方法和参考意义基本上都失效了。精准测试提供了累计覆盖率,能够将多个版本的覆盖率以最新版本的代码结构进行投影,在控制流上进行累加。这样测试团队无需关注每个版本的覆盖情况,即可关注一个完整测试周期内所有版本的累积覆盖率。另外,考虑到敏捷迭代每个版本的测试需求,即:针对特定模块和功能范围进行测试(并不是全量测试),精准测试提供了相关覆盖率的计算方法。它可以自动圈定某个用例和用例集有关的代码范围(这些也是基于用例和代码的关系分析基础上动态计算的),在运行少量用例或者某个功能模块的情况下,它可以自动确定相关代码,把不相关的代码从覆盖率的分母中过滤掉。这样相关覆盖率在仅仅运行部分少量用例的情况下,依然具有很强的统计和参照意义。第三章 精准测试的定义精准测试定义:由中国团队发起并原创完成测试理念设计和商用产品研发的全新测试技术。旨在测试用例执行过程中,全自动建立任意运行模式的软件系统的功能点与源代码之间高度的可视化追溯机制,获取功能点相关的代码覆盖率并进行精准回归等测试用例深度辅助分析算法的应用。精准测试是测试理论界首次同时使用测试用例及其相关代码两个关键因子,进行质量综合考量和分析的创新测试方法体系。3.1 基本定义星云精准测试在测试用例执行过程中,可以同步全自动建立任意运行模式的软件系统功能点与源代码之间的高度可视化追溯机制,即通过内部算法能够将缺陷对应的代码出错位置直接定位出来;能够获取功能点相关的代码覆盖率并进行精准回归等,使测试用例深度辅助分析算法得以强化应用。这是软件测试首次同时使用测试用例及其相关代码两个关键因子,进行质量综合考量和分析的创新测试理论方法体系。这种有效的数据追溯与“量子联动”的突破性技术特性,大大增强了测试的深度与广度,打破了测试部门的成长天花板,为测试过程本身的价值挖掘和测试数据资产的增值,提供了必要而充分的条件。3.2 关键技术精准测试体系贯穿整个软件测试生命周期。精准测试主要侧重于系统级测试,在单元测试、集成测试、系统测试、验收测试、回归测试中,均能赋予测试数据强大的追溯能力。关键核心技术有:测试用例和代码逻辑的双向追溯,测试示波器、覆盖率可视化、回归测试用例的自动选取、缺陷最后执行时序分析、智能缺陷定位、敏捷环境下多版本白盒测试数据的聚合、聚类分析、结合代码结构与动态数据的测试漏洞检出等。精准测试在测试用例执行过程中,为用户从底层自动建立任意运行模式的软件系统功能点与源代码之间的可视化追溯机制,使用户获取用例级的代码覆盖率等多种高级测试数据。这一突破性的创新智能算法,有力的打破了软件开发、测试、维护及管理人员等之间的数据孤岛状态,实现了软件测试过程和结果的高度精准可视化,在软件高可靠性和高可信度方面,提供了全面而有力的数据支撑。精准测试运行模式是灰盒模式,即:可以在黑盒功能测试的时候,同步完成数据采集和分析计算,让“点测”团队也可轻易切入到精准测试模式,无需改变现有测试形式与流程,不增加额外的技术学习与转换成本。3.3 应用范围精准测试适用于任何形态的软件系统。星云精准测试可应用于各种软件包括嵌入式系统、分布式系统、web应用系统、单机软件系统等各类软件的测试,并且完全不受限于被测试软件本身的业务需求。3.4 用户收益实现从发现缺陷到预防缺陷的转型。减少因为缺陷而对整个研发运维流程造成的返工成本。使发现缺陷前移,减少因项目后期的严重缺陷而导致产品交付延期、成本增高,影响交付质量。建立跨需求、开发、测试等部门的测试协同平台。实现业务数据可追溯化和路径可视化。优化技术与业务方案。根据不同的质量要求,优先级顺序、技术实现手段等,实现智能灵活的技术方案推荐、交付和应变机制。减少无数据支撑造成的内耗。企业“精准众测”平台,支撑千人团队同时在线。测试数据可以根据管理需要做分析,为企业内的成本管控提供选型参考。实现跨地区,跨部门的业务人员,开发人员和测试人员的测试协同,即使不在同一办公地点的人员,也可针对测试需求,测试任务,测试用例和测试缺陷等方面进行远程沟通和实时协同作用,最终完成整个测试过程的实施。支持敏捷开发与测试模式。关注新功能的增量测试,支持自动化回归测试,实现高效的IT交付。第四章 精准测试的基础架构介绍4.1 精准测试的技术架构精准测试从某些层面来讲,赋予了测试用例真正的生命力。测试用例是测试数据的一种,当测试数据实现路线可追溯可视化的时候,一些高级算法的强大能力就可以显示出来。我们从精准测试的整体架构图中可以做一具体分析。图4.1-1 精准测试的总体架构图第一层:利用先进的前置编译器,为客户做源码静态结构分析(在客户的实际环境中,根据客户的需求进行相关的技术配合);第二层:将处理好的系统程序放入测试环境运行,测试工程师通过人工或程序自动化的形式,开始执行用例(人工执行用例可以和测试管理平台或者Excel表格方式进行对接),精准测试的 “软件示波器”采集运行数据并进行高速智能运算,获取精确的测试数据;第三层:根据采集的代码与对应的测试用例,在星云精准测试平台中实现用例与源码的互相追溯;第四层:通过精准测试的分析平台,可以对测试数据进行缺陷定位、用例聚类分析、回归测试用例和最小测试用例集等功能的计算,用户还可以根据需求,批量生成相应的测试报告,或进行测试数据高级分析。图4.1-2 精准测试的用例魔方在总体业务架构图的左上角区域,我们可以看到“用例魔方”几个字。大家可能会比较好奇“用例魔方”的涵义,它是精准测试中非常核心的高级回归功能之一。所谓“魔”是精准测试核心算法所赋予的超能力,所谓“方”实际上是代表测试用例的集合,每个测试用例用一个小方块标识,所有测试用例的集合用一个大方块。当我们把精准测试的和用例分析相关的功能画成架构图形表示的时候,它自然而然地看起来就像魔方。精准测试体系中,测试用例对应的代码逻辑精确而完整的实现了全自动化的追溯和存储,因此赋予了测试用例深入分析的基础能力。在精准测试的用例魔方中,目前存在三个面(随着后续功能的增加,将增加分析的面):即回归测试用例选取、测试用例聚类分析、测试用例最小化,同时辅之以智能缺陷定位技术。当测试用例与代码的追溯关系建立的时候,测试魔方的核心功能区即同步构建出来。为数据的多角度分析,提供了丰富的资源素材库。4.2 软件示波器软件示波器是星云精准测试独有的功能,它如同软件的质量运行情况“追溯穿行器”一样,在测试工程师按下启动键的同时,即时开始建立用例与代码的自动关联。示波器把采集到的测试数据通过可视化的窗口界面进行实时展示,内容涵盖采集到的块、条件和函数信息。蓝色波形代表写入的数值,黄色波形表示读取的数值,用户可以清晰的看到被测系统的数据变化。它如同心跳监控仪一样,如果被测试程序发生了崩溃,软件示波器就像人的心脏停止跳动一样,一根横线拉直向用户报警。如果正常采集到数据,会有持续的波形展示出来,高效而精准地监控程序细微的运行状况。示波器精密捕获每个软件单元任何微小的运行波动和行为改变,支持多次运行数据的比对。它可以根据需要记录崩溃前的至少50个块,使“崩溃重现”变得轻松简单。软件示波器中的测试用例可以从现有的测试管理系统导入进来,先选中用例点击开始,驱动被测试系统运行后,软件示波器就会采集到程序内部运行逻辑对应的波形信息。用例执行结束后,点击停止。这个用例运行阶段的数据,通过开始和结束的点击,边界就记录下来了。图4.2-1 软件示波器面板的正下方可以展示函数的各种调用信息。包括类、函数,参数类型等。清晰的列示出参数列表、类运行情况、内存检测数据、数据库拦截等多角度的数据分析追溯情况信息。示波器观测的维度较多,用例与代码的追溯是精准测试的基础功能,后面的高级算法都在这个基础上展开。用例和代码的追溯就像一个全景的调试器,只要功能由测试人员运行,所有的内部代码执行逻辑瞬间就可以展示出来。通过测试数据的反向追溯分析,开发人员可进行一致性修改,避免修改引入新的缺陷,通过正向追溯结果,开发可对用例的执行进行全面掌握,可用于快速修复缺陷和详细实现确认。同时软件示波器也提供一个辅助的等价类划分的功能,它将一个用例从开始到结束所执行的路径信息终值,完整记录下来。如果两个用例终值不一样,就可以确定为不是等价类。对于很多从功能表面很难界定是否等价类的测试用例,软件示波器可以给出精确结果。因此软件示波器的价值与意义在于:(1)只要测试开始执行,即可以透明方式高速采集功能运行过程中对应程序的运行逻辑。(2)在系统高速运转下采集,可保证对原有应用无干扰,超过1500w/s的采集速率。(3)可采集程序的条件,执行路径,执行参数,内存使用等动态运行数据。为了方便客户在运行项目测试时,一边对被测系统做实时数据监测,一边同步观察到示波器里面数据写入和读取的波形,星云做出了实时数据监测的悬浮窗缩略图,减少了切换带来的工作量。它不影响原有被测系统的界面,以半透明悬浮的方式展示在被测试应用界面的前面。图4.2-2 软件示波器悬浮窗4.3精准测试的双向追溯精准测试的测试用例和代码的双向追溯功能,是精准测试核心技术之一。如同前文的“量子纠缠”,即运行测试用例的同时,精准测试可以通过程序自动的记录并追溯到这个测试用例相应执行的代码。如果测试人员关注某一些代码行,它可以追溯出哪些测试用例在运行过程中运行过这段代码。通过这个技术特性,测试工程师的每个测试用例都可以进行量化分析和统计,提供了开发人员和测试人员之间精准的数字化交流依据, 增加测试和开发的交流效率。双向追溯技术记录了每个测试用例对应的程序内部的执行细节,细致到每个条件、分支、语句块的执行情况。开发人员亦可通过双向追溯的结果去理解程序逻辑,进行软件维护以及进行可一致性的修改。4.3.1 双向追溯技术正向追溯将测试用例和代码执行信息自动关联,可追溯到函数级别及代码块级别;通过正向追溯可直接把BUG定位到故障和缺陷逻辑相应的代码,并提供最后运行的时序数据;通过正向追溯自动记录产生功能对应的详细设计实现,辅助软件解耦和架构分析。图4.3.1-1 双向追溯(正向)-测试用例追溯到代码图4.3.1-2 双向追溯(正向)-测试用例追溯到代码4.3.2 双向追溯技术反向追溯将代码执行、函数、代码块级别和测试用例执行信息自动关联;通过反向追溯可直接观察代码变动所影响的测试范围;协助开发,进行代码修改后影响功能的范围评估;协助测试人员对代码修改部分所影响的测试用例进行评估。图4.3.2-1 双向追溯(反向)-代码追溯到测试用例图4.3.2-2 双向追溯(反向)-代码追溯到测试用例4.3.3 数据追溯技术-追溯测试用例的全景调用精准测试通过正向追溯把测试用例运行的代码执行进行了全景绘制,在全景图中,测试人员可以有效的观察到函数之间的整体的调用与走向,观察出被测模块与上层之间的调用关系。图4.3.3 测试用例运行的代码整体调用第五章 精准测试的核心组件与功能精准测试的核心组件与功能:软件测试示波器、用例和代码的双向追溯、智能回归测试用例选取、覆盖率分析、缺陷定位、测试用例聚类分析、测试用例自动生成系统等,完整的构成了精准测试技术体系。精准测试系统本质是一套强大的计算机开发与测试系统,实现了数据的可视化联动,以及开发辅助分析。它的关键技术赋予了测试用例和代码强大的相互追溯能力,随后衍生实现了很多高级测试功能与算法。精准测试系统将用例深入到代码层分析后,可以大幅改进人工测试所产生的各种问题。接下来将从风险控制、工作协同、敏捷迭代方面详细解析精准测试的核心功能和实际收益。5.1 风险控制5.1.1 七种测试覆盖率星云精准测试提供7种测试覆盖率:分别为:SC0语句块覆盖率、True覆盖率、Both覆盖率、CDC覆盖率、Branch覆盖率、MC/DC覆盖率。用户首先选择分析覆盖率的维度,例如选择了“SCO语句块”维度,那么系统就会将被测试程序的所有语句块结构展示出来,并且用颜色表达覆盖情况,绿色代表覆盖,深蓝色代表未覆盖。同时告知覆盖率的分子和分母都是哪些,非常清晰的展示覆盖率可视化结果。精准测试在前期已经对程序的静态结构进行了深度的分析,因此用户在覆盖率可视化界面,根据选择的维度在代码层面上把需要展示的结构单元都结构化的展示出来。例如图5.1.1-1 七种测试覆盖率中的第二张图 图5.1.1-1 七种测试覆盖率MC/DC覆盖率可视化MC/DC覆盖率,即修正判定条件覆盖,该覆盖率数据 MC/DC是DO-178B/C Level A认证标准中规定的、欧美民用航空器强制要求遵守的覆盖率标准。MC/DC覆盖率可以基本保证被测试软件无缺陷,对于大型系统的可靠性要求很高的一些关键模块,建议采用这个覆盖率标准。MC/DC覆盖简单来说,就是追踪复合条件中每个子条件的真假翻转,在其子条件不变前提下,是否都独立的影响了整个条件的真假值。星云精准测试系统会自动的把各种组合都列好,通过颜色表达哪些子条件已经满足,以及对应满足情况时其他独立子条件的组织情况。图5.1.1-2 MC/DC覆盖率可视化条件组合可视化展示精准测试对于多条件组合的代码,采用了最新研发的条件组合可视化视图进行展示。视图中,用户可以观察到每个条件的真假运行情况,以及条件与条件的组合运行情况。对于测试人员来说,当全部条件组合之间的T与F都完全满足时,即可实现代码全路径覆盖。图5.1.1-3条件组合可视化展示5.1.2 新增代码覆盖率敏捷模式下,因迭代频繁其存量的代码量很大,通常更关注增量覆盖度量。精准测试可以在程序新版本发布后,自动计算新增(变更)代码的范围,给出新增代码的覆盖率。覆盖率的分母中的函数都是变更和新增的函数。与此同时,基于反向追溯的功能,我们还可以给出新增代码对应的测试用例名称。当某个新增函数没有达到很高覆盖率的时候,我们通过反向追溯的用例,可以判定因为哪些功能范围的用例设计不充分,导致了新增代码覆盖率不高。图5.1.2 新增代码覆盖率5.1.3 测试覆盖率范围筛选与再统计在做精准测试或统计覆盖率时,往往测试管理者、开发人员、测试人员为了保证测试覆盖率的正确性,会对某个方法、类进行查看或在统计中把代码中一些废弃的函数、某些特殊情况下无法测试到的代码进行移除(至少是做相应备注),从而让测试代码覆盖统计率达到更加准确。星云精准测试在设计中,通过多种搜索、方法、类、模块过滤等功能,把需要统计的范围进行缩小、不需要统计的去除。根据用户的选择,进行覆盖率再统计展示。图5.1.3 测试覆盖率范围筛选与再统计5.2 工作协同5.2.1 打通开发与测试的隔阂精准测试打通开发与测试的协同工作通道,使得开发与测试能够更好的沟通,提高工作效率。传统模式下,开发人员关注的是代码,测试人员关注的是业务角度的测试用例,彼此的直接关联相对较弱。开发和测试的沟通,基本就是采用自然语言、Excel表格、内部系统等,存在交流信息不够严谨的问题。例如测试工程师发现一个缺陷,提交到缺陷系统,开发需要花费大量时间再行理解、准备数据、复现、调试,直到最后的修正。因为业务上的功能执行和代码并没有明确的关系,通常测试工程师执行完功能测试用例后,让开发人员帮助评审也非常困难。若测试工程师提供的测试结果都是比较模糊的功能逻辑描述,重现缺陷需要花费大量的时间。开发人员修改代码后,对于变更描述,以及变更引起的关联问题描述通常也都很模糊,导致测试又出现新问题。企业采用精准测试技术后,通过执行用例可以直接追溯到对应执行的程序代码块,这样的数据化沟通,将使开发人员和测试人员之间的协同工作效率大大提高。图5.2.1  协同模式5.2.2 源码动静态数据的统一星云精准测试通过插装得到的项目静态结构信息,结合测试后采集到的测试数据,能够精准记录测试的过程,通过这些静态数据和动态数据视图,便于开发人员基于图形化结果进行快速分析。对于不懂开发的测试工程师,通过程序控制流程图的图形以及通过颜色表示的覆盖信息,可以直接看到程序内部漏测的逻辑是什么,也可以通过这些结果直接与开发沟通,进行辅助用例和逻辑的补充。因为内部逻辑的强追溯性并且能够图形化的打开,可以有力保证黑盒测试后期开发快速理解并解决瓶颈问题,保持全程测试的高效执行。图5.2.2-1 源码静态结构与动态测试数据统一图(函数调用图)图5.2.2-2 源码静态结构与动态测试数据统一图(控制流程图)精准测试在程序静态分析的基础上,可以对程序绘制可视化的图形,同时将动态执行的覆盖信息染色到这些视图上。对于不懂开发的测试人员也可以很清晰的看到程序的哪些结构节点没有被覆盖到。例如图形中蓝色的节点是未覆盖的节点,绿色的是覆盖的,因为控制流程图本身有分支,嵌套等各种关系,测试工程师可以很容易判断出覆盖的范围大致是哪些。而如果有开发人员介入,可以更清晰地分析测试工程师执行的用例所遗漏的程序逻辑。图 5.2.2-3源码静态结构与动态测试数据统一视图5.2.3 缺陷最后执行时序分析星云测试可自动捕获缺陷或崩溃发生时,程序最后执行的详细路径信息。缺陷发生后,开发人员能够直接看到缺陷出现时,代码执行的时序和路径信息,直接定位缺陷并排查问题,节省大量的沟通、复现和调试的时间成本。当功能执行发现缺陷后,在软件示波器上可以立即按下“停止”键,那么最后执行的代码序列就可以被抓取到,开发人员可快速定位缺陷最后执行的50个代码块、条件、判断的各种执行信息。在下面视图中,我们可以根据标号(从1到50),看到代码最后的运行时序,在图形里面的每一个绿色小方块为一个代码语句块或者一个条件、判定,在一个大方框下的绿色方块代表一个函数内部的代码块。经过布局算法后产生下述图形。图5.2.3 缺陷最后执行时序分析5.2.4 智能缺陷定位通常测试工程师只是负责发现缺陷,缺陷的具体定位只能交由开发人员来执行。精准测试打破了测试部门的天花板,即通过内部算法能够将缺陷对应的代码出错位置直接定位出来。这相当于增加了测试深度,同时体现了测试数据和测试过程本身的价值。对于测试工程师来说,只要发现用例相似而程序在输出上有对错区分,就可以使用精准测试的智能缺陷定位功能。精准测试平台通过测试人员在功能测试阶段标记的用例执行状态,以及软件示波器自动记录的程序运行频谱,自动分析缺陷的出现的代码块。因精准测试平台可以获取每个用例执行时详细的路径追溯信息,测试工程师只要告知系统用例的状态,例如是否通过是否正确,那么精准测试内部算法就会去根据正确和失败的路径差异进行计算,给出缺陷出现具体位置的可疑度排名。这个功能可以大大增强测试在整个开发流程的参与度和测试数据价值,也让开发人员减少了自己去模拟场景的时间,快速提高开发和测试的协同和配合的效率。对于同类测试用例,经过多组测试可给出非常有效的结果。列出的可疑代码,可直接通过测试过程给出,提升测试的价值及产出。图5.2.4-1 通过功能测试频谱法分析进行智能缺陷定位选择可疑度算法、得到可疑度高的代码块,关联源码后,可根据代码可视化查看具体位置。可疑度计算有一个公式,并不复杂,通常每个代码块有2个变量,四种状态值。分别是:是否执行、是否通过,这样每代码块都有一个可疑度值。星云精准测试提供3种常用计算公式,供大家参考。aep表示通过且覆盖到该块的测试用例的个数、anp表示通过且未覆盖到该块的测试用例的个数、aef表示未通过且覆盖到该块的测试用例的个数、anf表示未通过且覆盖到该块的测试用例的个数。结果表示该块的可疑度。图5.2.4-2 智能缺陷定位展示5.3 精准测试对敏捷迭代的支持5.3.1 敏捷迭代下多版本白盒测试数据的聚合在敏捷环境下由于版本迭代速度很快,每个不用的代码版本上通常只能采集到少量的覆盖率。一旦发布新版本,就意味着代码发生了变化,覆盖率数据就需要重新采集,但是每个版本采集的少量覆盖率,从分析层面上并没有多大的意义。针对以上问题,精准测试给出了“**累计覆盖率”**的计算方法。它将一系列迭代版本的覆盖率,在最新的程序版本上进行投影累加。用户可将一个阶段各个版本的覆盖率累加起来进行分析。算法的思路是以最新版本代码为基础,以某个函数为单位,一直往前累加。直到这个函数在之前的某个版本代码发生了变化,就停止累加。例如下图函数A的4个版本的覆盖都可以累加,是因为这个函数在4个版本中都没有发生变化。而红色的函数B只累加了3个版本,是因为从版本v2.0-2后这个函数发生了代码变更。之前的代码覆盖就不能累加了。星云精准测试-敏捷环境下多版本白盒测试数据的聚合如图所示。图5.3.1-1敏捷环境下多版本白盒测试数据的聚合这种累加是在确保函数代码没有发生变化的情况下,在控制流上对相应节点的覆盖率进行累加。例如下图中3个版本,覆盖率不同的分支和控制流,数据累加后可以看到所有分支都覆盖到了。图5.3.1-2敏捷环境下多版本白盒测试数据的合并分析5.3.2 聚类分析星云精准测试提供的聚类分析功能,根据测试用例的函数执行剖面的向量化信息,对测试用例进行精确的空间距离计算后执行聚类分析。聚类结果可以分析被错误执行的用例,例如不相关的功能点聚类到一起,则说明其测试执行可能存在错误。精准测试提供的聚类分析功能,也可以辅助找到缺陷分布的密集区域。大部分情况下,缺陷分布会呈现2/8的聚集特性。在时间紧张的情况下,我们可以通过聚类结果,每个类选取中心点以及周边几个用例。如果没有问题,就可以去测试其他聚类,如果发现一个类缺陷概率高,那么这个类就需要进行重点测试。通过聚类结果可以分析测试用例的分布密度等信息,辅助进行测试决策。图5.3.2-1 测试密度下图中测试用例分类都有一个名字,这个名字是聚类结果中每个类中心点的测试用例名字,它基本标定了这个类的功能点范围。聚类的大小代表了某个功能范围测试是否足够充分。例如一些应该重点测试的功能,聚类结果中的用例数应该很多;一些小众的功能,聚类中用例数应该比较少。一个类中用例数越多,这个类圆圈比例越大,反之则越小。在聚类的基础上,我们也可以对一个类中的等价类用例进行分析。是等价类的用例,会分成一组专门展示。 图5.3.2-2 聚类分析5.3.3 覆盖率漏洞检出在敏捷迭代过程中,通常没有充分的时间将所有函数的覆盖率都达到一个很高的层级(Level)。精准测试结合代码结构和动态数据综合分析,通过计算直接筛选出潜在的高危测试漏洞,可以在短期内确定高危漏测模块并针对性的解决,帮助用户快速找到严重缺陷。当测试时间不充分的时候,执行完黑盒测试以后,先看测试漏洞列表,里面显示了通过静态信息和动态信息计算,得到的最高风险的漏测点模块。我们可以通过复杂度进行计算,因为复杂度高的模块一般来讲,它是相对重要的模块并且逻辑复杂,如果动态覆盖比较低,我们会优先筛选出来进行排序。处于调用和被调用中间的模块,因为属于中间关键模块,我们也会计算它的扇入扇出,和动态覆盖率信息。如果它的比率很高,将被认为是高风险模块,被筛选出来进行排序。回归时,应优先测试风险指数高的高危模块,补充他们的覆盖率。图5.3.3漏洞检测列表5.3.4 最小测试用例集精准测试也可以对用例集进行优化。比如用户有大量用例的情况下,尤其是自动化用例集含有长期维护的冗余用例。精准测试平台可以对很多重复用例的逻辑进行筛选和过滤,优化出满足当前总体覆盖的最小用例集。图5.3.4星云测试最小测试用例集第六章 精准测试支持不同剖面的分析报告在时间有限,经费有限,资源有限的情况下,我们既要考虑测试是否充分,也要顾及时间、人员、设备配置等限制条件。精准测试可以支持企业不同剖面的软件质量分析需求。6.1 详细的测试总结报告内容测试资源分析:多少人,多长时间、整体测试有效率及执行率测试结果分析:描述需求的测试结果,系统实现了哪些功能点,哪些还没有实现缺陷情况分析:缺陷复现、缺陷处理、缺陷数量、属性、状态分布,缺陷预防、缺陷收敛度度量指标分析:测试覆盖率、测试执行率、测试执行通过率、测试缺陷解决率效率指标分析:进度偏离度、缺陷发现率、用例执行效率和质量等高风险识别与排序:注明当前项目中面临的最严重、最优先的问题整体评估:哪些功能已经实现,哪些功能还未实现,还遗留哪些问题,遗留缺陷分析优化建议:测试过程优化,从测试组的角度为测试工作提出建议图6.1 星云测试的差异报告分析6.2 高级回归测试报告对前期测试执行阶段发现的问题、缺陷集中的功能,业务比较重要且使用频繁的功能进行再次测试,确保系统上线后,已被修复的问题不会重新出现,重要的、高优先级的业务不会发生错误。图6.2智能回归测试用例选取6.3 测试用例库评估报告软件测试的主要工作,是把软件需求映射为软件测试。测试用例是软件测试全过程的核心,也是测试执行环节的基本依据。精准测试充分满足软件测试执行过程中的各种指标:测试用例执行进度测试用例通过率测试用例颗粒度分析识别无用的测试用例识别冗余的测试用例从侧面提供增添新测试用例的依据从侧面提供调整测试用例库结构的依据图6.3 测试用例最小集6.4 精准测试的VIP企业内网私有云可信化报表星云精准测试提供多个剖面的高可靠性测试质量进度追踪报表。当客户端录入测试用例并采集数据后,用户内网web端将产生实时、详实的测试数据分析报表。该报表与普通的测试管理系统不同:普通的测试管理系统人为录入数据的情况比较多,使得数据状态的真实性没办法确切保证。精准测试提供的报表,底层数据来自于执行测试用例时候代码数据的采集,通过专用底层接口上传,完全无法进行数据调整或者篡改和伪造。通过浏览器登录测试系统,选择需要跟踪的项目,就可以实时对整个测试的质量、进度、人员进行精准的分析和管理。企业内网云端管理系统展示的数据基于精准测试数据的分析,所有数据原生精确,支持移动测试+本地测试。测试团队、开发团队、甲方负责人等多种角色都可以登录系统,从各个层面对测试、软件质量进行分析。图6.4项目汇总展示6.4.1 精准测试的VIP企业内网私有云-测试效率的直观展示精准测试报告可直观分析每天的测试效率,通过代码模块和复杂度关系图,看到函数群落测试情况分布及趋势,可直观精准识别系统测试所处阶段。每日增长覆盖率报表:管理者可以清晰的看到整个团队的效率趋势变化,比如刚开始测试的时候覆盖率增长快,到了黑盒测试瓶颈点上升就很慢了。这时候精准测试技术就开始发力,可以清晰地看到它在弥补效率损失方面的优势。覆盖率和复杂度报表:可以很直观地看到测试的质量深度,例如在测试不充分的时候,复杂度高的模块通常覆盖率都比较低,统计点分布自一个左上角的区域(表示高复杂度+低覆盖率),而当测试深入进行,这些点就会向右侧移动。管理者可以非常直观的看到系统测试的充分程度和上线的质量把握。图6.4.1-1 覆盖率每日增长趋势图与黑盒测试瓶颈图6.4.1-2 测试效率换档点与测试深度趋势观察表6.4.2 精准测试的VIP企业内网私有云-测试用例排行图测试用例排行分析报表:可直观展示参与测试工程师所执行的用例数、通过率和缺陷率,真实记录并分析每个测试用例的实效性。星云精准测试-测试工程师实效精准分析系统,将参与的测试工程师所执行的用例从逻辑覆盖映射到代码覆盖,真实记录并分析每个测试参与者的工作实效。以逻辑覆盖为基准的而不是用例数量为考核标准。图6.4.2 测试用例排行图6.4.3 精准测试的VIP企业私有云-测试用例双向追溯与覆盖率可视化通过用户的内网精准测试web报表,可以追踪每个测试用例执行的覆盖率和执行的函数路径信息,那些没有真正执行的用例,将无法伪造其对应的覆盖率信息。图6.4.3-1测试用例双向追溯追踪每个用例执行的函数信息以及具体的代码覆盖信息,在web端展示代码覆盖率视图,更具体的分析用例的执行情况。图6.4.3-1覆盖率可视化6.5 精准测试在数字化转型中的作用 完成数字化转型。提高软件交付质效、实现快速迭代持续交付,有效呈现测试价值。培养业务和测试的“两栖专家”。从不同角度提供有价值的数据依据,使测试团队既能熟悉业务知识、业务场景,又具备较强的业务分析评估和整合创新的能力。数据化交付。实现企业内部云平台建设、明确各工程活动环节的交付物和交付标准,并将质量验证标准、验证手段和监控工具嵌入流水线,保证各环节的有效性,对质量趋势进行提示和预警,及早发现缺陷,实现质量可视、过程可追溯、可审计。建立测试数据资源池,整合测试资产。利用大数据、人工智能等技术建立质量智能分析模型等,为“产品质量智能分析平台”提供有效数据。减少因人员变动而产生的成本影响。一般外包人员的流失率普遍为20-40%左右,重新招聘和培养,将对项目进度及成本进度,造成很大影响。因篇幅限制,完整版可查看 星云测试官网(www.teststars.cc)
  • [技术干货] 【敏捷智库知识卡】第12期 需求剪不断理还乱(内附1-12期卡片合集下载)
    知识卡反馈有礼,点这里!往期卡片回顾:【敏捷智库知识卡】第1-7期合集【敏捷智库知识卡】 第8期 拍脑袋估算法?OUT!:科学估算,平稳生产,嗷闪!【敏捷智库知识卡】第9期 微服务架构难落地?MSA实施指导框架来帮你【敏捷智库知识卡】 第10期 任务不让指派还没人认领,我咋整?—— Scrum Master的心酸谁能知?【敏捷智库知识卡】 第11期 项目团队人员变动频繁怎么办——大牛走了,你怕不怕?1-12期卡片合集请点击附件下载
  • [技术干货] 【敏捷智库2020年8月刊】 本期推荐:包不同的沙雕敏捷,敏捷需求管理系列分享
    【摘要】 敏捷智库月刊,每月更新一刊,欢迎大家品读。本期推荐包不同的沙雕敏捷、敏捷需求管理系列、规模化敏捷、敏捷教练Lucy和实战专家管知时、RSG2020,精彩内容值得分享。月刊反馈有礼,点这里惊喜等着你~【敏捷智库2020年6月刊】 本期推荐:敏捷和效能专家郑立,第14次敏捷报告重磅解读【敏捷智库2020年7月刊】 本期推荐:专家Yegor解密软件质量墙,DevSecOps的前世今生完整无水印版请下载附件。
  • [交流吐槽] 《敏捷团队绩效考核》读书笔记
    Part Zero: 引言泥石流主播管婷婷是笔者心目中第三个美女敏捷大师(按出场次序为序)。第一个是《敏捷无敌1》中的敏捷圣贤(鉴于《敏捷无敌2》中的敏捷圣贤正在向冬哥融合。。。此处特意标明是1。。。),第二个是《敏捷转型》一书的作者王明兰姐姐,第三个就是她了。笔者曾经为了那句优美的开场白而陶醉:“"欢迎大家来到无法帮助你成为职场精英,也不想帮你出人头地,也没有能力让你走上人生巅峰的只能让你过毫无亮点·,平淡无奇每一天的职场泥石流直播间"。(笔者不禁又贴了1遍,且默默地念了2遍。。。)能说出这么丧的语句的美女,写的书会是啥样子?很多人一定像笔者一样,被勾起了兴趣。笔者也是,不过幸运的是,笔者不必为管姐姐写的书花钱,因为Lucky的笔者抽奖抽中了这本书。尽管,书籍直接从电子工业出版社的仓库寄出,明显在书籍的敏捷出版流程中上缺少了重要的作者签名环节,但是,俗话说,拿别人的手短,吃别人的嘴软。笔者仍然认为,不写读后感回报一下自己的运气,不算好汉。(这就是中奖的那本书)于是,笔者就开始了速读之旅。(以上图片来自于网络)Part One :书籍导读在看到书内容之前,面对《敏捷团队绩效考核》这样的标题,笔者曾因为这应该是一本对敏捷团队的成员如何考核的书,大概应该会有对Scrum Master该如何考核,对Product Owner该如何考核,对开发团队的成员该如何考核等等展开阐述。但是看完之后,除了发现在P103,作者在介绍KPI的优缺点的时候,提到了”对SM的评估定性的可能性更大,KPI评价体系HOLD不住“之外,书中很少有对基于敏捷团队,特别是典型的Scrum团队的角色,进行具体如何考核的具体说明。而是从贝尔宾团队的角色理论,提到了对以下9种角色进行分析:(以上图片由Jason Wang老师提供)并且由此引出,敏捷团队的绩效考核,要注意考核团队成员的软技能。特别是要考核定性指标等等话题。这不禁让笔者对作者的作品产生了大大的怀疑。连基本的Scrum角色的评价说明都没有,这怎么敢说是一本关于敏捷团队的书呢?本书的小标题是《KPI、OKR和360度评估体系的应用与实践》,管姐姐在书中的第三章、第四章和第五章分别对标题提到的OKR、360度考核和KPI及平衡计分卡的考核,以及这些考核如何应用到敏捷团队,做了具体的介绍,作者颇有见地地提出了以下见解:(1)OKR是最适合敏捷团队的绩效考核工具(P47)。它通过对Object(目标)和Key Result(关键结果)的分解和实施,并通过员工参与目标的制定,提升了员工的积极性。OKR的季度目标数量应保持在3~5个,每个目标的关键结果也保持在3~5条左右(P53)。对于目标,需按照优先级排序(P54),O需要相对稳定,但KR可以随时调整(P55)。但是,对于敏捷团队而言,定量指标比较容易在OKR上体现,但是定性指标却很难在OKR上追踪和评估(P62~P63)。所以光靠OKR不行,需要结合360度评估法对间接贡献和软技能进行评估(P63)。(2)360度评估是一种能对绩效考核的定性指标进行评估的科学方法。它通过对被考核者的直属上级、客户代表、直属下级、评级人员、被考核者自己和其他紧密合作者进行评估,多角度的搜集定性指标,以平衡单一角色对定性指标进行评估的偏颇。书中对自我评价与他人评价之间的不同评价结果,还给出了如何判断这些评价结果的建议(自我评估结果与他人评估结果四象限)(P88~P89)。但是,尽管360度评估结果是一个打分系统,但其分数不应该直接用于横向比较被考核者绩效的优劣(P90)。此时,绩效考核的管理人员应该根据这些评估的统计结果,以及定量指标的结果,对员工的绩效进行排序(P91)。书中还对360度评估的一些操作要点进行了介绍,比如对被考核者的6~12个紧密接触者搜集报告、注意选择高质量的评估者以及评估者角色的权重、可以让员工提名一名被评估者、选择2~3个月评估一次,通过交流倾听的方式允许被评估者进行表达和反馈、通过先扬后抑的方式不让被评估者难堪、聚焦1~2个改进点、关注特性明显的指标等等方式,对360评估的方法提了有效建议(P92~P94)。关于360度评估对于敏捷团队绩效考核的意义,作者提到:确实定性指标是依赖于主观评价,但通过360度的评价方式,主观评价的结果可能会趋于客观。另外,基于360度评价形成的“员工画像”,以及通过“员工画像”形成的“敏捷团队画像”,可以为组织的改进提供高价值的参考(P96)。(3)KPI(Key Performance Indicator)是对工作绩效进行量化的最直接的方式。它有利于将顶层经营设计在组织内进行高效传达,通过层层分解,将目标分配给各级部门、子部门和个人。目标明确、容易聚焦、直观、简单。但它的劣势也尤为明显,只聚焦财会指标,适合于传统行业,但对于新兴行业、新岗位和新流程很难落实。因为它只能评价结果,不能揭示细节和深层次原因、也无法评价定性指标(P102),会让人聚焦指标而不是聚焦目标,并且容易导致员工通过粉饰KPI来换取高绩效(P104)。关于KPI在敏捷团队绩效考核的问题,作者指出:组织内部也一样存在相对工作内容确定性高、工作流程成熟和所需技能稳定的岗位,对这些岗位是可以使用KPI进行考核的(P108)。KPI用于定量指标的考核一直很有效。(P105)。(上图为雷布斯对KPI的表述,表明了他去KPI考核的强大决心)(4)平衡计分卡是一个将绩效分为财务、客户、内部流程和学习与成长四个维度的全面的业务评价系统,可以平衡短期行为和长期行为、长期目标与短期目标、结果性指标和动因性指标、财务指标与非财务指标、内部群体和外部群体等等(P110~P111)。在敏捷团队上,由于敏捷的实践方法多数是跨职能合作、激励、授权、培训、协助沟通等等,这些内容很难量化结果。此时如果引入平衡计分卡,可以使得敏捷的实施有更多的资源支持(P111)。在介绍完4种方法之后,作者提出了四个方法针对不同类型的组织进行评估的方式(P112),包含:(1)敏捷成熟度高的组织,可采用OKR+360结合;(2)敏捷转型初期的组织:可采用平衡积分卡+360结合;(3)业务稳定的组织:可采用KPI+360结合;(4)对于偏领导岗位(包含SM):可采用OKR+360结合。当然以上也不是一概而论。书中还花了一个章节(第六章),对敏捷组织中的中层管理人员如何考核做了描述:中层管理人员的绩效包含业务绩效、合作绩效和管理绩效。业务绩效以定量指标为主、后两类则以定性指标为主(P115)。敏捷的领导力的核心是:将中层管理人员定位成:为团队提供清晰目标而非任务、利用员工内在驱动力而非外在刺激、使用引导和教练技术帮助员工成长而非命令和直接解决问题。(P121)敏捷管理人员,应根据情景领导模型,根据不同的环境和管理对象的不同,采取不同的领导方式,最终实现员工的高工作意愿和高工作能力。针对中层管理人员的绩效考核方式,可以采取360度+KPI/ORK/平衡计分卡(之一)结合的方式。其中优先考虑360度+平衡计分卡的方式。(P125)对这些人员考核的目的是打造高绩效团队的能力,而不是考核管理人员本身有多强大(P126)。书中还对通过行业和工作特点的红海和蓝海属性,考核本身的成本,以及组织的文化特征(如强人型、拼命干-尽情玩型、攻坚型、流程型)选择合适的考核方法做了阐述。(第七章)。本书还有其他一些章节,由于篇幅有限,不再赘述。。(其实是笔者懒得不想写了,怕写完了读者就不看作者的书了。不过冠冕堂皇的原因是:读者朋友们,要知道二手读后感一定没有一手读物好看,何况书籍封二还有好看的作者照片,想看书吗?去买买买啊。。。)Part Two :读后敢言话说敏捷跟绩效考核的关系这块,似乎是敏捷界不曾提及的话题(也许提了,反正笔者也不是敏捷界的,不知道~~)。但是从书中描述的内容来看,我感觉敏捷团队的绩效考核实施还存在一些巨大的问题需要克服:(1)敏捷团队是一个强调快速适应变化的团队,强调的是快速解决问题,但是作者提到的OKR实施中的巨大成本(比KPI高好几倍)。这不禁让我感觉,是不是它根本上就跟敏捷基因是不合拍的。想想看,一个快速反应部队正在前线侦察,敌情明显,正在随机而动,结果后方大本营传来”回来,开会考核了”的消息。前线的布阵,诱敌深入可能都会功亏一篑。从书中的描述看来,绩效考核有各种会议,包含但不限于:制定目标的沟通会议,跟踪目标的沟通会议,打分评价的会议,以及结果出来后的沟通会议等等(或者不是会议,而是准备材料,讲解材料,阅读材料等等)。也许还有落实目标的宣讲会,讲解打分标准的培训会等等,不一而足。敏捷强调的是小团队作战,结果降临团队的是好几个不同评价体系的人:把你派到这个敏捷团队的上司,让你给其他人做KPI评价的路人甲,让你给其他人做OKR评价的宋兵乙,以及让你自己评价的HR丙。天啦,你还要干正事吗?996甚至007就是这样形成的吧?我(貌似)曾在泥石流群里面抛出了一个典型的话题:SM一般情况下大概没看到有几个加班的,但是开发团队大概率是天天加班,但是加班的原因如果是白天在应付各种考核会议,或者为考核会议提供各种评价你的或者你评价的那些材料,你白天干活干不完是免不了的,结果SM下班了,你的直属领导也下班了,而你还得把白天落下的活在晚上给补完。这种情况下,开发团队乐意实施绩效考核吗?(2)在绩效目标和敏捷项目团队的目标方面,作者提出了采用看板的方式存放OKR的目标,将OKR的目标经常作为标语一样出现在被评价员工的视野之中(P56),这其实就引出了一个比较关键的问题。绩效目标本身,到底是对所有员工都是公开的,还是仅仅对员工及其上级(包括上上级)及HR开放?因为被考核员工的绩效大多是通过不断地商议跟其直属上级制定的,如果这个目标公开给其他人,那么一定会造成大家互相攀比绩效的问题。他职级跟我差不多,为啥定的OKR比我低很多,原因是什么?那我是不是也该制定下跟他差不多的目标?这样下去,所有员工的OKR没准会被拉低到最低OKR目标人员的水平,导致公司或部门的整体OKR无法达到目标。(最短木桶原理)就我个人的经验来看,一般绩效都是跟年薪挂钩的,而很多公司的年薪都是保密的。我20万年薪,他30万年薪,做的事情差不多,但是是因为我的议价能力不如他,或者我并不是老板的熟人,导致我的薪资水平如此低廉。而绩效本身又是跟薪酬的绩效部分挂钩的。如果绩效的目标确定的不好,对我个人而言,就是巨大的利益损失。这样下去,OKR本身也会变成一个虚假的数字。并不能反映我所能达到的实际能力和水平。我宁可露拙也要保护自己的利益。因为本来拿钱少,那我就少做点事情吧。。。(3)在敏捷绩效的实施过程中,作者在文中强调了对OKR工具的使用(P56),比如市场上的OCR管理工具,或者大公司自己开发的绩效管理工具。但是,上面(P91)也提到,管理人员拥有对员工定性指标的最终确定权力。那么不可避免地,在绩效考核系统,就要求有自动调整的部分(笔者在绩效考核的项目需求研讨时,也遇到过需要常常允许手工调整考核结果这样的需求)。当然,从系统而言,允许手工调整是一个系统灵活性设计的一个特性,但是对于绩效考核本身而言,这样的内容越多,说明考核的水分可能就越大。因为决定绩效考核结果的,也许就是你的直属领导心里的那杆秤。或者是最高领导给HR设置的人力资源指标。领导想给你发绩效的时候,你做的再烂(比如曾经的项目导致系统崩溃过),我也给你调整到高分。如果我不想给你发绩效的时候,你的沟通能力,客户反馈等等指标,就都是差的。即便你代码写得再好也没用。你还愿意在这里呆着吗?赶紧走吧。。。(4)从书中敏捷团队最常用的OKR方法可以看出,O需要反复迭代后才能确认的(是不是要为O的制定搞个Sprint?),KR确实可以随时变的(P70~P71)。这样就导致了自己的关键结果可能处于不断地变换之中,一旦觉得这个可能达不到了,那就改成另外一个。这样的做法感觉跟敏捷有点背道而驰的意思。外界环境变化了,为啥O不能变?敏捷宣言的价值观之一是什么?——响应变化高于遵循计划。结果你说O确定了就执行吧。这还是遵循计划,仅仅是实现计划的路径发生了变化。所以,书中多次提到的”对于敏捷而言,唯一不变的是变化“,是否就不生效了?因为还有一个唯一不变的,就是O。(5)所以就以上几点来看,我个人感觉,敏捷绩效考核可能存在巨大的陷阱,按照著名敏捷教练Ethan Huang的说法,敏捷团队可能就不应该搞敏捷绩效。如果绩效考核的目的是达成战略目标,以及激励员工(P2)。如果我们实现了这些目标,还需要敏捷绩效考核干嘛呢?(不过这些话都是黄老师说的)其实我个人还有其他好几个角度想说,但是到吃饭时间了。我也不能无限制地写读书笔记而不学习其他东西。还有任务要完成,否则,我怕今年年底我拿不到绩效。就这样交差吧!如果有机会,我还可以再补充几点意见。但是,还是希望大家好好看看管姐姐的书,顺便多看看泥石流的直播。毕竟看书,是我们生活的一大乐趣。(全文完,谢谢阅读)
  • [热门活动] 【DevCloud · 敏捷智库】【合辑】 回帖赢码豆获奖名单公布----20200810期
    用户昵称奖项获得码豆分享链接张辉周最佳回复,回复有奖2200https://bbs.huaweicloud.com/forum/forum.php?mod=redirect&goto=findpost&ptid=24443&pid=300517&fromuid=216950victor98回复有奖200Lhosv回复有奖200努力变好回复有奖200yhl回复有奖200