Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >.NET单元测试的艺术-3.测试代码

.NET单元测试的艺术-3.测试代码

作者头像
Edison Zhou
发布于 2018-08-20 09:49:14
发布于 2018-08-20 09:49:14
56200
代码可运行
举报
文章被收录于专栏:EdisonTalkEdisonTalk
运行总次数:0
代码可运行

开篇:上一篇我们学习单元测试和核心技术:存根、模拟对象和隔离框架,它们是我们进行高质量单元测试的技术基础。本篇会集中在管理和组织单元测试的技术,以及如何确保在真实项目中进行高质量的单元测试。

一、测试层次和组织

1.1 测试项目的两种目录结构

  (1)集成测试和单元测试在同一个项目里,但放在不同的目录和命名空间里。基础类放在单独的文件夹里。

  (2)集成测试和单元测试位于不同的项目中,有不同的命名空间。

实践中推荐使用第二种目录结构,因为如果我们不把这两种测试分开,人们可能就不会经常地运行这些测试。既然测试都写好了,为什么人们不愿意按照需要运行它们呢?一个原因是:开发人员有可能懒得运行测试,或者没有实践运行测试。

1.2 构建绿色安全区

  将集成测试和单元测试分开放置,其实就给团队的开发人员构建了绿色安全区,这个区只包含单元测试。

  因为集成测试的本质决定了它运行时间较长,开发人员很有可能每天运行多次单元测试,较少运行集成测试。

单元测试全部通过至少可以使开发人员对代码质量比较有信心,专注于提高编码效率。而且我们应该将测试自动化,编写每日构建脚本,并借助持续集成工具帮助我们自动执行这些脚本。

1.3 将测试类映射到被测试代码

  (1)将测试映射到项目

  创建一个测试项目,用被测试项目的名字加上后缀.UnitTests来命名。

  例如:Manulife.MyLibrary → Manulife.MyLibrary.UnitTests 和 Manulife.MyLibrary.IntegrationTests,这种方法看起来简单直观,开发人员能够从项目名称找到对应的所有测试。

  (2)将测试映射到类

  ① 每个被测试类或者被测试工作单元对应一个测试类:LogAnalyzer → LogAnalyzer.UnitTests

  ② 每个功能对应一个测试类:有一个LoginManager类,测试方法为ChangePassword(这个方法测试用例特别多,需要单独放在一个测试类里边) → 创建两个类 LoginManagerTests 和 LoginManagerTests-ChangePassword,前者只包含对ChangePassword方法的测试,后者包含该类其他所有测试。

  (3)将测试映射到具体的工作单元入口

  测试方法的命名应该有意义,这样人们可以很容易地找到所有相关的测试方法。

  这里,回归一下第一篇中提到的测试方法名称的规范,一般包含三个部分:[UnitOfWorkName]_[ScenarioUnderTest]_[ExpectedBehavior]

    • UnitOfWorkName  被测试的方法、一组方法或者一组类
    • Scenario  测试进行的假设条件,例如“登入失败”,“无效用户”或“密码正确”等
    • ExpectedBehavior  在测试场景指定的条件下,你对被测试方法行为的预期  

  示例:IsValidFileName_BadExtension_ReturnsFalse,IsValidFileName_EmptyName_Throws 等

1.4 注入横切关注点

  当需要处理类似时间管理、异常或日志的横切关注点时,使用它们的地方会非常多,如果把它们实现成可注入的,产生的代码会很容易测试,但却很难阅读和理解。这里我们来看一个例子,假设应用程序使用当前时间进行写日志,相关代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static class TimeLogger
    {
        public static string CreateMessage(string info)
        {
            return DateTime.Now.ToShortDateString() + " " + info;
        }
    }

  为了使这段代码容易测试,如果使用之前的依赖注入技术,那么我们需要创建一个ITimeProvider接口,还必须在每个用到DateTime的地方使用到这个接口。这样做非常耗时,实际上,还有更直接的方法解决这个问题。

