Posts Tagged TDD

一步一步来TDD开发之利其器(2-2)

在上篇介绍完NUnit 之后,接着介绍的是一款相当不错的mock工具—>Moq

依然按照之前的规矩来介绍

什么是Moq?

moq 是一款相当不错的Mock 工具。当然有人会问,Mock 又是什么呢?从字面上来说,是“假的”的意思,在Coding 中,Mock 的意思即是做一个假的对象,来得到返回值。

为什么要Moq | Mock ?

1、真实的对象创建可能超级麻烦

2、我们没有必要去观测一个底层的对象

3、对象产生了一些不可控制的变化(比如Random)

4、真实的对象压根还没写呢。

举个简单的例子,在经典的三层架构中,最麻烦的莫过于DAL 层,因为他需要跟数据库打交道,所以涉及到很多的东西,所以可能很麻烦;或者这个时候甚至DAL 层还很不稳定,经常出现加字段,变更属性等奇怪的需求导致BLL几乎无办法测试;也有可能你现在的数据库根本禁不起测试数据的折腾,一旦写入了测试数据,则数据库里原有的数据就乱了。这个时候,别放弃你测试BLL的计划而转身去与DAL折腾,Mock军队的Moq,就会来拯救你。

怎样使用Moq

使用Moq 有几个先决条件:

1、被Mock 的类不能是seal 的。人民群众纷纷表示没影响,因为我们在做设计的时候,都知道应该做成松耦合,抽象出接口,我们只需要Mock 这个接口就ok了

2、方法必须是virtual 的。人民群众再次纷纷表示没影响,原因同上

3、不能模拟静态方法。影响较小,只不过有的地方确实还是不太方便,比如说Mock 某个Helper 类,只不过话说回来了,都Helper 类的,也不需要去Mock 吧。

 

有了这几条,我们就来正式的介绍Moq的用法

首先,需要我们来抽象出一个实现类的接口,比如这里的DAL

Read the rest of this entry »

Tags: , , ,

一步一步来TDD开发之利其器(2-1)

很俗的一个开头——“工欲善其事,必先利其器”,上一篇介绍了TDD的一些好处和实现它的基本方法,今天就主要来说下,在微软.Net 阵营中TDD开发需要的一些常用工具。

首先介绍的是很普及的NUnit.

仍然是What Why How

NUnit是什么?

NUnit 是一个支持.net 语言的单元测试框架,他来自于著名的JUnit。NUnit 支持包括property,Custom attribute等.net 有,而java没有的特性(在我印象中05年java没有,不知道现在有没)。NUnit 是个免费开源的产品,你可以去官方网站down下他的源代码做分析,当然,如果你有结余的Money,你也可以考虑Donate 支持下。

为嘛要使用NUnit?

NUnit 是一个非常轻的测试框架,更有意思的是,它幽默的支持自测试(也就是可以测试自己)。之后NUnit 测试的时候还有一个好处:不依赖于Visual studio ,用NUnit 进行测试,非常快。

当然也要有对比,Visual Studio 也有自带的单元测试,而且做的还是相当不错的,更可以结合它自身的项目工程管理,生成很漂亮的报表,然而,它也有一些缺点:比较重,需要依赖VS,运行一个测试消耗的时间比NUnit 要多一些。当然还有一个重要的缺点,贵~当然在和谐的天朝,这个缺点可以忽略不计。

怎样用NUnit?

其实NUnit 很轻,用起来非常容易。

只需要在项目中引用一下NUnit 框架就ok

image

这样就搞定了。

(不知道为什么,wordpress在插入code 的情况下显示的读取的很慢,为保证default页面速度,只好然您点击更多来查看代码了)

Read the rest of this entry »

Tags: , ,

一步一步来TDD开发之概要(1)

啥是TDD?

其实很简单,Test Driven Development,测试驱动开发。简单的说就是“代码未动,测试先行”:在开发的最初期就写好测试,之后以通过代码测试为目的,不断的进行代码编写以及重构,最终通过所有测试,完成代码编写的一种开发方式。这种开发方式用于敏捷开发,或者也可以说是敏捷的精髓。

为何要TDD?

TDD的好处有一些,以下是我自己觉得TDD的一些优势:

1、目标非常明确:通过测试用例。

