当前位置: 首页 > news >正文

不再为命名而苦恼!使用 MSTestEnhancer 单元测试扩展,写契约就够了

有没有觉得命名太难?有没有觉得单元测试的命名更难?没错,你不是一个人!看看这个你就知道了:程序员最头疼的事:命名 或它的英文原文 Don’t go into programming if you don’t have a good thesaurus - ITworld。

立刻前往 nuget.org 下载安装 MSTestEnhancer 即可解决命名的苦恼。


体验 MSTestEnhancer

看看苦恼的单元测试怎么写:

[TestClass]
public class 被测类名Test
{
    [TestMethod]
    public void 被测方法名_条件1_预期1()
    {
        // 测试用例代码
    }

    [TestMethod]
    public void 被测方法名_条件2_预期2()
    {
        // 测试用例代码
    }
}

这是以 MSTest 为例,但 NUnit、XUnit 等编写体验于此也类似,都需要为测试方法命名。在这个例子中,我们写了中文的 条件预期,在实际编写时,可能是更加复杂的短句,例如:ArgumentNullThrowsArgumentNullException,于是最终的方法名可能是 TargetMethod_ArgumentNull_ThrowsArgumentNullException。这样的方法多了也就难以读懂单元测试的代码了。

然而现在看看 MSTestEnhancer 的单元测试怎么写:

[TestClass]
public class 被测类名Test
{
    [ContractTestCase]
    public void 被测方法名()
    {
        "契约 1(当 Xxx 时,应该发生 Yyy)".Test(() =>
        {
            // 测试用例代码
        });

        "契约 2(但当 Zzz 时,应该发生 Www)".Test(() =>
        {
            // 测试用例代码
        });
    }
}

有没有觉得很直观?条件和预期直接以中文字符串的形式写在了代码里,所有契约的阅读一目了然。而且由于不需要再写条件和预期了,所以测试方法名可以与被测方法名完全一样。也就是说——再也不用为单元测试的方法取名字而伤透脑筋了。

可是,工具支持呢?不要紧,在工具中也能显示中文的契约,Visual Studio 中的测试管理器和 ReSharper 测试结果页都支持显示这些中文的契约。以下是 ReSharper 的单元测试结果页视图:

单元测试结果页

每个契约按照方法名归类防止,测试结果一目了然。

参数化的单元测试

有些契约需要更多的值组合来验证正确性,那么可以在契约测试用例的后面添加参数。

"质数".Test((int num) =>
{
    // 测试用例代码
}).WithArguments(2, 3, 5, 7, 11);

"{0} 不是质数".Test((int num) =>
{
    // 测试用例代码
}).WithArguments(1, 4);

也可以添加多个参数(最多支持 8 个):

"契约 1,参数中可以带 {0} 和 {1}。".Test((int a, int b) =>
{
    // 现在,a 会等于 2,b 会等于 3。
}).WithArguments(2, 3);

"契约 2".Test((int a, int b) =>
{
    // 现在有两组代码,一组 a=2, b=3;另一组 a=10, b=20// 当然也可以传入元组数组。
}).WithArguments((2, 3), (10, 20));

在显示单元测试结果时,如果契约字符串中含有格式化占位符 {0}{1} 等,会被自动替换为参数的值。

异步的单元测试

Test 方法中传入的每个 Action 都支持 async 关键字,并会在执行测试用例时等待异步操作结束。

额外的黑科技

MSTest v2 支持嵌套类型的单元测试。也就是说,我们可以利用这一点做出近乎无限层级的单元测试树出来。

相关文章:

  • Windows 10 自带那么多图标,去哪里找呢?
  • 如何删除 Windows 10 系统生成的 WindowsApps 文件夹
  • 命令“xxx.exe xxx”已退出,代码为 n。这些错误是什么意思?
  • 将 async/await 异步代码转换为安全的不会死锁的同步代码
  • 屏幕上那个灰色带有数字的框是什么?看着好难受!
  • Roslyn 入门:使用 Roslyn 静态分析现有项目中的代码
  • Roslyn 入门:使用 Visual Studio 的语法可视化窗格查看和了解代码的语法树
  • 利用 ReSharper 自定义代码中的错误模式,在代码审查之前就发现并修改错误
  • 在编写异步方法时,使用 ConfigureAwait(false) 避免使用者死锁
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • 解决 mklink 使用中的各种坑(硬链接,软链接/符号链接,目录链接)
  • Roslyn 的确定性构建
  • 使用 MSBuild 响应文件 (rsp) 来指定 dotnet build 命令行编译时的大量参数
  • VS 编译太慢了吗?新建解决方案配置关闭一部分项目的编译
  • 流畅设计 Fluent Design System 中的光照效果 RevealBrush,WPF 也能模拟实现啦!
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Android 架构优化~MVP 架构改造
  • Android组件 - 收藏集 - 掘金
  • css的样式优先级
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • eclipse的离线汉化
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Javascript 原型链
  • jquery cookie
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 程序员该如何有效的找工作?
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 源码安装memcached和php memcache扩展
  • 阿里云API、SDK和CLI应用实践方案
  • 组复制官方翻译九、Group Replication Technical Details
  • ​第20课 在Android Native开发中加入新的C++类
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #define、const、typedef的差别
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (论文阅读11/100)Fast R-CNN
  • (七)理解angular中的module和injector,即依赖注入
  • (十)c52学习之旅-定时器实验
  • (转)visual stdio 书签功能介绍
  • .NET 表达式计算:Expression Evaluator
  • .net(C#)中String.Format如何使用
  • @Conditional注解详解
  • @EnableAsync和@Async开始异步任务支持
  • @html.ActionLink的几种参数格式
  • [ 手记 ] 关于tomcat开机启动设置问题
  • [ 数据结构 - C++]红黑树RBTree
  • [Android] 240204批量生成联系人,短信,通话记录的APK
  • [android] 天气app布局练习
  • [Android]使用Git将项目提交到GitHub
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [C#]扩展方法