Step1.创建一个名为SystemTime的定制类,在所有的产品代码里边使用这个定制类,而非标准的内建类DateTime。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public class SystemTime
    {
        private static DateTime _date;

        public static void Set(DateTime custom)
        {
            _date = custom;
        }

        public static void Reset()
        {
            _date = DateTime.MinValue;
        }

        public static DateTime Now
        {
            get
            {
                // 如果设置了时间,SystemTime就返回假时间,否则返回真时间
                if (_date != DateTime.MinValue)
                {
                    return _date;
                }
                return DateTime.Now;
            }
        }
    }

  阅读这段代码,其中有一个小技巧:SystemTime类提供一个特殊方法Set,它会修改系统中的当前时间,也就是说,每个使用这个SystemTime类的人看到的都是你指定的日期和时间。有了这样的代码,每个使用这个SystemTime类的人看到的都会是你指定的日期和时间。

Step2.在测试项目中使用SystemTime进行测试。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    [TestFixture]
    public class TimeLoggerTests
    {
        [Test]
        public void SettingSystemTime_Always_ChangesTime()
        {
            SystemTime.Set(new DateTime(2000, 1, 1));
            string output = TimeLogger.CreateMessage("a");

            StringAssert.Contains("2000/1/1", output);
        }

        /// <summary>
        /// 在每个测试结束时重置日期
        /// </summary>
        [TearDown]
        public void AfterEachTest()
        {
            SystemTime.Reset();
        }
    }

  在测试中,我们首先假定设置一个日期,然后进行断言。并且借助TearDown方法,确保当前测试不会改变其他测试的值

Note : 这样做的好处就在于不用注入一大堆接口,我们所付出的代价仅仅在于在测试类中加入一个简单的[TearDown]方法,确保当前测试不会改变其他测试的值。

