详解测试驱动开发 Test Driven Development(TDD)

2023-05-16

 

{TDD的目标}

Clean Code That Works

这句话的含义是,事实上只做两件事情:让代码奏效(Work)和让代码洁净(Clean),前者是把事情做对,后者是把事情做好。

 

想试用TDD的人们,请遵循下面的步骤:

编写TestCase--<实现TestCase--<重构
(确定范围和目标) (增加功能) (提升设计)

{TDD的优点}

『充满吸引力的优点』:

完工时完工;
全面正确的认识代码和利用代码;
为利用你成果的人提供Sample;
开发小组间降低了交流成本,提高了相互信赖程度; 
避免了过渡设计;
系统可以与详尽的测试集一起发布,从而对程序的将来版本的修改和扩展提供方便;

『不显而易见的优点』

逃避了设计角色;
降低了理解代码所花费的成本;

『有争议的优点』

提高了开发效率

 

{TDD的步骤}

步骤制品
(1)快速新增一个测试用例新的TestCase
(2)编译所有代码,刚刚写的那个测试很可能编译不通过原始的TODO List
(3)做尽可能少的改动,让编译通过Interface
(4)运行所有的测试,发现最新的测试不能编译通过-(Red Bar)
(5)做尽可能少的改动,让测试通过Implementation
(6)运行所有的测试,保证每个都能通过-(Green Bar)
(7)重构代码,以消除重复设计Clean Code That Works

 

{FAQ}

[什么时候重构?]

重构不是一种构建软件的工具,不是一种设计软件的模式,也不是一个软件开发过程中的环节,正确理解重构的人应该把重构看成一种书写代码的方式,或习惯,重构时时刻刻有可能发生。在TDD中,除去编写测试用例和实现测试用例之外的所有工作都是重构,所以,没有重构任何设计都不能实现。

实现测试用例时重构代码,完成某个特性时重构设计,产品的重构完成后还要记得重构一下测试用例。

 

[什么时候设计?]

设计的时机应该由开发者自己把握,不要受到TDD方式的限制,但是,不需要事先确定的事一定不能事先确定,免得捆住了自己的手脚。

 

[什么时候增加新的TestCase?]
没事做的时候。通常我们认为,如果你要增加一个新的功能,那么先写一个不能通过的 TestCase;如果你发现了一个bug,那么先写一个不能通过的TestCase;如果你现在什么都没有,从0开始,请先写一个不能通过的 TestCase。所有的工作都是从一个TestCase开始。

 

[TestCase该怎么写?]
测试用例的编写实际上就是两个过程:使用尚不存在的代码和定义这些代码的执行结果。所以一个 TestCase也就应该包括两个部分--场景和断言。 

这个世界上最难的事情也不在于如何解决问题,而在于ask the right question!

 

[TDD能帮助我消除Bug吗?]
答:不能!千万不要把"测试"和"除虫"混为一谈!"除虫"是指程序员通过自己的努力来减少bug的数量(消除bug这样的字眼我们还是不要讲为好^_^),而"测试"是指程序员书写产品以外的一段代码来确保产品能有效工作

 

[我该为一个Feature编写TestCase还是为一个类编写TestCase?]

我们的研究结果表明,通常在一个特性的开发开始时,我们针对特性编写测试用例,如果您发现这个特性无法用TestCase表达,那么请将这个特性细分,直至您可以为手上的特性写出TestCase为止。从这里开始是最安全的,它不会导致任何设计上重大的失误。但是,随着您不断的重构代码,不断的重构 TestCase,不断的依据TDD的思想做下去,最后当产品伴随测试用例集一起发布的时候,您就会不经意的发现经过重构以后的测试用例很可能是和产品中的类/方法一一对应的。

 

[什么时候应该将全部测试都运行一遍?]
Good Question!大师们要求我们每次重构之后都要完整的运行一遍测试用例。这个要求可以理解,因为重构很可能会改变整个代码的结构或设计,从而导致不可预见的后果,但是如果我正在开发的是一个ERP怎么办?运行一遍完整的测试用例可能将花费数个小时,况且现在很多重构都是由工具做到的,这个要求的可行性和前提条件都有所动摇。所以我认为原则上你可以挑几个你觉得可能受到本次重构影响的TestCase去run,但是如果运行整个测试包只要花费数秒的时间,那么不介意你按大师的要求去做。

 