可能有些朋友觉得,平时需求也是一个明确的目标啊?我的想法是,需求每次有很多,随着自己不断的coding,有些小需求就会被忽略,有的需求像是实现了,又像是没实现,很难有个标准的判断,而TDD明确了你的任务:通过测试

2、防止过度设计

平时做项目的时候,有时候做着某个点,之后不知不觉的就把功能写的过于复杂而不必要,通过TDD,你只需要去实现测试就ok了,不需要考虑那么多因素

3、展示效果方便,工作有成就感

在通过测试之后,你就可以展示自己的工作成果了,每次通过test那个绿灯,无疑对鼓舞士气起着显著的作用。

4、自动化测试

虽然自动化测试不是TDD的主要特点,但是无疑自动化测试是一个很爽的事情:不再需要你从UI层自己一点一点的进入某个地方,之后加上断点,从堆栈中抓出某个变量。用“鼠标点着”的测试方法依赖人工,每次测试都需要你集中精力,小心翼翼。而自动化测试,只需要在代码中加入几个断言,编译一下,之后通过测试工具测试,什么地方通过什么地方没通过,立马一目了然。

怎样TDD

这是我从wikipedia 下弄下来的一张图,它很好的描述了TDD的整个流程,之后下面的文字翻译自wikipedia对tdd的描述

image

1、编写测试用例

在测试驱动开发中,在写每一个特性之前,首先都需要编写一个测试(这个测试在最开始肯定会失败,因为你还没实现这个特性,当你测试到通过测试之后,说明“新”特性已经被实现了)在写测试的时候,你需要对需实现的特性有着清晰的认识,了解它的规格和需求。 你可以通过用例图或者假设场景(User Stories) 去获得特性的需求和“非正常情况”(Exception Condition)的处理。当然你也可以去把以前的测试做一些修改或者扩充来满足新的“特性要求”。这是TDD区别于你写好代码后做单元测试的特性:这样做可以让你在编写代码之前,紧盯着需求,这是个微妙的,但是很重要的不同点。

2、运行所有的测试,之后看最新的那个测试报错了没

这个是用来验证 测试工具是否工作正常,新的测试在没有写任何新的代码之前,是不会通过测试的。这实际上也同时检测了 “测试”自身的代码,举个反例:如果说碰到了这种事情–>新的测试仪被通过了,则那个测试就相当于没用。

新测试必须失败的原因还有一些期望的原因:会提高信心(虽然并不是每个人都会),因为咱们测试了需要测试的东西,并且除非我们实现了这个期望的用例,咱才能通过测试。

3、写代码实现

这个步骤是编写代码来通过测试。写的这些代码暂时也许不需要非常完美,咱们可以用一个很囧的代码去实现一个测试。为啥这么说,因为我们待会将会重构它的。

只为了让代码通过测试来写,是相当重要的一个原则。不要画蛇添足的写上你预想出的其他功能,你的目的就是单纯的通过测试。

4、运行自动化测试看看是否都通过了测试

如果说所有的测试都通过了,咱就可以确认代码已经满足了所有测试过的需求了。这是个在整个开发迭代中的不错的最终结果的开始。

5、重构代码

这个时候,代码可以好好的清理下了。通过重新运行测试用例,我们可以确认重构没有影响到任何已经实现的功能。

消除“复制代码”是任何软件设计的一个重要的概念,同事在这里,它也是删除删除测试代码和产品最终代码的一个概念。比如说一些“神奇数字”(某个已有初始值,但没注明具体含义的数字)“神奇字段”。

迭代

当你折腾完之后,你就可以写新的一个测试了,这种循环会推动功能的完备。每个步骤应该保证“很小”,只需要很少的步骤(1-10次编辑)对于每个测试。如果新的新的代码不能迅速的通过一个测试,或者其他的测试莫名其妙的错了,咱就应该undo 或者恢复到过度调试(revert in preference to excessive debugging.)持续集成有助于提供可回复的测试点。When using external libraries it is important not to make increments that are so small as to be effectively merely testing the library itself,[3] unless there is some reason to believe that the library is buggy or is not sufficiently feature-complete to serve all the needs of the main program being written.(这句话我没看明白,但不太影响理解整个流程)

ok,就到这里了,下篇文章将介绍做TDD需要的几个工具。

Tags: , ,