IntelliTest(4) – Hands on[译]

  在我们写传统单元测试时,为了达到一定的覆盖率,开发者需要反复的做一些类似的工作,比如,写测试用例,查看哪些代码未被覆盖,继续写测试用例覆盖之,直到所有的代码都被覆盖。

  有了IntelliTest后,这一切都变得不一样了。我们会手把手的介绍IntelliTest技术,为了便于大家理解,会使用一个demo项目

一、准备demo项目

  按照上面给出的GitHub地址,克隆项目后,打开PokerLeagueManager.sln。这个demo主要用于跟踪统计每周的扑克牌联赛数据,每个玩家的游戏记录(玩过的游戏、总胜利次数、总筹码等)都会记录在一张表里。我们想要测试的方法在PokerLeagueManager.Queries.Core\EventHandlers\GetPlayerStatisticsHandler.cs\Handle
(GameDeletedEvent)里,代码片段如下:


image.png

这个方法做的事情是在一次游戏结束后更新相关玩家的数据。详细步骤如下:

  1. 获取在这次游戏的相关玩家
  2. 遍历这些玩家,并获取它们当前的统计数据
  3. 更新玩家数据
  4. 保存数据

正如我们在平时的开发,这个方法需要和其他对象交互。我们的目标就是让IntelliTest生成100%覆盖率的用例。

二、运行IntelliTest并理解它的警告

  我们可以看到,只生成了两个用例,而且覆盖率极低(6/42blocks),还有5个警告。


image.png

点击警告按钮切换到警告界面。


image.png

第一个分类是“运行时警告”,将使用“PokerLeagueManager.Queries.Core.QueryDataStore
[PQCQ]” 作为接口“IQueryDataStore”的实例。通过查看代码,我们发现“IQueryDataStore”在基类BaseHandler中以属性的形式定义。为了测试Handle方法,我们必须要有一个IQueryDataStore的实例,这里,IntelliTest通过探测为我们推荐了PQCQ。

那么,PQCQ真的是我们需要的类型吗?

  与此同时,IntelliTest探测到需要有一个公开的方法来初始化PQCQ,因为我们在测试Handle方法时需要用到PQCQ的实例,所以,在第二个警告分类“对象创建”的第一个警告就告诉我们它将会自动生成的对象构造API(一个工厂方法),如果愿意,我们可以保存这个工厂方法供测试方法调用。


image.png

当IntelliTest按照自己的方式真实的去构造PQCQ时,它发现它无法构造,并给出了原因。这便是“对象创建”分类中的第二个警告。


image.png

第三个分类叫做“无法探测的代码”,只有一个警告,从旁边的堆栈中我们可以看到,是DbContext的构造函数中的一些代码无法探测(如何探测?)。无法探测代码,有两个可能的原因:

  1. 引擎无法探测那部分代码
  2. 探测那部分代码会导致系统运行缓慢

  有时候,IntelliTest探测分支需要运行非常多次的代码,甚至超过了系统为了保证性能设置的阈值。因此,它发出警告,并停止探测。

三、提供伪对象

  在继续之前,我们需要回答一开始那个问题:

  PQCQ真的是我们需要的类型吗?

  显然它不是,为了测试Handle方法,我们需要一个IQueryDataStore的伪对象,在解决方案中,我们可以找到一个叫FakeQueryDataStore的类,这就是我们需要的伪对象。

  为了完成IntelliTest,我们需要完善PUT方法。

  点击警告按钮切换到测试窗口,全选用例并保存,然后删除掉.g.cs文件(这里面的用例并不符合我们的要求,它无法覆盖全部的代码)。剩下的GetPlayerStatisticsHandleTest.cs就是PUT方法的文件。

  在测试项目中添加PokerLeagueManager.Common.Tests的引用,并且按照下面图片的红色指示完善代码。


image.png

  再次运行IntelliTest(点击探测窗口中的运行,或在PUT方法上运行IntelliTest)

  这次探索越界的警告就没了,我们可以看到有2个用例,4个警告。


image.png

  查看警告我们发现,IntelliTest告诉我们它能够初始化PokerLeagueManager.Common.Tests.
FakeQueryDataStore[PCTF],以及我们可以使用的API。
当它使用这个API去初始化[PCTF]时,再次提示有无法探测的代码。在堆栈查看窗口中,我们可以跟踪到,无法探测的代码在GetData<T> 方法中。因为我们不是要测试这个伪对象,所以可以忽略这个异常。

  选择“对象创建”类别,忽略里面的全部异常。

  我们继续观察可以发现,在无法探测代码中,都是关于[PCTF]的,我们可以全部忽略。

  我们可以在PexAssemblyInfo.cs中看到,增加了两行。


image.png

  再次运行IntelliTest。

  依然是两个用例,但是警告都没了。

  通过分析Handle方法,我们知道,GetData必须返回一些数据我们才能覆盖余下的代码。(目前只覆盖了15/42 blocks)。

四、配置PUT

  在PUT中,“target”是我们要测试的类对象。分析代码发现,GetData<T>方法中的T,需要是LookupGamePlayersDto和GetPlayerStatisticsDto类型,我们需要用数据填充PCTF的实例,这里,我们可以通过PUT配置,让IntelliTest为我们生成这些数据。我们需要在PUT的签名中,添加需要IntelliTest帮忙生成的数据。我们需要两个LookupGamePlayersDto实例和一个LookupGamePlayersDto实例。同时,我们要将统计数据和第一个玩家关联起来。

继续添加引用PokerLeagueManager.Common.DTO,同时按照下面红色指示添加代码:


image.png

接下来,我们需要填充target的数据:


image.png

执行被测方法:


image.png

最后,我们只需要简单的查询统计数据并对数据的字段下断言:


image.png

因为我们改变了PUT,所以可以删除g.cs文件。

五、100%覆盖

  再次运行IntelliTest。这次我们可以看到所有的代码都被覆盖了(52/52 blocks),并且有7个用例,3个通过,4个失败。还有7个警告。


image.png

分析警告可以知道,所有的警告都跟我们要测试的Handle方法无关,果断忽略之。


image.png

忽略后,可以看到,在PexAssemblyInfo.cs中增加了如下内容:


image.png

再次运行IntelliTest。这次我们可以看到代码全被覆盖,7个用例通过3个,并且没有警告。


image.png

其中两个未通过是对参数e未作判空处理,一个是除数出现0的情况(当Statistics.GamesPlayed=1时),还有一个是堆栈溢出,通过跟踪代码我们可以知道详细的用例。

  至此,IntelliTest已经生成了所有用例,并发现了代码中的问题。如果我们增加更多的断言,会生成更多用例验证正确性。

强烈建议阅读英文原文



2017-10-20 11:43:52

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342