<th id="v9g6b"><track id="v9g6b"></track></th>

  • <em id="v9g6b"><acronym id="v9g6b"></acronym></em>
    <progress id="v9g6b"><pre id="v9g6b"></pre></progress>
    <tbody id="v9g6b"></tbody>
    <button id="v9g6b"><acronym id="v9g6b"></acronym></button>
    <rp id="v9g6b"><ruby id="v9g6b"></ruby></rp>

        <dd id="v9g6b"></dd>

        <em id="v9g6b"></em>

          B/S开发框架测试驱动开发(TDD)指导书(九)

          本指导书详细介绍了敏捷实践——TDD的各个方面。TDD是提升单元测试有效性的工程方法,web开发框架中遵循测试先行、小步快跑和及时重构的原则,能有效减少过度设计,促进降低开发成本、以及提高软件质量和设计效率。另外,本指导书还对遗留系统的TDD,以及TDD工具的选择给予参考性建议,B/S开发框架并通过大量的实践案例引导你充分体验TDD的魅力。

          TDD实战(三)

          web开发框架项目大部分是.net项目的,我们该篇文章已.net为例为大家讲解。

          本实战是以Provision服务控制组件为对象,介绍使用.net语言实施TDD的情况,可供使用.net语言的产品参考。

          web开发框架TDD的开发模式就是先写测试代码,然后再写实现,TDD就是一个红-绿-红-绿-……不断重复的过程。希望通过先写测试,可以完善代码的设计,保证实现代码的质量,并且这些测试代码能够给后续的重构提供保证……TDD可以给我们带来许多好处,可是TDD中也存在许多困难。在实践过程中我们总结出了以下几点TDD实践方式。

          web开发框架.netTDD实战

          1.1.1  选取合适的测试粒度

          之前我们写测试代码提倡代码覆盖率,提倡分支覆盖率。web开发框架项目实现的时候就是针对每个函数写测试代码。于是我们辛辛苦苦的把测试代码写完后,可实现代码如果改动了,测试代码也需要跟着更改。如果实现代码的改变太大,那么测试代码基本上重写一遍。实际代码中一整个类的改变都是很正常的,更不用说一个函数的改变。于是测试代码的维护难度随着项目的进行越来越困难,并且之前实现的测试代码经常只能被抛弃。这是什么原因照成的呢?是由于之前我们选取的测试粒度的问题,我们针对测试的函数是不稳定的,一个函数在某种实现下有一定价值,但是如果实现方式调整了,那么这些函数的输入和输出自然就跟着变化了,甚至整个函数也都废弃的情况也是很正常的。皮之不存,毛将焉附,测试代码自然只能抛弃。所以在实现测试代码之前,首先就要选取合适的测试粒度。写测试代码不一定是针对函数的,也不一定是针对某个类,应该针对是一组具有稳定功能的代码,这组代码有固定的输入和输出。那么针对这组代码写的测试代码才有稳定性的保证,才能持续集成。具体到敏捷项目中开发模式,测试粒度的范围可以是一个用户故事中的一个功能点。比如我们开发服务控制组件(请结合附带的代码一起看),需要实现以下几个功能:

          l  单个用户请求不应并发执行

          l  多个用户的请求可以并发执行

          l  无主响应应该返回错误

          l  高优先级请求优先执行

          l  同一用户的优先级可以通过后续请求被提高

          l  同一用户已经处理过的请求不应影响后续请求的优先级

          以上6点就是服务控制组件需要实现的基本功能,这每个功能都有明确的输入和输出,不管最后服务控制组件如何实现,这些功能点的行为都是一致的。如果今后服务控制组件需要重构,重构后的代码也是需要实现同样的功能点的。web开发框架中这些功能点是系统中稳定的边界,是能够用来构建稳定的测试代码。于是web开发框架项目针对每个功能点写一个测试函数。(具体可以参见实现,为了保证测试代码的可读性,我们尝试用中文命名测试代码的函数名,以上每个功能点的测试函数在ControllerComponentTest类中有同名的测试函数).举个测试单个用户请求不应并发执行例子如下,其他的可以看源代码。

          @Test

              public void 单个用户请求不应并发执行() throws Exception
          {
          
              String subscriber = "123456";
          
              String requestID1 = "0001";
          
              String requestID2 = "0002";
          
              final Message msg1 = createMsg(subscriber, requestID1, 0);
          
              final Message msg2 = createMsg(subscriber, requestID2, 0);
          
              final Message response = createResponse(msg1);
          
              inputQueue.put(msg1);
          
              inputQueue.put(msg2);
          
              process();
          
              i.assertEquals(msg1, i.assertOutputed());
          
              i.assertNotOutputed();
          
              inputQueue.put(response);
          
              process();
          
              i.assertEquals(response, i.assertOutputed());
          
              i.assertEquals(i.assertOutputed(), msg2);
          }

          在开发完所有的测试函数后,就给将要实现的服务控制组件规定好行为了,web开发框架开发的时候就是采用合理的实现方式,把所有的测试用例全部通过即可。


          1.1.2  开发测试框架支持提高测试代码开发效率

          web开发框架项目在选取好测试粒度后,我们发现测试代码还是很难写。为什么很难写,主要原因如下:

          l  需要测试的单元是系统中一部分,运行起来需要系统的上下文。

          l  测试代码需要构建一些测试数据类

          l  需要写一些额外的代码来组装测试数据或者触发测试单元的行为

          造成上述问题的一个原因就是测试代码和实现代码的耦合性太强,测试代码是依附于实现代码的,并且没有对测试代码的实现进行设计和抽象,对于实现代码有一个框架支持,但是测试代码没有。所有我们在开发测试过程中,构建了一个测试框架SnowBall来支撑开发测试代码。SnowBall实现以下三种功能:

          l  Dependency Injection,负责公共环境的准备,每个测试类可以选择需要注入的公共环境

          l  Fixture Injection,负责测试使用数据的构建。

          l  Helper Injection,实现测试API,使用测试API可以方便的组装测试数据,出发测试函数的行为。

          通过SnowBall框架,首先可以隔离测试代码和实现代码。不管是公共的环境数据,还是测试用例需要用到的测试类,之前我们的做法就是new一个环境或者new一个测试类,如果不可以new就采用Mock的方式实现等。这样实现的结果就是如果实现代码更改,那么测试代码new的地方也需要修改,如果在很多个地方都new了同一个对象的话,那么就需要在这些地方都做相应的修改。有了测试框架后就避免了类似灾难的发生。通过测试框架,我们统一管理的公共环境数据,测试数据产生的方法,测试代码如果需要使用公共环境数据或者测试数据,只需要从测试框架中取得即可。比如在FlowInstanceTest..net测试类中:

          a. 通过Dependency注入来获取公共的环境RuleEngineService。具体实现代码如下:

              @Inject

          IRuleEngineService ruleEngineService;

          构建出来的ruleEngineService就可以直接使用了。

          b. 通过Fixture Injection来获取测试数据类FlowNode,具体实现代码如下:

              @Fixture(NESRV_CFD_NODE.class)

          Provider<FlowNode> cfdNodeProvider;

          构建出来的cfdNodeProvider还可以产生出多个FlowNode实例,具体使用如下:

          nowaitNode = cfdNodeProvider.get();

          skipNoWaitNode = cfdNodeProvider.get();

          c. 通过Helper Injection来获取测试API,具体实现代码如下:

              @Helper

          TestHelper i;

          有了这个测试i,就可以写出如下简介的测试代码:

          i.connect(startNode, nowaitNode, waitNode);

          1.1.3  web开发框架TDD测试驱动BUG修复

          当web开发框架项目一个Bug出现时,以前通常的做法是:定位问题——>修改实现,使Bug消失——>提交代码。由于这样的模式没有任何测试代码保证,我们的修改可能影响其他功能,引入新的Bug。同时在其他地方的修改,还可能使这个Bug再次出现。采用TDD模式开发的做法就会是:写一个测试用例让Bug重现——>定位问题——>修改实现,测试通过——>重构——>执行测试——>让所有测试通过——>提交代码。TDD模式让所有出现过的Bug都有一个测试覆盖,从而保证了后续的任何修改都不会使之前出现过的Bug再次出现。同时,系统已有功能也都会有测试覆盖,我们在修改Bug的时候不会担心会影响现有功能。比如在服务开通引擎中存在一个BUG,对于异步的节点可以正常跳转,但是对于同步的节点不能正常跳转。于是在FlowInstanceTest类中构建两个测试用例:

          @Test
          public void 异步节点不满足规则时应当跳过() throws PlatformException, ComponentException, InterruptedException
          {
            ......(具体实现参考附带源码)
          }
          
          @Test
          public void 同步节点不满足规则时应当跳过() throws PlatformException, ComponentException, InterruptedException
          {
                ......(具体实现参考附带源码)  
          }

          开始时候同步节点的测试用例是不通过的,在修改好BUG后这个测试用例通过了。

          总之,TDD是一件有价值的事情,同时也是需要技巧的。TDD的实践也许很困难,但是,坚持下去,经过web开发框架不断地积累和摸索,TDD将会无限美妙。

          标签: B/S开发框架测试驱动开发

          网站&系统开发技术学习交流群:463167176

          本站文章除注明转载外,均为本站原创或翻译,欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,共创和谐网络环境。
          转载请注明:文章转载自:软件开发框架 ? B/S开发框架测试驱动开发(TDD)指导书(九)
          本文标题:B/S开发框架测试驱动开发(TDD)指导书(九)
          本文地址:http://www.sajuice.com/OrgTec/Agile/0015.html

          相关文章: 深入敏捷框架--公司级Story培训指导书(二)

          电话
          电话 18718672256

          扫一扫
          二维码
          本港台开奖 <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>