近期应项目须要,笔者疯狂学习UWP项目测试的知识,确实学习到了很多关于测试方面的知识,等有时间会好好地记录下测试的学习成果。OK,回到主题,在笔者作项目测试的过程当中把本身遇到的坑都简单的记录了下来,而且写了个关于测试的Demo,传送门。下面简单地笔者的初入测试门槛的经验!ios
首先上环境:git
使用到的测试框架:MSTest 提供的 UnitTestFramework + 微软 Microsoft BigPark Studios
团队开发的 SimpleStub
Mock框架。github
处于笔者的水平限制,笔者前后尝试了 NUnit
、XUnit
等多款测试框架可是效果并非太好,其中 NUnit
彷佛对 UnitTestProject
(单元测试应用)并不太友好(多半是笔者水平的问题,若是有Dalao能教下我NUnit与UWP的集成请私信),网上的dalao们使用 XUnit
多数是基于 ClassLibrary
的项目,而笔者尝试的时候发现系统没法直接调用 ClassLibrary
所书写的测试 ,须要加载 Runner
,有些小麻烦,不过应该也是能用的。最终,多番尝试后笔者敲定了使用 MSTest
+ SimpleStub
这两款框架(都是来自微软,相信与UWP兼容性不错)。框架
MSTest比较简单,上述的MSDN传送门对应的网页有详细的指导,而 SampleStub
则须要注意挺多的,笔者将本身在使用过程当中踩的一些可能比较常见的坑记录了下来,下面上笔者记录的小坑:函数
摘自笔者Demo项目的README:单元测试
做为一个刚入测试的小菜鸡,做者在结合使用这两个框架的时候也遇到了不少坑,下面简单列举一些萌新们可能会踩的坑:学习
- UWP 新建一个UnitTest项目?
答:UWP 的单元测试项目优选
单元测试应用
类型的项目,即新建一个单元测试应用
的项目,而且在其中书写本身的测试测试
- 为何在新建的UnitTestProject内新建测试文件不会在测试列表中显示?
答:测试文件目前使用的是注解机制,其中对做为TestFixture的测试类以及测试方法都是有访问权限要求的,即必须都为
public
的 ,而且测试方法Method
必须为public void
类型的。spa
测试经常使用的东西:
Assert
类的诸多方法,Such as:AreEqual
AreSame
IsTrue
等code如何在目前的Unit测试引入Mock框架?
答:目前的状况,做者尝试过许多框架,出于做者水平,这些框架(NUnit Template 不支持、XUnit 换成Library没法识别测试)在做者的UWP上表现都不太好。目前发现表现最好的是微软去年年底推出的
SimpleStub
框架,而后做者也推荐使用这个,由于做者我的认为这个是目前与MSTest
兼容最好的Mock框架。
SimpleStub
如何使用?答:Nuget -> download SimpleStub nuget package 。而后环境就已经搭建好了,选择你的测试项目进行生成,此时框架会自动在编译期间在项目obj目录下生成一个
SimpleStub.generate.cs
的文件。利用这个文件生成一个StubXxxx
的Mock对象进而实现测试,详细用法见样例代码(UnitTestProject1
内的TestUserMagr.cs
)Tips:
- 这里补充说明下,若是项目生成后在obj目录下没找到
SimpleStub.generate.cs
文件,说明生成SimpleStub.generate.cs
文件失败了,此时应该去查看Console(输出控制台)的输出内容,挖掘出错误的缘由,解决异常后从新生成下便可!
SimpleStub
框架为咱们生成的 StubXxx
Mock对象的一些方法构建,由于这与构建的Mock对象的 MockBehavior
息息相关,详细请见示例代码最后,上笔者Demo中测试的部分代码:
namespace UnitTestProject1 { [TestClass] public class TestUserMagr { // 待测试对象-> uMagr Mock对象->uMagr.UDao(IUserDao) private UserMagr uMagr; [TestInitialize] public void BeforeTestInitialize() { uMagr = new UserMagr(); } [TestMethod] public void TestCallSequence() { // 新建mock对象 var stub = new StubIUserDao(MockBehavior.Strict) .CreateUser((p2) => { return null == p2 ? 0 : 1; }, Times.Once)// 限定最多调用一次 .CreateUser((p2) => { return null == p2 ? 0 : 1; }, Times.Twice)// 限定最多调用两次 .CreateUser((p2) => { return null == p2 ? 0 : 1; }, Times.Forever);// 解除调用次数上限设置 // 若是不执行上述最后一行,那么stub对象只能执行CreateUser 两次(取决于最后一条的限定),执行超出次数会抛异常 // 将Mock对象赋值给依赖对象,从而解除依赖对象对测试的干预 uMagr.UDao = stub; // 从这开始执行测试 相似 EasyMock->replayAll(); Assert.AreEqual(1, uMagr.CreateUser(new User() { Username = "123", Password = "123" })); Assert.AreEqual(1, uMagr.CreateUser(new User() { Username = "123", Password = "123" })); Assert.AreEqual(1, uMagr.CreateUser(new User() { Username = "123", Password = "123" })); } [TestMethod] public void TestMethod_WithReturnType_WithParameters()// 测试Mock对象的函数带参数的调用 { // 设置一些初始变量 int Expect = 1; string Username = null; string Password = null; // 用于判断是否修改的对象 User user = new User() { Username = Username, Password = Password }; // 开始构建Mock var stub = new StubIUserDao() .CreateUser((u) => { user = u; return Expect; }); uMagr.UDao = stub; // replayAll() Assert.AreEqual(Expect, uMagr.CreateUser(new User() { Username = "test" })); Assert.AreEqual("test", user.Username); } [TestMethod] public void TestThatMethodStubCanBeOverwritten()// 测试Mock对象的方法是否支持重写 { // 构建一个Mock对象 var stub = new StubIUserDao() .CreateUser(u => 1); // 重写其调用的方法,若是须要重写则须要加上overwrite:true,不然将不会重写 stub.CreateUser(u => 2, overwrite: true); uMagr.UDao = stub; // replayAll() Assert.AreEqual(2, uMagr.CreateUser(new User())); } [TestMethod] [ExpectedException(typeof(SimpleStubsException))] public void TestMethod_WithReturnType_WithParameters_DefaultBehavior_Strict()// 展现 MockBehavior为Strict下的不一样之处,于下面的method一块儿比对观察 { // 构建一个不带函数定义的Mock对象(存根) var stub = new StubIUserDao(MockBehavior.Strict); uMagr.UDao = stub; // 调用方法的时候,Strict模式下会抛出异常,由于没有定义调用函数 Assert.AreEqual(0, uMagr.CreateUser(null)); } [TestMethod] public void TestMethod_Void_WithNoParameters_DefaultBehavior_Loose() { // 构建一个不带函数定义的Mock对象(存根),默认下MockBehavior为Loose var stub = new StubIUserDao(); uMagr.UDao = stub; // 调用方法的时候,Loose模式下不会抛出异常,而且返回函数返回值的默认值 null | 默认基本类型值 | Assert.AreEqual(0, uMagr.CreateUser(null)); } } }
OK,就先记录到这!