1.5 使用继承使测试代码可重用

  推荐大家在测试代码中使用继承机制,通过实现基类,可以较好地展现面向对象的魔力。在实践中,一般有三种模式会被使用到:

  (1)抽象测试基础结构类模式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /// <summary>
    /// 测试类集成模式
    /// </summary>
    [TestFixture]
    public class BaseTestsClass
    {
        /// <summary>
        /// 重构为通用可读的工具方法,由派生类使用
        /// </summary>
        /// <returns>FakeLogger</returns>
        public ILogger FakeTheLogger()
        {
            LoggingFacility.Logger = Substitute.For<ILogger>();
            return LoggingFacility.Logger;
        }

        [TearDown]
        public void ClearLogger()
        {
            // 测试之间要重置静态资源
            LoggingFacility.Logger = null;
        }
    }

    [TestFixture]
    public class LogAnalyzerTests : BaseTestsClass
    {
        [Test]
        public void Analyze_EmptyFile_ThrowsException()
        {
            // 调用基类的辅助方法
            FakeTheLogger();

            LogAnalyzer analyzer = new LogAnalyzer();
            analyzer.Analyze("myemptyfile.txt");

            // 测试方法的其余部分
        }
    }

  使用此模式要注意继承最好不要超过一层,如果继承层数过多,不仅可读性急剧下降,编译也很容易出错。

  (2)测试类类模板模式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /// <summary>
    /// 测试模板类模式
    /// </summary>
    [TestFixture]
    public abstract class TemplateStringParserTests
    {
        [Test]
        public abstract void TestGetStringVersionFromHeader_SingleDigit_Found();
        [Test]
        public abstract void TestGetStringVersionFromHeader_WithMinorVersion_Found();
        [Test]
        public abstract void TestGetStringVersionFromHeader_WithRevision_Found();
    }

    [TestFixture]
    public class XMLStrignParserTests : TemplateStringParserTests
    {
        protected IStringParser GetParser(string input)
        {
            return new XMLStringParser(input);
        }

        [Test]
        public override void TestGetStringVersionFromHeader_SingleDigit_Found()
        {
            IStringParser parser = GetParser("<Header>1</Header>");

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual("1", versionFromHeader);
        }

        [Test]
        public override void TestGetStringVersionFromHeader_WithMinorVersion_Found()
        {
            IStringParser parser = GetParser("<Header>1.1</Header>");

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual("1.1", versionFromHeader);
        }

        [Test]
        public override void TestGetStringVersionFromHeader_WithRevision_Found()
        {
            IStringParser parser = GetParser("<Header>1.1.1</Header>");

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual("1.1", versionFromHeader);
        }
    }

  使用此模式可以确保开发者不会遗忘重要的测试,基类包含了抽象的测试方法,派生类必须实现这些抽象方法。

  (3)抽象测试驱动类模式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /// <summary>
    /// 抽象“填空”测试驱动类模式
    /// </summary>
    public abstract class FillInTheBlankStringParserTests
    {
        // 返回接口的抽象方法
        protected abstract IStringParser GetParser(string input);
        // 抽象输入方法(属性),为派生类提供特定格式的数据
        protected abstract string HeaderVersion_SingleDigit { get; }
        protected abstract string HeaderVersion_WithMinorVersion { get; }
        protected abstract string HeaderVersion_WithRevision { get; }
        // 如果需要,预先为派生类定义预期的输出
        public const string EXPECTED_SINGLE_DIGIT = "1";
        public const string EXPECTED_WITH_MINORVERSION = "1.1";
        public const string EXPECTED_WITH_REVISION = "1.1.1";

        [Test]
        public void TestGetStringVersionFromHeader_SingleDigit_Found()
        {
            string input = HeaderVersion_SingleDigit;
            IStringParser parser = GetParser(input);

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual(EXPECTED_SINGLE_DIGIT, versionFromHeader);
        }

        [Test]
        public void TestGetStringVersionFromHeader_WithMinorVersion_Found()
        {
            string input = HeaderVersion_WithMinorVersion;
            IStringParser parser = GetParser(input);

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual(EXPECTED_WITH_MINORVERSION, versionFromHeader);
        }

        [Test]
        public void TestGetStringVersionFromHeader_WithRevision_Found()
        {
            string input = HeaderVersion_WithRevision;
            IStringParser parser = GetParser(input);

            string versionFromHeader = parser.GetTextVersionFromHeader();
            Assert.AreEqual(EXPECTED_WITH_REVISION, versionFromHeader);
        }
    }

    public class DBLogStringParserTests : GenericParserTests<DBLogStringParser>
    {
        protected override string GetInputHeaderSingleDigit()
        {
            return "Header;1";
        }

        protected override string GetInputHeaderWithMinorVersion()
        {
            return "Header;1.1";
        }

        protected override string GetInputHeaderWithRevision()
        {
            return "Header;1.1.1";
        }
    }

  此模式在基类中实现测试方法,并提供派生类可以实现的抽象方法钩子。当然,只是大部分的测试代码在基类中,派生类也可以加入自己的特殊测试。

  此模式的要点在于:你不是具体地测试一个类,而是测试产品代码中的一个接口或者基类。

  当然,在.NET中我们也可以通过泛型来实现此模式,例如下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public abstract class GenericParserTests<T> where T : IStringParser // 01.定义参数的泛型约束
    {
        protected abstract string GetInputHeaderSingleDigit();
        protected abstract string GetInputHeaderWithMinorVersion();
        protected abstract string GetInputHeaderWithRevision();

        // 02.返回泛型变量而非接口
        protected T GetParser(string input)
        {
            // 03.返回泛型
            return (T)Activator.CreateInstance(typeof(T), input);
        }

        [Test]
        public void TestGetStringVersionFromHeader_SingleDigit_Found()
        {
            string input = GetInputHeaderSingleDigit();
            T parser = GetParser(input);

            bool result = parser.HasCorrectHeader();
            Assert.AreEqual(false, result);
        }

        [Test]
        public void TestGetStringVersionFromHeader_WithMinorVersion_Found()
        {
            string input = GetInputHeaderWithMinorVersion();
            T parser = GetParser(input);

            bool result = parser.HasCorrectHeader();
            Assert.AreEqual(false, result);
        }

        [Test]
        public void TestGetStringVersionFromHeader_WithRevision_Found()
        {
            string input = GetInputHeaderWithRevision();
            T parser = GetParser(input);

            bool result = parser.HasCorrectHeader();
            Assert.AreEqual(false, result);
        }
    }

    public class DBLogStringParserTests : GenericParserTests<DBLogStringParser>
    {
        protected override string GetInputHeaderSingleDigit()
        {
            return "Header;1";
        }

        protected override string GetInputHeaderWithMinorVersion()
        {
            return "Header;1.1";
        }

        protected override string GetInputHeaderWithRevision()
        {
            return "Header;1.1.1";
        }
    }

二、优秀单元测试的支柱

  要编写优秀的单元测试,它们应该同时具有 可靠性可维护性可读性

