首页 > 其他分享 >单元测试篇2-TDD三大法则解密

单元测试篇2-TDD三大法则解密

时间:2024-04-07 09:12:55浏览次数:23  
标签:代码 单元测试 TDD 失败 测试 编写 三大

引言

在我们上一篇文章了解了单元测试的基本概念和用法之后,今天我们来聊一下 TDD(测试驱动开发)

测试驱动开发 (TDD)

测试驱动开发英文全称是Test Driven Development 简称 TDD。

根据 UncleBob 的 TDD 描述总结

我们先创建一个测试项目

直接在 VS 创建即可,可以参考上一篇文章的创建过程

The Three Laws of TDD.

  • You are not allowed to write any production code unless it is to make a failing unit test pass.
  • You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  • You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

这是本文的描述的三个 TDD 开发的原则,它确保了代码的质量和可维护性。

下面对这三条内容做详细的解释

  • 第一条规则指出 不允许编写任何的生产代码,除非是在让单元测试通过时。
    • 简单理解就是在编写任何实际的业务逻辑代码之前,必须先编写一个或者多个单元测试,这些单元测试因为没有实现所以会失败,有了失败的单元测试之后我们才可以去在生产代码中实现业务逻辑
  • 第二条规则指出 不允许编写比失败所需更多的单元测试代码;编译失败也是失败:

    • 这可以理解为 在编写单元测试时,应该只编写足够使测试失败的最小代码量。这样,可以立即知道新写的生产代码是否解决了问题。编译失败同样被视为测试失败,因为编译不通过意味着代码无法运行。

那一个我们上一章节的一个数学计算类的例子


namespace dotNetParadise_TDD.Test;

public class MathCalculatorTests
{
    [Fact]
    public void Add_TwoNumbers_ReturnSum()
    {
        // Arrange
        var calculator = new MathCalculator();

        // Act
        var result = calculator.Add(3, 5);

        // Assert
        Assert.Equal(8, result);
    }
}

因为我们没有 MathCalculator 这个类的实现所以,代码会编译失败。

image

在这个示例中,我们展示了如何编写一个简单的单元测试,测试 Calculator 类的 Add 方法是否能够正确地将两个数字相加并返回正确的结果。根据 TDD 原则,我们只编写了必要部分的代码来测试这个功能,并且在这个阶段测试应该会失败,因为 Add 方法还未实现。编译失败也会被视为测试失败,这强调了编写足够简洁和精确的单元测试的重要性,符合第二条准则。

  • 第三条规则指出 不允许编写比通过单个失败单元测试所需更多的生产代码
    可以理解为在编写生产代码时,只需编写足够让失败的单元测试通过的代码,而不是一次性编写完整的功能。这有助于保持代码的小步前进,并且每次更改都有明确的测试验证。

现在把MathCalculator类中增加一个参数*2 即翻倍的一个功能

第一步编写一个单元测试方法,

    [Fact]
    public void DoubleNumber_WhenGivenSingleNumber_ReturnsDouble()
    {
        // Arrange
        var calculator = new MathCalculator();

        // Act
        var result = calculator.DoubleNumber(2);

        // Assert
        Assert.Equal(4, result);
    }

第二步 编写足够让失败的单元测试通过的代码

namespace dotNetParadise_TDD.Test;

public class MathCalculator
{
    public int DoubleNumber(int number)
    {
        throw new NotImplementedException();
    }
}

接下来运行单元测试

 dotNetParadise_TDD.Test.MathCalculatorTests.DoubleNumber_WhenGivenSingleNumber_ReturnsDouble
   源: MathCalculatorTests.cs 行 20
   持续时间: 371 毫秒

  消息: 
System.NotImplementedException : The method or operation is not implemented.

  堆栈跟踪: 
MathCalculator.DoubleNumber(Int32 number) 行 7
MathCalculatorTests.DoubleNumber_WhenGivenSingleNumber_ReturnsDouble() 行 26
RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

结果和预期一样,测试没有成功

image

现在来重构一下这个方法

    public int DoubleNumber(int number)
    {
        //throw new NotImplementedException();
        return 2 * number;
    }

再次运行单元测试

image

可以看到单元测试成功了!

TDD 开发流程图

最后

