【C#编程最佳实践 一】单元测试实践

简介: 【C#编程最佳实践 一】单元测试实践

工作三周了,深深理解了学校和工作中处理问题的不同,从武哥这里得到了四字经验:最佳实践,而这个最佳实践是先投入工作,而后获取结论,改变之前先理论后实践的做法。于是产生了写一系列的博文的想法,积累工作中的经验,希望以后少踩坑,本篇为开篇第一篇,涉及到我这两周真正有所实践的学习–单元测试。本系列最佳实践每一篇博文都长期更新,而且每一篇都会分两方面来讲:1,知识的通用性,2,知识在工作中的最佳实践。

单元测试

注意:本篇只针对C#,适用版本vs2015

定义

是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,Java里单元指一个类,C#中,一个方法,一个类,一个窗口的测试。即单元测试。单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中 要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

一些常识

测试范围:单元测试一般针对公共方法,例如public修饰的方法

测试人:编写者自身

测试时机:在函数编写之前,并随着功能增加不断增加测试用例

通用操作

创建和运行

1,创建单元测试项目

2,依据要测试的项目,各级对应创建相应的文件夹

3,在文件夹下添加单元测试

4,注意待测方法前要加[Test Method],否则不能生成单元测试

5,第一次测试的时候要生成解决方案,然后才能运行或调试单元测试

常用测试方法

常用测试方法测试:

Assert.IsNull() 测试指定的对象是否为空引用,如果为空,则测试通过;

Assert.IsNotNull() 测试指定的对象是否为非空,如果不为空,则测试通过;

Assert.IsTrue() 测试指定的条件是否为True,如果为True,则测试通过;

Assert.AreEqual() 测试指定的值是否相等,如果相等,则测试通过;

对于不同返回类型需要做哪些测试

**对于int型:**Assert.AreEqual()方法来测试是否和预期值相等,一般测试是否为1

对于String类型的:先测是否为null---Assert.IsNull(),然后测是否为空串Assert.AreEqual(),最后测和预期值是否相符Assert.AreEqual()

对于list类型:先测是否为null–Assert.IsNull(),然后测list.Count>0是否为真Assert.IsTrue() ,最后测返回列表个数list.Count是否和预期相同Assert.AreEqual()

最佳实践

随着单元测试的深入,持续进行,会涉及到各个方面:首先,DAO层的单元测试最佳实践

最佳实践规则

1,单元测试原子性,没有switch,没有分支,总体来说,圈复杂度为1–ps(vs2015可安装CodeMetrics插件检测圈复杂度)

2,单一职责,指行为不是方法,类例如数据库里的增删改查,CRU和SafeCRU,一个整体行为,而不是多个方法,这样可以减少代码量,而且也对整个行为进行了测试

3,独立无耦合,单元测试间不能相互调用,否则有可能出现无限循环错误

4,属性值不共享,每个独立单元都要准备自己的数据,虽然复用低,但是能保证一致

5,测试驱动开发,单元测试越早越好,我之后写代码也要记住这一点

最佳实践结构

依照个人经验总结以下结构:

1,测试类内准备的公共数据

该测试准备数据修饰为private static

1,公共待测数据:公有的,各个方法都会使用到的测试数据

2,公共的预期值:公有的,约定好的各个待测方法的执行预期值

2,测试类内准备的继承自父类方法的测试

由于一些类可能会共用一些方法,所以可以抽象出一个公共父类,这样我们把所有公共父类所有的方法单独拿出来测试,这样每一个子类测试的时候测试到公有父类的方法可以减少错误的发生,甚至可以直接copy代码

该测试方法修饰为 public void 待测方法名()注意,一定要为public,否则测试无法进行

1,该方法私有的待测数据:私有的,该方法测试需要用到的数据 类型一般为var

2,该方法私有的业务测试:私有的,该方法核心功能的测试(例如一个更新操作函数,就不需要对其它诸如创建等做过多assert)

3,销毁为测试准备的所有数据(公有+私有)

3,测试类内准备的自身实现的方法的测试

不是从父类继承的公用方法,也主要包括三个步骤

该测试方法修饰为 public void 待测方法名()注意,一定要为public,否则测试无法进行

1,该方法私有的待测数据:私有的,该方法测试需要用到的数据 类型一般为var

2,该方法私有的业务测试:私有的,该方法核心功能的测试(例如一个更新操作函数,就不需要对其它诸如创建等做过多assert)

3,销毁为测试准备的所有数据(公有+私有)

最佳实践操作

tip:还可以做代码覆盖率检测哦。利用vs自带的代码覆盖率检测可以看到有哪些方法还没有被测试

DAO层进行的最佳实践

dao层一般用于和数据库的存储过程进行交互,操作无外乎增删改查,且大多数的增删都是通过id来操作,而更新和删除则是通过id和一些相应的参数来实现。