[什么时候改进一个TestCase?]
增加的测试用例或重构以后的代码导致了原来的TestCase的失去了效果,变得无意义,甚至可能导致错误的结果,这时是改进TestCase的最好时机。但是有时你会发现,这样做仅仅导致了原来的TestCase在设计上是臃肿的,或者是冗余的,这都不要紧,只要它没有失效,你仍然不用去改进它。记住,TestCase不是你的产品,它不要好看,也不要怎么太科学,甚至没有性能要求,它只要能完成它的使命就可以了--这也证明了我们后面所说的"用Ctrl-C/Ctrl-V编写测试用例"的可行性。

 

[为什么原来通过的测试用例现在不能通过了?]
这是一个警报,Red Alert!它可能表达了两层意思--都不是什么好意思--1)你刚刚进行的重构可能失败了,或存在一些错误未被发现,至少重构的结果和原来的代码不等价了。2)你刚刚增加的TestCase所表达的意思跟前面已经有的TestCase相冲突,也就是说,新增的功能违背了已有的设计,这种情况大部分可能是之前的设计错了。

 

[我怎么知道那里该有一个方法还是该有一个类?]
这个问题也是常常出现在我的脑海中,无论你是第一次接触TDD或者已经成为 TDD专家,这个问题都会缠绕着你不放。不过问题的答案可以参考前面的"什么时候设计"一节,答案不是唯一的。其实多数时候你不必考虑未来,今天只做今天的事,只要有重构工具,从方法到类和从类到方法都很容易。

 

[我要写一个TestCase,可是不知道从哪里开始?]
从最重要的事开始,what matters most?从脚下开始,从手头上的工作开始,从眼前的事开始。从一个没有UI的核心特性开始,从算法开始,或者从最有可能耽误时间的模块开始,从一个最严重的bug开始。

 

[为什么我的测试总是看起来有点愚蠢?]

不必担心这一点,事实上,大师们给的例子也相当愚蠢,比如一个极端的例子是要写一个两个int变量相加的方法,大师先断言2+3=5,再断言5+5=10,难道这些代码不是很愚蠢吗?其实这只是一个极端的例子,当你初次接触TDD时,写这样的代码没什么不好,以后当你熟练时就会发现这样写没必要了,要记住,要记住,谦虚是通往TDD的必经之路!从经典开发方法转向TDD就像从面向过程转向面向对象一样困难,你可能什么都懂,但你写出来的类没有一个纯OO的!

 

[什么场合不适用TDD?]
问的好,确实有很多场合不适合使用TDD。比如对软件质量要求极高的军事或科研产品--神州六号,人命关天的软件--医疗设备,等等,再比如设计很重要必须提前做好的软件,这些都不适合TDD,但是不适合TDD不代表不能写TestCase,只是作用不同,地位不同罢了。

 

{Best Practise}

[微笑面对编译错误]

通常,编译错误都集中在下面三个方面:
(1)你的代码存在低级错误
(2)由于某些Interface的实现尚不存在,所以被测试代码无法编译
(3)由于某些代码尚不存在,所以测试代码无法编译

请注意第二点与第三点完全不同,前者表明设计已存在,而实现不存在导致的编译错误;后者则指仅有TestCase而其它什么都没有的情况,设计和实现都不存在,没有Interface也没有Implementation。

另外,编译器还有一个优点,那就是以最敏捷的身手告诉你,你的代码中有那些错误。

 

[重视你的计划清单]

在非TDD的情况下,尤其是传统的瀑布模型的情况下,程序员不会不知道该做什么,事实上,总是有设计或者别的什么制品在引导程序员开发。但是在TDD的情况下,这种优势没有了,所以一个计划清单对你来说十分重要,因为你必须自己发现该做什么。

 

[废黜每日代码质量检查]
如果我没有记错的话,PSP对于个人代码检查的要求是蛮严格的,而同样是在针对个人的问题上, TDD却建议你废黜每日代码质量检查,别起疑心,因为你总是在做TestCase要求你做的事情,并且总是有办法(自动的)检查代码有没有做到这些事情 --红灯停绿灯行,所以每日代码检查的时间可能被节省,对于一个严格的PSP实践者来说,这个成本还是很可观的!

 