2.1 编写可靠的测试

  一个可靠的测试能让你觉得自己对事态了如指掌,能够从容应对。以下是一些指导原则和技术:

  (1)决定何时删除或修改测试

  一旦测试写好并通过,通常我们不应该修改或删除这些测试,因为它们是我们得绿色保护网。但是,有时候我们还是需要修改或者删除测试,所以需要理解什么情况下修改或删除测试会带来问题,什么情况下又是合理的。一般来说,如果有产品缺陷、测试缺陷、语义或者API更改或者是由于冲突或无效测试,我们需要修改和删除测试代码。

  (2)避免测试中的逻辑

  随着测试中逻辑的增多,出现测试缺陷的几率就会呈现指数倍的增长。如果单元测试中包含了下列语句就是包含了不应该有的逻辑:

  • switch、if或else语句;
  • foreach、for或while循环;

  这种做法不值得推荐,因为这样的测试可读性较差,也比较脆弱。通常来说,一个单元测试应该是一系列方法的调用和断言,但是不包含控制流程语句,甚至不应该将断言语句放在try-catch中

  (3)只测试一个关注点

  如果我们的单元测试对多个对象进行了断言,那么这个测试有可能测试了多个关注点。在一个单元测试中验证多个关注点会使得事情变得复杂,却没有什么价值。你应该在分开的、独立的单元测试中验证多余的关注点,这样才能发现真正失败的地方。

  (4)把单元测试和集成测试分开

  掐面讨论了测试的绿色安全区,我们需要的就是准备一个单独的单元测试项目,项目中仅包含那些在内存中运行,结果稳定,可重复执行的测试。

  (5)用代码审查确保代码覆盖率

  如果覆盖率低于20%,说明我们缺少很多测试,我们不会知道下一个开发人员将怎么修改我们得代码。如果没有回失败的测试,可能就不会发现这些错误。

2.2 编写可维护性的测试

  可维护性是大多数开发者在编写单元测试时面对的核心问题之一。为此我们需要:

  (1)只测试公共契约

  (2)删除重复测试(去除重复代码)

  (3)实施测试隔离

  测试隔离的基本概念是:一个测试应该总是在它自己的小世界中运行,与其他类似或不同的工作的测试隔离,甚至不知道其他测试的存在

2.3 编写可读性的测试

  不可读的测试几乎没有任何意义,它是我们向项目的下一代开发者讲述的故事,帮助开发者理解一个应用程序的组成及其开端。

  (1)单元测试命名

  这个前面我们讨论过,应该包括三部分:被测试方法名_测试场景_预期行为,如果开发人员都是用这种规范,其他的开发人员就能很容易进入项目,理解测试。

  (2)变量命名

  通过合理命名变量,你可以确保阅读测试的人可以尽快地理解你要验证什么(相对于理解产品代码中你想要实现什么)。请看下面的一个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    [Test]
    public void BadlyNameTest()
    {
        LogAnalyzer log = new LogAnalyzer();
        int result = log.GetLineCount("abc.txt");

        Assert.AreEqual(-100, result);
    }

    [Test]
    public void GoodNameTest()
    {
        LogAnalyzer log = new LogAnalyzer();
        int result = log.GetLineCount("abc.txt");
        const int COULD_NOT_READ_FILE = -100;

        Assert.AreEqual(-COULD_NOT_READ_FILE, result);
    }

  经过改进后,我们会很容易理解这个返回值的意义。

  (3)有意义的断言

  只有当测试确实需要,并且找不到别的办法使测试更清晰时,你才应该编写定制的断言信息。编写好的断言信息就像编写好的异常信息,一不小心就会犯错,使读者产生误解,浪费他们的时间。

  (4)断言和操作分离

  为了可读性,请不要把断言和方法调用写在同一行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 断言和操作写在了同一行
    Assert.AreEqual(-COULD_NOT_READ_FILE, log.GetLineCount("abc.txt"));

三、小结

  这一篇我们学习了:

  • 尽量将测试自动化,尽可能多次地运行测试,尽可能持续地进行产品交付;
  • 把集成测试和单元测试分开,为整个团队构建一个绿色安全区,该区域中所有的测试都必须通过;
  • 按照项目和类型组织测试,把测试分别放在不同的目录、文件夹或者命名空间中;
  • 使用测试类层次,对一个层次中相关的几个类进行同一组测试,或者对共享一个通用接口或者基类的类型进行同一组测试;
  • 优秀单元测试具有三大支柱:可读性、可维护性与可靠性,它们相辅相成。
  • 如果人们能读懂你的测试,就能理解和维护测试,如果测试能够通过,它们也会信任测试。一旦实现这个目标,你就能知道系统是否正常工作,具有了处理变更和在需要时修改代码的能力;