公有的准备数据

对应于准备数据的最佳实践:一般先不做公共准备数据,而是先写各个方法自己存在的准备数据,最后发现统一的可以抽象成公共数据。经过实践,我们可以这么准备数据

#region 公共的准备数据
        // *************************************************************公共的准备数据
        private static int age= 2345;   //例如下边的方法用到了age,所以抽象出来
        /// <summary>
        /// 创建方法,如果每个测试方法都用到了Create,则把它抽象出来实现复用(但不能再将其视为单元测试方法)
        /// </summary>
        /// <returns></returns>
        private int Create(Guid id)
        {
            var model = Build(id);
            return UserDao.Instance.Create(model);
        }
        /// <summary>
        /// 实例构造方法
        /// </summary>
        /// <returns></returns>
        private User Build(Guid id)
        {
            return new User()
            {
                ID = id,
                UserName = "tianmaolin",
                Age=age
             };
        }
        #endregion 公共的准备数据
        #region 公共的预期值
        //*************************************************************公共的预期参数值
        private static int checkDataRight = 1;
        #endregion 公共的预期值

对方法进行单元测试

#region 继承自父类的方法进行的单元测试
        //********************继承自父类的方法进行的单元测试***********************************
        /// <summary>
        /// 基于id测试用户的增删改查
        /// <param name="id"/>
        /// </summary>
        [TestMethod]
        public void UserCRUD()
        {
            //准备数据==========================================================SetUp
            var id = Guid.NewGuid();
            var model = Build(id);
            var create = Create(id);
            //准备好的更新状态
            var modelupdate = new User()
            {
                ID = id,
                UserName = "tttttttt",
            };
            //测试创建============================================================ C
            //测试是否创建成功
            Assert.AreEqual(checkDataRight, create);
            //测试是否查询成功=====================================================R
            var read = UserDao.Instance.GetById(id);
            Assert.IsNotNull(read);  //非空测试
            Assert.IsTrue(read.ID == id);//Guid一致性测试
            Assert.IsTrue(read.UserName == "tianmaolin");//创建者姓名一致    
            Assert.IsTrue(read.Age == age);//创建者年龄一致性测试
            //测试是否更新成功(依据新model更新) =================================== U
            var update = UserDao.Instance.Update(modelupdate);
            Assert.AreEqual(checkDataRight, update);//更新成功测试
            var readupdate = UserDao.Instance.GetById(id);//更新后获取
            Assert.IsTrue(read.UserName == "tttttttt"),创建者姓名更新测试      
            //测试删除=============================================================D
            var delete = UserDao.Instance.Delete(id);
            Assert.AreEqual(checkDataRight, delete);//是否删除成功
            var readagain = UserDao.Instance.GetById(id);//再次查询
            Assert.IsNull(readagain);//为空则删除成功
            //====================================================================TearDown
        }
        #endregion 继承自父类的方法进行的单元测试

踩过的坑

1,如果两张表有主外键关联关系,对从表的数据进行单元测试的时候先要创建主表的数据,最后还要记得销毁主表里的数据,例如student的插入依赖class。

2,写单元测试之前,一定要看代码的具体实现,我写代码发现存储过程里的操作之前有查重操作,然而自己并没有看好,导致每次都插入失败,血淋淋的教训,一定要先看好待测函数的功能实现,避免采坑!!!,尤其是涉及到模糊查询的时候,创建第二条数据的时候一定要改变要求非重复的值,否则会创建失败。

3,涉及到更新的单元测试,提前准备好更新数据,还得注意哪些数据无需更新,不是所有传入的参数都是要更新的,不要导致一直报错

建议测试过程

1,先看函数要实现什么功能,一定要理解他要的输入和期望的输出,如果有分支流程还得注意准备两套数据,如果有更新要提前准备更新数据

2,再看存储过程需要什么参数,存储过程里是否有查重等条件限定,要创建满足条件限定的准备数据

3,然后要准备好数据,发现多个方法有公有数据,统一拿出来,创建这种通用操作抽离出来

4,测试之后一定要记得销毁数据

5,出错要耐心调试,注意表间关系