[如果无法完成一个大的测试,就从最小的开始]
如果我无法开始怎么办,教科书上有个很好的例子:我要写一个电影列表的类,我不知道如何下手,如何写测试用例,不要紧,首先想象静态的结果,如果我的电影列表刚刚建立呢,那么它应该是空的,OK,就写这个断言吧,断言一个刚刚初始化的电影列表是空的。

 

[尝试编写自己的xUnit]
Kent Beck建议大家每当接触一个新的语言或开发平台的时候,就自己写这个语言或平台的xUnit,其实几乎所有常用的语言和平台都已经有了自己的 xUnit,而且都是大同小异,但是为什么大师给出了这样的建议呢。其实Kent Beck的意思是说通过这样的方式你可以很快的了解这个语言或平台的特性,而且xUnit确实很简单,只要知道原理很快就能写出来。

 

[善于使用Ctrl-C/Ctrl-V来编写TestCase]
不必担心TestCase会有代码冗余的问题,让它冗余好了。

 

[永远都是功能First,改进可以稍后进行]
上面这个标题还可以改成另外一句话:避免过渡设计!

 

[淘汰陈旧的用例]
舍不得孩子套不着狼。不要可惜陈旧的用例,因为它们可能从概念上已经是错误的了,或仅仅会得出错误的结果,或者在某次重构之后失去了意义。当然也不一定非要删除它们,从TestSuite中除去(JUnit)或加上Ignored(NUnit)标签也是一个好办法。

 

[用TestCase做试验]
如果你在开始某个特性或产品的开发之前对某个领域不太熟悉或一无所知,或者对自己在该领域里的能力一无所知,那么你一定会选择做试验,在有单元测试作工具的情况下,建议你用TestCase做试验,这看起来就像你在写一个验证功能是否实现的 TestCase一样,而事实上也一样,只不过你所验证的不是代码本身,而是这些代码所依赖的环境。

 

[TestCase之间应该尽量独立]
保证单独运行一个TestCase是有意义的。

 

[不仅测试必须要通过的代码,还要测试必须不能通过的代码]
这是一个小技巧,也是不同于设计思路的东西。像越界的值或者乱码,或者类型不符的变量,这些输入都可能会导致某个异常的抛出,或者导致一个标示"illegal parameters"的返回值,这两种情况你都应该测试。

 

[编写代码的第一步,是在TestCase中用Ctrl-C]
这是一个高级技巧,呃,是的,我是这个意思,我不是说这个技巧难以掌握,而是说这个技巧当且仅当你已经是一个TDD高手时,你才能体会到它的魅力。多次使用TDD的人都有这样的体会,既然我的TestCase已经写的很好了,很能说明问题,为什么我的代码不能从TestCase拷贝一些东西来呢。

 

[测试用例包应该尽量设计成可以自动运行的]
如果产品是需要交付源代码的,那我们应该允许用户对代码进行修改或扩充后在自己的环境下run整个测试用例包。既然通常情况下的产品是可以自动运行的,那为什么同样作为交付用户的制品,测试用例包就不是自动运行的呢?即使产品不需要交付源代码,测试用例包也应该设计成可以自动运行的,这为测试部门或下一版本的开发人员提供了极大的便利。

 

[只亮一盏红灯]
大师的建议,前面已经提到了,仅仅是建议。

 

[用TestCase描述你发现的bug]

用TestCase描述bug的另一个好处是,不会因为以后的修改而再次暴露这个bug,它已经成为你发布每一个版本之前所必须检查的内容了。

 

{关于单元测试}

单元测试的目标是

Keep the bar green to keep the code clean

这句话的含义是,事实上我们只做两件事情:让代码奏效(Keep the bar green)和让代码洁净(Keep the code clean),前者是把事情做对,后者是把事情做好,两者既是TDD中的两顶帽子,又是xUnit架构中的因果关系。

单元测试作为软件测试的一个类别,并非是xUnit架构创造的,而是很早就有了。但是xUnit架构使得单元测试变得直接、简单、高效和规范,这也是单元测试最近几年飞速发展成为衡量一个开发工具和环境的主要指标之一的原因。

 