通常我们进行单元测试的时候都是先写业务逻辑,然后再单元测试,当系统业务逻辑变复杂之后可能会遗漏一些测试 CaseTDD 的出现就是解决这个问题,通过测试 Case 来写重构业务代码的模式。

这三个规则确保了 TDD 的核心循环:红(测试失败)、绿(测试通过)、重构。通过不断地重复这个过程,开发者能够编写出高质量、可测试、易于维护的代码。

本文完整源代码
image

标签:代码,单元测试,TDD,失败,测试,编写,三大
From: https://www.cnblogs.com/ruipeng/p/18118155

相关文章

  • 对比.Net平台下三大日志库:Serilog、log4net和NLog
    原文链接:Serilog,log4netandNLogComparison:LoggingLibrariesfor.NETApplications(bytehide.com)译者前言:最近在搭建一套自己用的后端开发的架构,涉及到日志系统的选型,一番检索下找到了这篇文章,还算比较新,翻译过来跟大家分享一下。这篇文章运用了大量的比喻,不知道各位是......
  • 三大平台威廉希尔伟德下实现混合编程
    Android和iOS开发都支持C++开发,可以一套代码多平台使用。同时C++难以反编译的特性也可以为Android开发带来代码的保密,另一native特性也可以提高代码的运行效率。一、为什么使用C/C++便于移植,用C/C++写得库可以方便在其他的平台上再次使用。代码的保护,由于java层代码很容易被......
  • 面向对象--三大特征--继承
    1.继承:继承是面向对象三大特征之一,可以让类与类之间产生子父的关系.2.继承的格式:Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立继承关系.publicclassStudentextendsPerson{}Studnet称为子类(派生类),Person称为父类(基类或者超类).3.使......
  • 面向对象--三大特征--多态
    1.什么是多台:同种类型,表现不同形态.2.多态的表现形式:父类类型对象名称=子类对象.3.多态的前提:a.有继承/实现关系;b.有父类引用指向子类对象;例如:Fu f=newZi();c.有方法重写.4,多态的好处:使用父类作为参数,可以接受所有子类对象,体现多态的扩展性和便利.......
  • 最大连续子数组和的单元测试
    (1)请从语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖五个覆盖标准中(条件组合覆盖难度较大,鼓励尝试,但请谨慎选择),任选一个标准设计测试用例(2)请利用自动测试工具对程序进行测试(3)请将程序运行结果和自动测试分析结果截图粘贴到文档中为了求数组最大字段和,须定义......
  • 如何在vscode中为c#编写单元测试
    如何在vscode中为c#编写单元测试从零开始创建一个单元测试工程创建测试单元工程创建测试文件的方法和新建项目类似,都是使用dotnetnew命令。dotnetnewxunit为测试单元工程添加需要测试的工程的项目引用dotnetaddreference..\MyMath\MyMath.csproj文件的目录结构......
  • 软件测试和质量管理——实验3:单元测试
    《软件测试和质量管理》实验报告三一、目的和要求        1、掌握单元测试技术,并要求按照单元测试的要求设计测试用例;        2、掌握在Eclipse里进行Junit4测试的技术;        3、根据题目要求编写测试用例;        4、实验结果要求给出测......
  • 单元测试的思考与实践
    1.什么是单元测试通常来说单元测试,是一种自动化测试,同时包含一下特性:验证很小的一段代码(业务意义或者代码逻辑上不可再分割的单元),能够更准确的定位到问题代码的位置能够快速运行(单元测试的意义,在于快速且周期性的验证原有代码的准确性),提高项目开发效率以隔离的方式(isol......
  • .Net单元测试xUnit和集成测试指南(1)
    引言在现代化的软件开发中,单元测试和集成测试是确保代码质量和可靠性的关键部分。ASP.NETCore社区内提供了强大的单元测试框架,xUnit是其中之一,它提供了简单、清晰和强大的测试功能,编写单元测试有许多优点;有助于回归、提供文档及辅助良好的设计。下面几节我们来深入浅出探讨如......
  • 单元测试和系统测试的区别?
    一、概念:系统测试进行系统测试以检查软件或产品是否满足指定的要求。它由测试人员和开发人员共同完成。它包含系统测试和集成测试。它是通过更多的正面和负面的测试用例来完成的。单元测试单元测试是软件测试级别的类型,其中测试软件的每个单独组件。单元测试通常由开......