相关文章
|
2天前
|
敏捷开发 测试技术 持续交付
自动化测试在敏捷开发中的实践
【7月更文挑战第5天】自动化测试在敏捷开发中扮演着至关重要的角色。通过制定合适的测试策略、选择合适的测试工具、编写和维护测试脚本以及集成到持续集成流程中,可以显著提高测试效率、加快反馈周期、提高测试覆盖率和降低测试成本。未来,随着技术的不断发展和敏捷开发的深入应用,自动化测试将在软件开发中发挥更加重要的作用。
|
4天前
|
敏捷开发 监控 测试技术
软件测试中的敏捷实践:如何有效整合测试与开发
【7月更文挑战第3天】在软件开发的快速迭代周期中,敏捷测试成为确保产品质量的关键。本文将探讨如何在敏捷开发环境中整合测试与开发工作,包括持续集成、测试自动化和跨功能团队协作的策略,旨在提升软件交付的速度和质量。
|
9天前
|
存储 C# 开发者
C# 编程基础:注释、变量、常量、数据类型和自定义类型
C# 编程基础:注释、变量、常量、数据类型和自定义类型
14 1
|
2天前
|
敏捷开发 jenkins 测试技术
软件测试中的敏捷实践:持续集成与自动化测试的融合之道
在软件开发领域,敏捷实践已成为提升项目响应速度和质量保证的重要手段。本文深入探讨了持续集成(CI)与自动化测试如何相辅相成,共同构建起一套高效、可靠的软件测试体系。通过实例分析,揭示了将敏捷原则应用于软件测试过程中的关键策略,并提出了实现这一目标的可行路径。文章旨在为软件测试专业人员提供一套结合敏捷理念的实用方法论,以应对快速迭代的软件项目需求。
|
3天前
|
测试技术 程序员 持续交付
软件测试中的敏捷实践:提升效率与质量的双重策略
在软件开发领域,敏捷实践已被证明是提高项目适应性、效率和产品质量的关键因素。本文深入探讨了敏捷方法在软件测试中的应用,并分析了其对测试流程的积极影响。通过引用最新的行业研究数据和案例分析,文章揭示了敏捷测试如何促进团队协作、缩短反馈循环、优化资源分配,并最终提升软件产品的整体质量。结合逻辑严密的分析框架和科学的数据支持,本研究旨在为软件测试专业人士提供一套实证基础的实践指南。
|
5天前
|
敏捷开发 算法 搜索推荐
软件测试的演变:从传统方法到敏捷实践
本文深入探讨了软件测试领域的发展轨迹,从早期以代码为中心的测试方法,到今日强调快速迭代和持续集成的敏捷测试实践。文章通过分析历史数据、行业报告以及权威研究,揭示了测试自动化、跨功能团队合作以及质量保证在现代软件开发中的重要性。进一步地,本文还讨论了如何将科学严谨性融入测试过程,包括采用基于证据的测试策略、利用统计方法评估软件质量,并提出了逻辑严密的测试案例设计原则。
|
5天前
|
机器学习/深度学习 人工智能 算法
自动化测试的演进与实践
随着软件行业的飞速发展,传统的手工测试方式已无法满足日益增长的软件质量保证需求。自动化测试作为提高软件测试效率和质量的关键工具,其发展和应用受到业界广泛关注。本文旨在探讨自动化测试技术的发展历程、面临的挑战及未来的发展方向。通过分析自动化测试的优势与局限,结合最新的行业数据和研究结果,揭示自动化测试在现代软件开发中的核心地位及其实践价值。
9 0
|
5天前
|
敏捷开发 jenkins 测试技术
软件测试中的敏捷实践:持续集成与自动化测试的融合
在软件开发领域,敏捷方法论的兴起带来了开发流程的重大变革。特别是持续集成(CI)和自动化测试的结合使用,为提升软件质量和开发效率提供了强有力的支持。本文将探讨持续集成环境下自动化测试的实施策略、优势以及面临的挑战,并借助实证数据和案例分析,揭示这一组合如何促进敏捷团队高效地应对快速变化的需求与代码库。
11 0
|
5天前
|
测试技术 UED
软件测试的科学与艺术:从数据导向到逻辑严密的实践
本文旨在探讨软件测试领域中数据导向和逻辑严密性的重要性,并分析如何通过科学严谨的方法提升测试效率和质量。文章首先概述了软件测试的基本概念和挑战,随后深入讨论了数据在测试设计和结果分析中的关键作用,以及如何利用逻辑推理来构建有效的测试案例和识别潜在缺陷。最后,本文提出了一系列实践建议,旨在帮助测试人员更好地整合数据驱动和逻辑推理方法,以实现软件测试的最优化。
8 0
|
8天前
|
机器学习/深度学习 人工智能 监控
探索自动化测试的前沿技术与实践
在软件开发周期中,自动化测试已成为确保软件质量和效率的关键因素。本文旨在探讨自动化测试的最新技术和实践方法,通过分析当前行业内的最佳实践和面临的挑战,提供一系列针对性的策略和建议。我们将深入讨论如何有效集成自动化工具、优化测试流程、以及提升测试覆盖率和精确度。文章结合了权威的数据支持和技术分析,旨在为读者提供实用的指导和见解,帮助他们在不断变化的技术环境中保持竞争力。
11 0