多数语言和平台的xUnit架构都是大同小异,有的仅是语言不同,其中最有代表性的是JUnit和NUnit,后者是前者的创新和扩展。一个单元测试框架xUnit应该:1)使每个TestCase独立运行;2)使每个TestCase可以独立检测和报告错误;3)易于在每次运行之前选择TestCase。

 

下面是枚举出的xUnit框架的概念,这些概念构成了当前业界单元测试理论和工具的核心:

[测试方法/TestMethod]
测试的最小单位,直接表示为代码。

[测试用例/TestCase]
由多个测试方法组成,是一个完整的对象,是很多TestRunner执行的最小单位。

[测试容器/TestSuite]
由多个测试用例构成,意在把相同含义的测试用例手动安排在一起,TestSuite可以呈树状结构因而便于管理。在实现时,TestSuite形式上往往也是一个TestCase或TestFixture。

[断言/Assertion]
断言一般有三类,分别是比较断言(如assertEquals),条件断言(如isTrue),和断言工具(如fail)。

[测试设备/TestFixture]
为每个测试用例安排一个SetUp方法和一个TearDown方法,前者用于在执行该测试用例或该用例中的每个测试方法前调用以初始化某些内容,后者在执行该测试用例或该用例中的每个方法之后调用,通常用来消除测试对系统所做的修改。

[期望异常/Expected Exception]
期望该测试方法抛出某种指定的异常,作为一个"断言"内容,同时也防止因为合情合理的异常而意外的终止了测试过程。

[种类/Category]
为测试用例分类,实际使用时一般有TestSuite就不再使用Category,有Category就不再使用TestSuite。

[忽略/Ignored]
设定该测试用例或测试方法被忽略,也就是不执行的意思。有些被抛弃的TestCase不愿删除,可以定为Ignored。

[测试执行器/TestRunner]
执行测试的工具,表示以何种方式执行测试,别误会,这可不是在代码中规定的,完全是与测试内容无关的行为。比如文本方式,AWT方式,swing方式,或者Eclipse的一个视图等等。

 

{实例:Fibonacci数列}

下面的Sample展示TDDer是如何编写一个旨在产生Fibonacci数列的方法。
(1)首先写一个TC,断言fib(1) = 1;fib(2) = 1;这表示该数列的第一个元素和第二个元素都是1。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
}

(2)上面这段代码不能编译通过,Great!--是的,我是说Great!当然,如果你正在用的是Eclipse那你不需要编译,Eclipse 会告诉你不存在fib方法,单击mark会问你要不要新建一个fib方法,Oh,当然!为了让上面那个TC能通过,我们这样写:

public int fib( int n ) {
return 1;
}

(3)现在那个TC亮了绿灯,wow!应该庆祝一下了。接下来要增加TC的难度了,测第三个元素。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(
2, fib(3));
}

不过这样写还不太好看,不如这样写:

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
}

(4)新增加的断言导致了红灯,为了扭转这一局势我们这样修改fib方法,其中部分代码是从上面的代码中Ctrl-C/Ctrl-V来的:

public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
return 1;
}

(5)天哪,这真是个贱人写的代码!是啊,不是吗?因为TC就是产品的蓝本,产品只要恰好满足TC就ok。所以事情发展到这个地步不是fib方法的错,而是TC的错,于是TC还要进一步要求:

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
assertEquals(fib(
2)+fib(3), fib(4));
}

(6)上有政策下有对策。

public int fib( int n ) {
if ( n == 3 ) return fib(1)+fib(2);
if ( n == 4 ) return fib(2)+fib(3);
return 1;
}

(7)好了,不玩了。现在已经不是贱不贱的问题了,现在的问题是代码出现了冗余,所以我们要做的是--重构:

public int fib( int n ) {
if ( n == 1 || n == 2 ) return 1;
else return fib( n - 1 ) + fib( n - 2 );
}

(8)好,现在你已经fib方法已经写完了吗?错了,一个危险的错误,你忘了错误的输入了。我们令0表示Fibonacci中没有这一项。