附件下载

  本系列文章的示例代码:点此下载

参考资料

  (1)Roy Osherove 著,金迎 译,《单元测试的艺术(第2版)》

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-05-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
.NET单元测试的艺术-1.入门
开篇:最近在看Roy Osherove的《单元测试的艺术》一书,颇有收获。因此,将其记录下来,并分为四个部分分享成文,与各位Share。本篇作为入门,介绍了单元测试的基础知识,例如:如何使用一个测试框架,基本的自动化测试属性等等,还有对应的三种测试类型。相信你可以对编写单元测试从一无所知到及格水平,这也是原书作者的目标。
Edison Zhou
2018/08/21
2.2K0
.NET单元测试的艺术-1.入门
.NET单元测试的艺术-2.核心技术
开篇:上一篇我们学习基本的单元测试基础知识和入门实例。但是,如果我们要测试的方法依赖于一个外部资源,如文件系统、数据库、Web服务或者其他难以控制的东西,那又该如何编写测试呢?为了解决这些问题,我们需要创建测试存根、伪对象及模拟对象。这一篇中我们会开始接触这些核心技术,借助存根破除依赖,使用模拟对象进行交互测试,使用隔离框架支持适应未来和可用性的功能。
Edison Zhou
2018/08/20
1.7K0
.NET单元测试的艺术-2.核心技术
重温《单元测试的艺术》,总结常用知识点
前几个月重温了单元测试的艺术。毕竟是14年的书内容有点旧,于是试着结合书中的内容和一些新的知识点写进这篇文章,希望对自己及各位读者有帮助。
dino.c
2019/07/30
1.6K0
重温《单元测试的艺术》,总结常用知识点
C# 单元测试框架 NUnit 一分钟浅谈
在软件开发过程中,单元测试是一种非常重要的质量保证手段。它可以帮助开发者验证代码的功能是否按预期工作,及时发现并修复错误。NUnit 是一个广泛使用的 .NET 单元测试框架,本文将从基础到进阶,介绍如何使用 NUnit 进行单元测试,并探讨一些常见的问题和易错点。
Jimaks
2024/10/30
3080
【单元测试】--编写单元测试
这是一个简单的NUnit单元测试的示例,展示了如何创建测试项目,编写测试用例,运行测试以及查看测试结果。随着你的项目复杂性的增加,你可以编写更多的测试用例来确保你的代码按预期工作。
喵叔
2023/10/22
5830
.NET重构—单元测试的代码重构
阅读目录: 1.开篇介绍 2.单元测试、测试用例代码重复问题(大量使用重复的Mock对象及测试数据) 2.1.单元测试的继承体系(利用超类来减少Mock对象的使用) 2.1.1.公用的MOCK对象
王清培
2018/01/08
1.3K0
.NET重构—单元测试的代码重构
ASP.NET MVC编程——单元测试
1自动化测试基本概念 自动化测试分为:单元测试,集成测试,验收测试。 单元测试 检验被测单元的功能,被测单元一般为低级别的组件,如一个类或类方法。 单元测试要满足四个条件:自治的,可重复的,独立的,快速的。 自治的是指:关注于验证某个单一功能,例如只关注于类的某个方法的功能。 可重复的是指:无论何时允许同一段测试代码都应该得到相同的结果。 独立的是指:不依赖与其他任何系统或单元测试。 快速的是指:所有测试都应快速地完成, 集成测试 验证两个或多个组件之间的交互。 验收测试 确保已构建的系统实现了既定的全部功
甜橙很酸
2018/04/17
2.2K0
ASP.NET MVC编程——单元测试
【单元测试】--单元测试最佳实践
编写单元测试代码时,遵循一致的风格和最佳实践是非常重要的,因为它有助于提高代码的可读性、可维护性和可靠性。以下是一些常见的单元测试代码风格和最佳实践:
喵叔
2023/10/22
7820
C#中的单元测试
C#程序可以使用NUnit框架进行单元测试,NUnit是.NET语言的一个测试框架,和Java语言的JUnit同属于XUnit。
卡尔曼和玻尔兹曼谁曼
2019/01/25
2.3K0
使用Visual Studio 2013进行单元测试--初级篇
1.打开VS2013 --> 新建一个项目。这里我们默认创建一个控制台项目。取名为UnitTestDemo 2.在解决方案里面新增一个单元测试项目。取名为UnitTestDemoTest 创建完毕后项
庞小明
2018/03/09
1.9K0
使用Visual Studio 2013进行单元测试--初级篇
C#的MSTest, NUnit, xUnit
在C#开发中,单元测试是确保代码质量和可靠性的关键环节。MSTest、NUnit和xUnit是.NET生态中最受欢迎的三大单元测试框架。它们各有特点,适用于不同的开发环境和需求。本文将对这三个框架进行深入解析,探讨它们的核心功能、使用场景、安装配置以及API概览。
Michel_Rolle
2024/10/09
2.8K0
ABP入门系列(11)——编写单元测试
源码路径:Github-LearningMpaAbp 1. 前言 In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operatin
圣杰
2018/01/11
1.8K0
ABP入门系列(11)——编写单元测试
【单元测试】--工具与环境
JUnit 是一个广泛用于 Java 程序开发的开源测试框架。它是单元测试的标准工具之一,用于编写和运行测试用例,以确保 Java 程序的各个组件按预期工作。以下是一些关键特点和概念,来介绍 JUnit:
喵叔
2023/10/22
6280
.NET Core 3.0 单元测试与 Asp.Net Core 3.0 集成测试
相信大家在看到单元测试与集成测试这个标题时,会有很多感慨,我们无数次的在实践中提到要做单元测试、集成测试,但是大多数项目都没有做或者仅建了项目文件。这里有客观原因,已经接近交付日期了,我们没时间做白盒测试了。也有主观原因,面对业务复杂的代码我们不知道如何入手做单元测试,不如就留给黑盒测试吧。但是,当我们的代码无法进行单元测试的时候,往往就是代码开始散发出坏味道的时候。长此以往,将欠下技术债务。在实践过程中,技术债务常常会存在,关键在于何时偿还,如何偿还。
李明成
2020/02/12
2.4K0
5 分钟 .NET 单元测试极简入门
为什么要花时间写单元测试?我直接让测试团队人肉测试,然后直接上生产,有什么问题吗?
郑子铭
2023/08/30
5200
5 分钟 .NET 单元测试极简入门
【Unity游戏开发】浅谈Unity游戏开发中的单元测试
  单元测试定义:单元测试在传统软件开发中是非常重要的工具,它是指对软件中的最小可测试单元进行检查和验证,一般情况下就是对代码中的一个函数去进行验证,检查它的正确性。一个单元测试是一段自动化的代码,这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行检验。单元测试使用单元测试框架编写,并要求单元测试可靠、可读并且可维护。只要产品代码不发生变化,单元测试的结果是稳定的。(百度的)
