zoukankan      html  css  js  c++  java
  • 在Visual Studio 2012使用单元测试

    本人之前很少使用单元测试,总觉得平时的工作写得代码够多了,单元测试还要再编码,增加大量工作量,相信不少程序猿也是这么认为吧。


    但是我认为,在必要的时候正确运用单元测试,可以大大缩短代码的调试时间,正所谓磨刀不误砍柴工,在此建议仍不会单元测试的,还是学一下吧。当然本人在单元测试方面还是菜鸟,无论是鸡蛋鲜花都欢迎。

    最近公司请微软的人做了一些关于使用VS2012进行单元测试的小培训,小生微做笔记,结合朦胧的记忆,在此自行总结,并分享之。废话少说,先上笔记: 

    1.先写单元测试(依我愚见,应该是接口先行,如果有的话) -> 测试失败 -> 以最小的改动(即编写实际代码)使测试通过(而在VS2012中已经不能通过现有项目直接生成测试项目了,我觉得这个功能还是应该保留,微软总是这副德行,强迫用户适应他们的产品,但是又不得不适应);

    2.不因单元测试而追加功能(代码),即逻辑不受单元测试影响;

    3.改变了代码的逻辑(增删改),应及时运行单元测试;

    4.在测试方法声明Attribute —— TestCategory("分类或特征名");

    5.在单元测试项目添加Fakes程序集分离外部依赖(如数据库访问,获取配置信息等);

    6.初始化单元测试类中的成员等信息,可添加方法并声明Attribute[TestInitialize](方法需为public);

    7.测试自动化。

    以下我将通过自己编写代码来验证上述笔记中的部分要点。有些未涉及,以后再尝试了。

    1.新建一个单元测试项目,并添加类XmlSerializationTest,代码如下:

        [TestClass]
        public class XmlSerializationTest
        {
            [TestMethod]
            public void TestWriteXml()
            {
                UserModel user = new UserModel();
                XmlSerialization serialization = new XmlSerialization();
                bool flag = serialization.WriteXml<UserInifo>(user);
                Assert.IsTrue(flag);
            }
        }
    View Code

    由于我这个项目是对Xml序列化进行测试,因而前提是项目中已存在了一个UserModel类,并且在单元测试项目中添加相应引用

        public class UserModel
        {
            public string LoginName { get; set; }
            public string Password { get; set; }
        }
    UserModel

    接下来在编写实际的代码,微软讲师建议我们先在测试项目编写,待通过单元测试后再将代码移到相应的项目下面。

        public class XmlSerialization
        {
            public bool WriteXml<T>(T model)
            {
                throw new NotImplementedException();
            }
        }
    XmlSerialization

    现在整个解决方案结构如下图所示

    保证整个解决方案生成成功之后点击菜单“测试” -〉 “运行” -〉 “所有测试”,发现测试不通过,于是就按照第一点笔记,以最小改动使测试通过。

    修改WriteXml方法为:

    public bool WriteXml<T>(T model)
    {
        return true;
    }

    运行测试通过。对于返回值为bool的方法,个人建议进行至少两次Assert,也就是分别对返回true和false进行Assert,因而我们再对WriteXml方法添加一个测试方法,

            [TestMethod]
            public void TestWriteXmlFalse()
            {
                Assert.IsFalse(new XmlSerialization().WriteXml<UserModel>(null));
            }

    运行测试,不通过,所以我得要好好改我的代码了,在改动当中坚持执行我的第三点笔记,改动代码及时运行单元测试。

        public class XmlSerialization
        {
            private string filePath;
            public XmlSerialization(string filePath)
            {
                this.filePath = filePath;
            }
    
            public bool WriteXml<T>(T model, string filePath = null) where T : class
            {
                bool result = false;
                if (model == null)
                {
                    return result;
                }
    
                if (string.IsNullOrEmpty(filePath))
                {
                    filePath = this.filePath;
                }
    
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                using (TextWriter tr = new StreamWriter(filePath))
                {
                    serializer.Serialize(tr, model);
                    tr.Close();
                    result = true;
                }
    
                return result;
            }
    
            public T ReadXml<T>(string filePath = null) where T : class
            {
                T model = null;
                if (string.IsNullOrEmpty(filePath))
                {
                    filePath = this.filePath;
                }
    
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                TextReader tr = null;
                try
                {
                    tr = new StreamReader(filePath);
                    model = (T)serializer.Deserialize(tr);
                }
                catch { }
                finally
                {
                    if (tr != null)
                    {
                        tr.Close();
                        tr.Dispose();
                    }
                }
    
                return model;
            }
        }
    XmlSerialization

    我们发现这个类的构造函数多了一个参数,是对象序列化后保存的路径,且该类对应的测试类都需要用到,因而我希望在每次测试进行单元测试前先将对象的构建,这就是第六点笔记提供的“声明Attribute[TestInitialize]”(注意必须是public方法,我用private方法运行测试是不通过)。改造后的测试类如下:

        [TestClass]
        public class XmlSerializationTest
        {
            private XmlSerialization serialization;
            [TestInitialize]
            public void InitTest()
            {
                this.serialization = new XmlSerialization(@"F:\usermodel.seri");
            }
    
            [TestMethod]
            public void TestWriteXml()
            {
                UserModel user = new UserModel();
                bool flag = serialization.WriteXml<UserModel>(user);
                Assert.IsTrue(flag);
                Assert.IsFalse(serialization.WriteXml<UserModel>(null));
            }
    
            [TestMethod]
            public void TestReadXml()
            {
                UserModel user = new UserModel();
                user.LoginName = "aa";
                serialization.WriteXml<UserModel>(user);
                UserModel model = serialization.ReadXml<UserModel>();
                Assert.IsNotNull(model);
                Assert.AreEqual(user.LoginName, model.LoginName);
    
                //路径不存在,应返回null
                UserModel modelnull = serialization.ReadXml<UserModel>(@"F:\notexists.seri");
                Assert.IsNull(modelnull);
            }
        }
    XmlSerializationTest

    还可以分析测试代码的覆盖率,如下图所示在测试资源管理器点击“运行”下的相应选项。

    居然是100%,真不知道这个东西微软是怎么分析出来的。

    把类XmlSerializationTest移到相应的项目,更改命名空间,在测试项目添加相应引用,测试通过。

    将解决方案添加到TFS源码管理,我这边是用的是微软云TFS免费版。

    收工。

    VS提供了很多类型的测试,负载、UI等等测试,感觉还是蛮强大的。

    下一篇:VS2012 单元测试之泛型类(Generics Unit Test)

  • 相关阅读:
    【LOJ】#2548. 「JSOI2018」绝地反击
    【LOJ】 #2547. 「JSOI2018」防御网络
    【LOJ】#2513. 「BJOI2018」治疗之雨
    【LOJ】#2546. 「JSOI2018」潜入行动
    【LOJ】#2479. 「九省联考 2018」制胡窜
    【LOJ】#2511. 「BJOI2018」双人猜数游戏
    【LOJ】#2493. 「BJOI2018」染色
    【LOJ】#2492. 「BJOI2018」二进制
    【LOJ】#2512. 「BJOI2018」链上二次求和
    使用POI读取excel文件内容
  • 原文地址:https://www.cnblogs.com/FreeDong/p/3129625.html
Copyright © 2011-2022 走看看