public void testFab() {
assertEquals(
1, fib(1));
assertEquals(
1, fib(2));
assertEquals(fib(
1)+fib(2), fib(3));
assertEquals(fib(
2)+fib(3), fib(4));
assertEquals(
0, fib(0));
assertEquals(
0, fib(-1));
}

then change the method fib to make the bar grean:

public int fib( int n ) {
if ( n >= 0 ) return 0;
if ( n == 1 || n == 2 ) return 1;
else return fib( n - 1 ) + fib( n - 2 );
}

(9)下班前最后一件事情,把TC也重构一下:

public void testFab() {
int cases[][] = {
{
00}, {-10}, //the wrong parameters
{11}, {21}}; //the first 2 elements

for (int i = 0; i > cases.length; i++)
assertEquals( cases[i][
1], fib(cases[i][0]) );

//the rest elements
for (int i = 3; i > 20; i++)
assertEquals(fib(i
-1)+fib(i-2), fib(i));
}

(10)打完收工。

 

测试驱动开发全功略(精)

测试驱动开发优缺点

——————————————————————————————————————————————

优势:

1. 有助于设计简单清晰而易用的接口。因为总是先有测试代码,才编写实现代码,意味着总是从使用者的角度设计接口,只有简单易用的接口才方便测试时调用,所以我几乎是“被迫”去努力设计简单易用的接口,因为我就是第一个使用者。

2. 模块切分的足够小但是模块间保持极低的耦合度。为了方便测试,我总是尽力把重复的逻辑剥离出来,单独构建模块进行测试;并且尽量减少模块间的耦合,保持模 块相对独立和功能完备。如果模块过大,或者模块间强耦合,写测试用例与代码时就会困难重重,笨重复杂。因为总是先写测试代码,眼前的利益高于一切,将来的 实现代码必然要迁就目前测试的需要。于是,我又“不知不觉”设计出小粒度模块,且模块间耦合度低的实现。

3. 肆无忌惮的重构。因为有测试用例和测试代码作担保,我终于能够从小心翼翼心惊胆战的重构中解脱出来,只要是更好的实现和设计,我都愿意尝试,管它呢,反正 多跑几遍测试就知道重构的结果如何了。可以说,测试驱动开发鼓励代码的不断进化,即使测试已经全部通过,也可以通过大胆重构来改进设计与实现。尽管此时是 否还需要再重构见仁见智,至少提供了一个可能,我是很喜欢这一点。

4. 测试代码是“活”的软件文档,它硬性规定了实现代码必须满足的需求,达不到就报错。传统的文本文档比之就苍白无力多了,“应该”,“必须”,这些字眼对程 序员有多少约束力?而且测试代码总是能与实现代码保持新鲜同步,传统文档写完后经常被上传服务器束之高阁,很少人问津,随着开发组内人员的变动,往往最后 就湮没在服务器的故纸堆之中了。

 

 

缺陷:

1. 测试驱动开发不可能让人立即具有设计出优美解决方案的能力,或者说是优秀的分析与解决问题的能力。TDD不是Test Driven Design。它只是一个过程,也许可以帮助你发现并帮助你实现优美的解决方案,但是它不能变魔术一样,只要学会了就变出一个优美的设计出来,优秀的分析 问题与解决问题的能力还是要靠不断地学习与借鉴他人成就才能得到提高。


2. 测试驱动开发不能节省开发投入,也很少能够节省开发周期。测试开发所编写的大量测试代码都是要投入时间与精力的,我现在的代码统计显示,测试代码与实现代 码的比例基本在3:2,即使因为测试驱动开发能得到一个简洁的设计,也不能弥补测试代码的工作量。当然,测试代码可以一定程度保证高质量的实现代码,从而 减少后期软件测试与修正缺陷的工作周期,并进一步在软件发布后减少代码修正维护的工作量。但至少在开发阶段,两相抵消,开发周期并不能有明显改善,如果是 第一次采纳测试驱动开发,甚至会延长开发周期。


