首先,我们写了示例,或者叫单元测试。然后利用IDE来创建还未创建的类和方法,因为这样比较快。领域驱动开发(DDD)可以保持设计和代码 语言与业务一致,BDD帮助我们关注行为、价值和如何使用类的示例。在发现某些新的、不寻常的或者遗漏的东西时,这帮助我们与业务建立有用的对话,而且由 于代码的设计和业务保持一致,对代码的修改难度,将与引起这些修改的业务流程修改的难度一致。
当我们完成了对每个类的编码后,我们继续对这个类的合作者编码,直到所有stub出来的类都有一个真正的实现。通过这种方式,我们可以保证我 们只做了那些可以为UI提供价值的事。我们不会为那些我们认为将来可能会用到的方法或数据库列来写代码,因为这在当时不是问题。这也帮助我们简化我们的设计。
好的设计可以在我们更深入理解业务流程时,简化代码修改,并为创建UI需要的价值提供更多的选择。就像Chris说的,“在金融领域,选项拥 有价值和过期时间。真正的选项-真实世界中的选项-也有价值,以及一个再没有选择余地的时间。有时,推迟决定并保持选项是值得的。”好的设计需要更长的时 间,但是这样是值得的,因为它让我们能够推迟决策,或当我们有更好理解时能够改变我们的决定。
这就是为什么我们使用好的设计实践,和像单元测试与系统测试这样的自动化反馈环,都是为了让修改变得容易。
不一定非要让开发人员来写这些代码,不过如果你正在写,那么你最终会成为一个开发人员。
我们为下一件最重要的事做准备
让我们看一个例子。
有一个简单的愿景:noughts and crosses游戏。出于练习的目的,我们假装没人玩过这个游戏,也没有人看过战争游戏。我们有一个很大的特性集,叫做“游戏规则”。
我们可以为这个特性集写一个故事。
为了玩Noughts and Crosses
作为一个玩家
我希望当有三个相同图形在一行时,有一个人获胜
下面是这个游戏的一个场景,以及对应的UI,使用JBehave来自动化:
给定一个这样的网格
OO.
XX.
X..
当玩家点击a3时
网格将会变成
OOO
XX.
X..
并显示“O 赢了!”
下面是定义GameModel应该如何工作的示例代码:
@Test
public void shouldNotifyObserverWhenTheCurrentPlayerWins() {
// 给定一个X将要获胜的布局
GameModel game = new GameModel();
game.playerActsAt(0, 0);
game.playerActsAt(1, 0);
game.playerActsAt(0, 1);
game.playerActsAt(2, 0);
MyGameObserver observer = new MyGameObserver();
game.addObserver(observer);
// 当X获胜时
game.playerActsAt(0, 2);
// X应该是当前的玩家
// 而且X获胜了
ensureThat(observer.game.currentPlayer(), is(Player.X));
ensureThat(observer.game.message(), is(“Player X wins!”);
}
一旦我们完成这些示例,就可以开始编写代码了-GameModel类-来帮助我们使这个示例运行通过。
在这个例子中,我们将GUI作为观察者mock出来,使用为这个例子创建的类-MyGameObserver。通过mock每个单元的协作者,我们可以保证示例与其他协作者没有耦合,包括那些还不存在的协作者。这让改变变得容易。
我们没有分数,我们不知道X是不是一直都先走,我们不知道有人获胜后应该如何-我们可能需要重启程序。我们只为这个场景、这个故事、这个特性集和这个愿景写了足够的代码。我们保持代码易于修改,这样就可以在以后为更多的场景和故事添加代码。
当我们完成时,我们就发布!
当所有的协作者都被真正实现时,我们就写完了这个场景的代码。
当一个故事中的所有场景完成时,我们就完成了这个故事。
当一个theme或特性集中的故事都完成时,我们就完成了这个特性集。
当涉众确认一个愿景的所有特性集都完成时,这个愿景就可以发布了。
在每个阶段,我们都努力尽快得到反馈
通过自动化示例和场景,我们能够发现代码是否能够工作。
通过自动化集成和部署到真实环境或相似的环境,我们能够发现是否有之前没有意识到的技术问题,或者没有考虑到的涉众。
通过尽快给涉众展示应用程序,我们能够发现我们是否可以完成愿景。
在敏捷和精益方法中,还有很多其他的反馈环。这意味着我们在开始工作时要假设可能会犯错误。我们不需要在一开始就保证每件事都是正确的-我们可以从“刚好够用”开始。
在每个阶段,我们都努力减少浪费
精益生产努力减少库存-那些还没有安装到可工作的汽车上的零件。用同样的方法,我们努力减少那些没有添加到可工作的特性集和愿景上的用户故事、场景、示例和代码。在看板系统中,信号被传递到每个阶段中,这样每个工作站就知道要为下一个工作站生产一些特定的东西。每个被生产出来的部分都是因为某个工 作站需要他们来满足客户的需要。这就是一个拉动系统。
在其他生产系统中,生产线上放着成盒的剩余零部件以备使用。人们需要围绕这些部件工作。这些部件需要维护、保护、空间等,如果商业需求的改变超过一定程度,这些部件就要被丢弃。
在一些软件项目中,我们也做了同样的事。我们创建特性集是因为我们有足够的预算。我们对详细分析那些我们相信会在3个月后需要的故事。我们为我们认为有趣的特性创建视图。我们创建数据库列和表来存储没有人会使用的信息,以及更多的视图来收集信息。所有这些都需要维护,需要和他们一起工作,而且在商业 需求改变时扔掉。
通过在需要使用时才生产需要的东西,精益生产线可以避免这些浪费。相似的,我们也可以在我们的项目中,通过只在需要时才创建来避免浪费。
这就是我们的拉动软件生命周期
最有价值的软件是还没有写出来的软件。
愿景促使涉众创建特性
特性促使BA创建用户故事
用户故事促使QA创建场景
场景促使UI专家设计UI
UI促使开发人员编写代码
代码促使开发人员编写更多的代码
我们做到能够支持下一件最重要的事
当我们完成时,就发布。
在每个阶段,我们都努力尽快得到反馈
在每个阶段,我们都努力减少浪费。
在生命周期中的每个角色都不需要一定是全职的-例如一个开发人员也可以做BA或QA。在这种情况下,他会带上BA的帽子。如果一个人不考虑他将从下一个阶段中得到什么-例如代码-那么就几乎不可能得到他在下个阶段需要的东西-例如用户故事-因此让不同的人扮演这些角色还是值得的。
不管用什么方法论,总是有不止一种方式来实现同一个目标,不止一种方式来应用方法论,以及不止一种拉动系统适合你。
当Dan North发明BDD时,他说:“程序员想知道从何处开始,测试什么不测试什么,一次测试多少,如何为测试命名,以及理解测试失败的原因。”
这个概括应该能让你知道从何处入手,什么好用什么不好用,一次应该做多少,如何称呼正在做的事,以及如何在软件生命周期的每个层次获得反馈;这样不管编写什么软件,都是好的软件。
文章来源于领测软件测试网 https://www.ltesting.net/