马三小伙儿
2018/09/12
3K0
【Unity游戏开发】浅谈Unity游戏开发中的单元测试
ASP.NET Core 单元测试:如何 Mock HttpClient.GetStringAsync()
在 ASP.NET Core 单元测试中模拟HttpClient.GetStringAsync() 的技巧。
Edi Wang
2021/05/27
1.4K0
单元测试一篇汇总
本文只对单元测试进行介绍,主要介绍如何在Android Studio下进行单元测试,单元测试使用的测试框架为JUnit
全干程序员demo
2024/10/11
2770
Asp.Net WebApi 调试利器“单元测试”
当我们编辑好一个WebApi应用程序后,需要对该Api接口进行调试,传统的调试办法是在方法内设置断点,然后用PostMan等http工具模拟访问进行查看WebAPI的运行情况,但这种除了效率较低还进行
码农阿宇
2018/04/18
2.3K0
Asp.Net WebApi 调试利器“单元测试”
单元测试的五个主要准则
自动化测试是所有大型软件项目不可或缺的一部分。它是提高质量、生产力和灵活性的一种手段。因此,对系统架构进行合理地设计以便利后续的开发和自动化测试变得至关重要。
肉眼品世界
2021/01/05
1.2K0
相关推荐
.NET单元测试的艺术-1.入门
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验