3. 测试驱动开发不能杜绝所有的软件缺陷。尽管测试驱动开发通过测试约束,减少了程序员犯错和遗忘的可能,但是这只是把问题从实现代码部分地转移到了测试代 码。测试用例的完备与否,测试代码本身逻辑的正确与否都依赖于程序员,糟糕的测试用例设计和测试代码实现可能自顾不暇,也就失去了监督实现代码的能力。我 就见过有程序员在测试代码中读取实现代码生成的数据,再直接拿之来验证实现代码生成的数据,x必然恒等于x,这样的测试逻辑必然成功,但是毫无意义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解测试驱动开发 Test Driven Development(TDD) 的相关文章

  • Rhino Mocks 部分模拟

    我正在尝试测试一些现有类的逻辑 目前不可能重构这些类 因为它们非常复杂并且正在生产中 我想做的是创建一个模拟对象并测试一个在内部调用另一个很难模拟的方法的方法 所以我只想为辅助方法调用设置一个行为 但是当我设置该方法的行为时 该方法的代码被
  • DUnit:如何运行测试?

    我怎么跑TestCase来自 IDE 我创建了一个新项目 具有单一 简单的形式 unit Unit1 interface uses Windows Messages SysUtils Classes Graphics Controls Fo
  • Dapper:单元测试 SQL 查询

    我从 Dapper 微型 ORM 开始 我使用 Dapper Rainbow 我想测试查询和它们检索的数据 我的意思是 例如 我有用户服务用方法GetAll 并且我想测试 sql 查询是否从某个列表中检索所有用户 不是从数据库中检索 因为我
  • 测试替身有哪些不同类型及其用途?

    我正在学习有关测试驱动开发的在线课程 并遇到了测试替身的概念 根据课程中测试替身的定义 测试双打 测试替身是在单元测试中用于替代实际生产系统协作者的对象 我知道测试双打是什么意思了 但后来有人提到 测试替身有多种类型 课程中提到的内容是 D
  • TDD:帮助编写可测试类

    我有一个快速的小应用程序 想尝试使用 TDD 进行开发 我从未使用过 TDD 实际上甚至不知道它是什么 直到我发现 ASP NET MVC 我的第一个 MVC 应用程序有单元测试 但它们很脆弱 耦合性强 需要太多维护 并且被放弃了 我是来学
  • Nock 在 Redux 测试中没有拦截 API 调用

    我正在尝试在 redux 应用程序中测试 api 调用 该代码几乎遵循中概述的模式异步动作创建者redux 文档的部分 http redux js org docs recipes WritingTests html http redux
  • PHP 中的测试驱动开发

    我是一名使用 PHP 工作的 Web 开发人员 我在 C 桌面应用程序中使用测试驱动开发的经验有限 在这种情况下 我们使用 nUnit 作为单元测试框架 我想在新项目中开始使用 TDD 但我真的不知道从哪里开始 对于基于 PHP 的单元测试
  • 测试 Django 信号的正确方法

    我正在尝试测试发送的信号 它正在提供 args 内部触发信号contact question create提交表单后立即查看 我的测试用例是这样的 def test form should post proper data via sign
  • 在代码中与在脚本中生成集成测试数据[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 这个问题很可能是基于意见的 但我确信 有确凿论据支持的观点将为明智的决策铺平道路 我确实喜欢使用 Autofixture 生成数据库状态 我真诚
  • VB6 有什么好的 TDD 工具或资源吗?

    是的 我知道我已经落后于时代了 但是我这里有一个古老的 VB6 编辑器应用程序 我相信没有人会很快升级到 NET 它使用了几个第三方 DLL 工具 并且由于它仍然使用旧的 RichEdit 控件 我基本上可以仅用这个工具来创建我自己的 Bu
  • 优秀软件设计和实现的示例[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我希望这不是重复的 您遇到过的设计和实施最扎实的软件系统 框架 应用程序是什么 似乎 TDD SOLI
  • RSpec:如何编写一个需要特定输出但不关心方法的测试?

    我正在尝试了解测试驱动设计 特别是 RSpec 但我在使用 RSpec 书中的一些示例时遇到了麻烦 在书中 我们测试 STDOUT 上的输出 如下所示 output double output game Game new output sh
  • TDD 新手:是否有带有测试的示例应用程序来展示如何进行 TDD?

    我真的很想进入 TDD 开发 但我不知道从哪里开始 我认为 查看代码并了解他们如何编写测试并使类可测试 这样我会更容易消化并开始使用自己 有谁知道任何示例或小型开源C 包含单元测试的应用程序 对于沙卡尔佩什来说 我会推荐 ObjectMen
  • 使用 Automapper 映射 ViewModel 后,我应该如何测试以及测试什么?

    我正在尝试测试Index控制器的动作 该动作使用自动映射器 http automapper org 映射域Customer视图模型的对象TestCustomerForm 虽然这有效 但我担心测试我从Index action 控制器的索引操作
  • YAGNI 在编写测试时也适用吗?

    当我编写代码时 我只编写我需要的函数 这种方法也适用于编写测试吗 为了安全起见 我应该提前为我能想到的每个用例编写测试 还是应该只为遇到的用例编写测试 我认为当你编写一个方法时 你应该测试预期的和潜在的错误路径 这并不意味着您应该扩展您的设
  • 忽略 ShouldBeEquivalentTo 中的内部属性

    在执行 ShouldBeEquivalentTo 时 有没有办法忽略类的内部属性 例如 在下面的类中 我想从对象图比较中排除 MetaData 属性 public class SomeObject Public string SomeStr
  • 将 TDD 与 Web 应用程序开发集成的最佳实践? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 单元测试和 ASP NET Web 应用程序在我的团队中是一个模棱两可的点 通常情况下 良好的测试实践会被忽视 Web 应用程序最终会在没有测试
  • 断言某个方法仅被调用一次

    我想断言一个方法只被调用一次 我正在使用 RhinoMocks 3 5 这是我认为可行的 Test public void just once var key id of something var source MockRepositor
  • 如何在meteor中建立单独的测试和开发数据库

    我已经为我的流星应用程序编写了一些测试 由于他们具有删除所有文档或填充新文档的设置和拆卸方法 因此我想在专用于测试的数据库上运行它们 我注意到数据库存储在 meteor local db 中 理想情况下 我希望从不同的端口访问 db tes
  • 学习 BDD、TDD(ruby、C#、javascript)的好资源

    学习 BDD 和 TDD ruby C javascript 有哪些好的资源 现在用什么好的框架 See 为什么我应该练习测试驱动开发以及应该如何开始 https stackoverflow com questions 4303 why s

随机推荐

  • 自动控制理论(2)——控制系统的数学模型(微分方程、传递函数)

    系列文章目录 自动控制理论 xff08 1 xff09 自动控制理论概述 自动控制理论 xff08 3 xff09 控制系统的数学模型 xff08 系统框图和信号流图 xff09 文章目录 系列文章目录一 线性系统的微分方程1 微分方程的建
  • Android 8.1共享系统代理中的热点(LineageOS15.1)

    https github com Mygod VPNHotspot 下载安装这个软件 xff0c 需要ROOT 开发者选项 xff1a 关闭WLAN硬件加速 该软件设置 xff1a 关闭IPV6 打开 修复DHCP 开启手机自带的热点 该软
  • 浏览器页面滚动条美化(样式)

    浏览器页面滚动条美化 xff08 样式 xff09 最近测试反应我们的产品在浏览器中当页面宽高出现溢出的情况下页面滚动条太丑了 xff01 让我们美化一下 xff01 然后花了一点时间专研了一下关于滚动条样式的相关知识 xff0c 今天就在
  • Android串口工具

    参考Android系统实现方式 xff0c 串口操作采用native实现 xff0c 比java层用文件流的方式更高效 xff0c 不需要延时和睡眠处理 xff0c 大量自测不会出现读取不到数据等问题 特点 xff1a 1 提供基本的串口操
  • 【VINS-Fusion入门之一】让系统跑起来

    文章目录 简介配置执行单目 43 IMU双目 43 IMU双目相机双目 43 GPS 落地备注 xff1a 简介 VINS xff0c 英文缩写Visual Inertial Systems 是一个实时视觉SLAM框架 xff0c 2017
  • 【VINS-Fusion入门之二】基于优化的多传感器融合

    文章目录 简介特征参考论文 解读系统框图相机模型 xff1a 配置文件全局优化闭环优化状态估计 简介 VINS Fusion is an optimization based multi sensor state estimator whi
  • RealSense T265使用教程

    RealSense ROS 安装 https github com IntelRealSense realsense ros 安装教程 https www intelrealsense com get started tracking ca
  • c++面试宝典

    目录 一 多线程 二 指针 三 字符串 四 面向对象 五 基本用法 六 c 43 43 11 七 算法 c 43 43 面试必考多线程 xff0c 内存 xff08 智能指针 xff09 xff0c 常见算法 xff0c 设计模式 一 多线
  • 音视频编解码之傅里叶变换和小波变换

    傅里叶变换的核心是从时域到频域的变换 xff0c 而这种变换是通过一组特殊的正交基来实现的 傅立叶变换使我们能通过频率成分来分析一个函数 任何信号 xff08 如图像信号 xff09 都可以表示成一系列正弦信号的叠加 傅立叶变换在实际中有非
  • CMakeLists.txt生成makefile

    本CMakeLists txt的project名称 会自动创建两个变量 xff0c PROJECT SOURCE DIR和PROJECT NAME PROJECT SOURCE DIR xff1a 本CMakeLists txt所在的文件夹
  • 编程之禅-程序员的哲学

    编程之道 xff0c 一个酷爱东方哲学和练太极拳的老外写的书 作者是一位资深的程序设计师 xff0c 从他的爱好和著作中 可以看得出作者的文化底蕴 而他现在从事的工作 xff0c 是如何把最好的管理技术和高科技企业联系起来 xff0c 而这
  • Pixhawk-开篇

    Pixhawk 开篇 互联网上关于介绍Pixhawk的文章特别多 有心人自己去网上查看吧 本篇文章未完 可能会有更新 不足请指出 QQ 4862879 说重点 Pixhawk指的是一款开源的硬件 下图的那个 是把原来的PX4FMU 43 P
  • Pixhawk_bootloader简介

    Pixhawk Bootloader引导过程简介 自己结合网络上的资源总结的内容 有不对的地方请及时指出 有侵权的请指出 QQ 4862879 Pixhawk硬件使用STM32的芯片 Cortex M3的内核有三种启动方式 xff0c 其分
  • 【ROS】移动机器人导航仿真(2)——SLAM(gmapping)

    在前一节中 xff0c 简单介绍了移动机器人的3D建模 xff0c 并在gazebo三维仿真环境中实现了简单的移动 这一节采用gmapping包实现机器人的SLAM xff08 同时定位与地图建立 xff09 使用上一节构建的机器人3D模型
  • Git 远程推送被拒绝的一种解决方案

    Git 远程推送被拒绝的一种解决方案 参考文章 xff1a xff08 1 xff09 Git 远程推送被拒绝的一种解决方案 xff08 2 xff09 https www cnblogs com wf skylark p 9315463
  • 关于putty连接服务器提示server unexpectedly closed connection解决方法

    关于putty连接服务器提示server unexpectedly closed connection解决方法 参考文章 xff1a xff08 1 xff09 关于putty连接服务器提示server unexpectedly close
  • centos7下部署主机监控,mysql指标监控,(prometheus+grafana+node_exporter+mysqld_exporter+alertmanager)

    先解释一下这些组件都是干什么用的 xff0c 组件说明prometheus server 是 Prometheus 组件中的核心部分 xff0c 负责实现对监控数据的获取 xff0c 存储以 及查询 exporter 简单说是采集端 xff
  • HTTP通讯安全中的Digest摘要认证释义与实现

    摘要 出于安全考虑 xff0c HTTP规范定义了几种认证方式以对访问者身份进行鉴权 xff0c 最常见的认证方式之一是Digest认证 Digest认证简介 HTTP通讯采用人类可阅读的文本格式进行数据通讯 xff0c 其内容非常容易被解
  • C/C++学习(2)关于strcpy、strcat函数使用

    strcpy strcat函数使用注意 题目来源 xff1a 点击打开链接 下列程序的打印结果是 char p1 15 61 34 abcd 34 p2 61 34 ABCD 34 str 50 61 34 xyz 34 strcpy st
  • 详解测试驱动开发 Test Driven Development(TDD)

    TDD的目标 Clean Code That Works 这句话的含义是 xff0c 事实上只做两件事情 xff1a 让代码奏效 xff08 Work xff09 和让代码洁净 xff08 Clean xff09 xff0c 前者是把事情做