• 1
  • 1
分享
  • VisualStudio中的单元测试
  • 北极 2020-10-13 17:27:15 字数 3268 阅读 2643 收藏 1

       1、VisualStuio中的测试资源管理器、CodeLens和ReSharper

       这篇文章实践使用VisualStudio 2019进行单元测试。在VisualStudio中通常都会使用“测试资源管理器”进行单元测试。

图1.png

       Professional和Enterprise版本可以使用CodeLens,这大大方便了测试的运行与调试。

图2.png

       但CodeLens的图标常常刷不出来,一些第三方插件(如ReSharper)会更好用。

       2、Live Unit Test

       VisualStudio可以使用Live Unit Test(实时单元测试),这个功能需要Enterprise版本。

图3.png

       Live Unit Testing 是 Visual Studio 2017 中引入的一种技术。 进行代码更改时,它会自动执行单元测试。

       实时单元测试:

  • 让你更有信心地对代码进行重构和更改。 Live Unit Testing 在编辑代码时自动执行所有受影响的测试,确保所做更改不会中断测试。

  • 指示单元测试是否充分覆盖代码,并显示未被单元测试覆盖的代码。 Live Unit Testing 以图形方式实时描绘代码覆盖率,以便一眼就能看到每行代码覆盖的测试数,目和未被任何单元测试覆盖的行。

       Live Unit Testing是个很好的功能,唯一的障碍是,如果解决方案中包含了集成测试会导致Live Unit Testing响应变慢。解决方案是创建一个不包含集成测试项目的解决方案,或者在解决方案资源管理器中右键单击想要排除的每个测试项目,然后依次选择“实时测试” > “排除”,这样Live Unit Test就不会对这些项目进行测试。

图4.png

       3、码覆盖率

       还是Enterprise版本的功能,Visual Studio的代码覆盖率工具可以很直观地查看到单元测试的代码覆盖率。

图5.png

       4、Microsoft Fakes

       微软有他自己的隔离框架Microsoft Fakes(在公司名称后面加Fakes,这命名真是超烂)。不过Fakes不怎么建议使用。

       Fakes有两种风格:

  • Stub(存根) 将类替换为可实现同一接口的小型替代项。

  • Shim(填充码) 在运行时修改应用的编译代码,这样就可以运行测试提供的垫片代码,而不用执行指定的方法调用。 填充码可用于替换对无法修改的程序集(如 .NET 程序集)的调用。

       一般原则是,为在 Visual Studio 解决方案中进行的调用使用存根,并为对其他引用的程序集的调用使用填充码。 这是因为在你自己的解决方案中,通过按照存根要求的方式定义接口来分离组件是一个很好的做法。 但是,外部程序集(如 System.dll)通常没有单独的接口定义,因此必须改用填充码。

  • 其他需要注意的事项还有:

  • 性能。 填充码运行较慢,因为它们在运行时会重新编写你的代码。 存根没有这项性能开销,与虚方法运行的速度一样快。

  • 静态方法和密封类型方法。 你只能使用存根实现接口。 因此,存根类型不能用于静态方法、非虚方法、密封虚方法、密封类型中的方法,等等。

  • 内部类型。 存根和填充码都可用于可通过程序集特性 InternalsVisibleToAttribute 访问的内部类型。

  • 私有方法。 如果方法签名中的所有类型都是可见的,则填充码可替换对私有方法的调用。 存根只能替换可见方法。

  • 接口和抽象方法。 存根提供了可用于测试的接口和抽象方法的实现。 填充码无法检测接口和抽象方法,因为它们没有方法体。

       但是由于不建议使用Fakes,所以基本上都会用NSub创建伪对象,Fakes的价值在于Shim,它有些别的隔离框架没有的独特功能。

       下面已LogAn项目为例讲解Fakes的用法。首先在单元测试的引用列表右键选中LogAn项目,选择“添加 Fakes 程序集”,然后重新生成方案,这时候可见到项目中多了LogAn.Fakes的引用,以及多了一些Fakes的文件。

图6.png

       使用Stub的单元测试代码如下:

CopyICalculator calculator = new Fakes.StubICalculator
{
    AddInt32Int32 = (arg1, arg2) => 3};
Assert.AreEqual(calculator.Add(1, 2), 3);

       重温一下NSub的相同功能:

Copy_calculator = Substitute.For<ICalculator>();
_calculator.Add(1, 2).Returns(3);
Assert.AreEqual(_calculator.Add(1, 2), 3);

       和NSub不同,Fakes提供的功能少了很多,不仅如此,每次更改项目都可能要重新添加Fakes引用(至少我在编译服务器上的项目老是因为Fakes出错)。所以一般不建议使用Fakes做Stub的功能。但是官方文档中外部程序集(如 System.dll)通常没有单独的接口定义,因此必须改用填充码 这句话却没有错,反正System.dll之类的第三方程序集又不可能经常改变,所以也没有需要重新添加Fakes程序集这个烦恼。下面介绍一下Shim的使用。

       假设有一个类:

Copypublic static class Y2KChecker
{ 
   public static void Check() 
      {
              if (DateTime.Now == new DateTime(2000, 1, 1))
                          throw new ApplicationException("y2kbug!");
    }
}

       由于它依赖于DateTime.Now,而假设我们没办法更改这段代码,为了对它进行单元测试我们必须使用Shim破除对DateTime.Now的依赖。首先选中System引用并右键选择添加Fake程序集,然后在测试代码的ShimsContext中插入Shim:

Copyusing (ShimsContext.Create())
{    // Arrange:
    System.Fakes.ShimDateTime.NowGet = () => new DateTime(2000, 1, 1);    
    // Act and Assert::
    Assert.ThrowsException<ApplicationException>(Y2KChecker.Check);
}

       如上面代码所示,Shim可以伪造DateTime.Now的值,这对单元测试提供了极大的方便。

       5、 结语

       虽然Fakes中的Stub不好用,但Shim还是挺有趣的,我建可以同时使用NSub和Fakes里的Shim。善用VisualStudio的各种工具可以大大提升单元测试的效率,不过基本上这些工具都只在Enterprise版本中提供。

       有趣的是MSTest自己也没有用Fakes,很多时候都是用moq。(例如PlatformServiceProviderTests.cs)

图7.png

       另外VisualStudio还有一些有趣的工具辅助单元测试,例如walterlv的这篇博客(不再为命名而苦恼!使用 MSTestEnhancer 单元测试扩展,写契约就够了)介绍了一种更直观的单元测试编写方式,不放试一试:

图8.png


作者:dino.c

链接:https://www.cnblogs.com/dino623/p/11266007.html#4006733657

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   就在我们等待英国竞争和市场管理局对微软以 690 亿美元收购动视暴雪的计划发出"同意/不同意"的信号时,一份新的报告称,微软最近对收购计划的修改将不必再经过欧盟的一系列调查。  欧盟监管机构--欧盟委员会早在今年 5 月就批准了微软收购动视暴雪的计划。然而,英国 CMA 于 4 月否决了同一计划,声称这会给微软在云游戏市场带来反竞争优势。  此后,微软向 CMA 提交了一份新计划。微软承诺让育碧通过云流媒体提供当前和未来的动视暴雪游戏。中国软件行业协会已临时批准了这一计划,预计将在 10 月 18 日之前给予最终批准。  有人猜测,由于微软计划的改变,欧盟可能会下令对该...
            0 0 576
            分享
          •   不管是Loadrunner还是jmeter进行性能测试,测试流程基本上都是一样的,限制以Jmeter为例分析测试流程:  一、性能测试需求分析  一般而言,被测对象的性能需求,会在用户需求规格说明说中给出,比如单位时间内的访问量达到多少、业务响应时间不超过多少、业务成功率不低于多少、硬件资源消耗应该在一个合理的范围内等,性能指标应以量化数据给出,对于一个规范的产品,产品团队会给出如下的性能要求:  如果产品团队并没有指明性能测试需求,或者只给出表述字面意义上的需求,如:系统的TPS需要到300以上,单笔交易时间不超过3秒,那么测试工程师如何提前量化的指标呢?  需要结合业务需求和系统本身特...
            0 0 183
            分享
          •   作为一名技术人,工作几年后越发觉得,决定你走到一定位置上关键的因素不仅仅是技术能力,情商更是占据了很大一部分。  反面-性格决定命运  俗话说性格决定命运,这是有一定道理的。  拿我身边的例子来说,李哥,在开发组工作了4年多,一直工作态度认真,但有一个毛病——情绪比较容易激动。  年后回来,因为一个问题导致他的工作脱了两天,期间他也跟相关同事沟通过,但是没解决。反馈给pm,pm没有帮忙协调。  一直等到快要上线的时候pm才帮忙处理了相关问题,但结果可想而知——来不及了,需要李哥加班才能解决问题。  不仅如此,这位pm的态度也不是很友好,认为问题出在李哥身上,一系列不如意的交涉后,李哥一气之...
            0 0 766
            分享
          • 读者提问:测试管理如何做到灵活调度测试资源 ?阿常回答:我在企业中的做法,供参考,有不同观点欢迎讨论。如何做到灵活调度测试资源1 将团队按业务线分成几个小组根据不同的业务线划分不同的测试小组;每个测试小组2~3人不等,每个小组指定一个leader;小组leader尽量不做变动,其他成员可根据具体不同业务的迭代任务量来做资源调度。2 周例会各业务组分享测试经验每周安排例行的业务测试经验分享;分享内容选取各业务线的重点业务;分享者为各业务测试小组的测试同学。3 各小组到其他业务组交叉测试在某个业务组需求任务较重时,从其他业务组调度测试资源;在各业务组同期迭代任务都较少的情况,安排各业务组进行交叉测...
            0 0 661
            分享
          •   缘起  众所周知,系统测试是需要编写测试用例的,它是保证测试执行正确性、有效性的基础。但是,大家可能很难想象神秘的黑客在挖掘漏洞的时候会提前编写测试用例,然后按照用例去执行。因为他的漏洞挖掘思路是存在脑海中,并且不断的根据实际情况进行调整的。  当然,关于黑客单打独斗挖掘漏洞的这种想象,显然已不大符合当前安全界的实际情况。从网络及信息安全的攻击角度来说,恶意攻击分子已经逐渐形成了目标精准、分工明确、技术先进的网络黑色产业链条,相应的从安全保护和防御角度来说,国家加大了对网络攻击等犯罪行为的打击力度,企业也逐渐加大了网络安全投入。  那么,当安全测试成为企业安全建设中的一个重要环节,安全测试...
            0 0 1638
            分享
      • 51testing软件测试圈微信