在 .NET 8.0 中使用 xUnit 进行数据驱动测试

news2024/11/11 7:21:59

在这里插入图片描述

1. 前言

xUnit是一个功能强大且易于使用的单元测试框架。在.NET开发中,单元测试是非常重要的一部分,它可以帮助我们确保代码的正确性和可靠性。使用xUnit可以帮助我们编写更高效、更有效的单元测试,并提高代码质量和可维护性。
在这里插入图片描述

2. 特性

xUnit支持多种.NET平台,例如.NET Core、.NET Framework和Mono。xUnit有许多优秀的特性和功能,以下是xUnit的一些主要特性:

  1. 数据驱动测试:xUnit支持使用InlineData、ClassData和MemberData等特性进行数据驱动测试。这些特性允许你为测试方法提供不同的输入数据,简化了测试代码的编写和维护。

  2. 异步测试:在异步编程模型中,xUnit支持异步测试。你可以使用async和await关键字来编写异步测试方法,并使用Assert等断言来验证异步操作的结果。

  3. 丰富的断言:xUnit提供了许多断言方法,用于比较预期结果和实际结果是否相等、是否为空等。这些断言方法可以帮助你编写更强大和灵活的单元测试。

  4. 多种输出格式:xUnit支持将测试结果输出为多种格式,例如XML、JSON、HTML和PlainText。你可以选择最适合你的应用程序或工具的格式。

  5. 灵活的测试配置:xUnit提供了许多配置选项,例如超时时间、并发级别、输出目录等。你可以根据自己的需要进行配置,以便更好地管理测试。

  6. 扩展性:xUnit提供了许多扩展点,例如TestOutputHelper、ITestCollectionOrderer等。你可以使用这些扩展点来自定义测试行为和结果。

  7. 支持.NET平台:xUnit支持多种.NET平台,例如.NET Core、.NET Framework和Mono。无论你使用哪个平台,都可以使用xUnit进行单元测试。

在这里插入图片描述

3. 实战介绍

在这里插入图片描述
在 .NET 8 中使用 xUnit 进行数据驱动测试,能够系统地提供不同的输入数据并验证相应的预期结果,从而有效地测试代码。xUnit 提供了多种方法,例如 [InlineData]、[ClassData]、[MemberData] 和自定义数据源,允许使用多种方式对测试进行参数化。

xUnit 中的 [InlineData] 属性支持直接在测试方法中提供特定的测试用例,有助于简洁明了的参数化。但是,它的局限性在于需要编译时常量值,并且可能不适合大型或动态数据集。另一方面,[ClassData] 和 [MemberData] 属性允许从方法或类提供数据,从而实现更复杂的测试数据生成,从而提供了更大的灵活性。然而,与 [InlineData] 相比,这些方法可能需要更高的设置复杂性,并且需要额外的类或方法来提供数据。

下面给出了我用来准备示例项目的工具。
在这里插入图片描述

  • VS 2022 社区版版本 17.8
  • .NET 8.0
  • XUnit

在这里插入图片描述

第1节.使用 [InlineData] 进行参数化测试

[InlineData] 允许将特定测试用例作为测试方法签名中的属性提供,从而实现一种简单简洁的参数化测试的方法。局限性在于:

  • 仅限于测试用例的编译时常量值。
  • 不适用于大型数据集或需要动态生成测试用例的场景。
public class CalculatorTestWithInlineData
{
    [Theory]
    [InlineData(2, 3, 5)] // Test case 1
    [InlineData(-1, 1, 0)] // Test case 2
    public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
    {
        // Arrange
        Calculator calculator = new Calculator();
        // Act
        int result = calculator.Add(a, b);
        // Assert
        Assert.Equal(expected, result);
    }
}

结果
在这里插入图片描述

第2节.使用 [ClassData] 和 [MemeberData]

[ClassData] 和 [MemberData] 属性允许从类或方法提供测试数据,从而便于为测试生成更复杂的数据。局限性在于:

  • 与 [InlineData] 相比,设置更复杂。
  • 需要创建其他类或方法来提供测试数据。

[ClassData] 的示例

using System.Collections;

namespace DataDrivenWithXUnit.Test
{
    public class CalculatorTestWithClassData
    {
        [Theory]
        [ClassData(typeof(TestClassDataGenerator))]
        public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
        {
            // Arrange
            Calculator calculator = new Calculator();
            // Act
            int result = calculator.Add(a, b);
            // Assert
            Assert.Equal(expected, result);
        }
    }

    public class TestClassDataGenerator : IEnumerable<object[]>
    {
        public IEnumerator<object[]> GetEnumerator()
        {
            yield return new object[] { 2, 3, 5 }; // Test case 1
            yield return new object[] { -1, 1, 0 }; // Test case 2
        }

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}

结果
在这里插入图片描述

[MemberData] 的示例

使用 [MemberData] 的 [Theory] 测试允许在单个测试方法中测试多个数据集,从而能够测试各种场景。局限性在于:

  • 测试的可读性可能会随着许多组合而降低。
  • 在处理多种组合时,复杂性会增加,这可能会使调试具有挑战性。
using System.Collections;

namespace DataDrivenWithXUnit.Test
{
    public class CalculatorTestWithMemberData
    {
        [Theory]
        [MemberData(nameof(CombinedData))]
        public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
        {
            // Arrange
            Calculator calculator = new Calculator();

            // Act
            int result = calculator.Add(a, b);

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


        public static IEnumerable<object[]> CombinedData()
        {
            var testData = new List<object[]>
            {
                new object[] { 2, 3, 5 },   // Test case 1: a=2, b=3, expected=5
                new object[] { -1, 1, 0 }  // Test case 2: a=-1, b=1, expected=0
            };

            return testData;
        }

    }
}

结果
在这里插入图片描述

第3节.创建自定义数据源

实现 IDataAttribute 的自定义数据源支持灵活和自定义的测试数据生成,提供内置属性之外的增强功能。局限性在于:

需要了解和实现 IDataAttribute 接口,这可能涉及更陡峭的学习曲线。
管理自定义数据源时的维护开销。

using System.Reflection;
using Xunit.Sdk;

namespace DataDrivenWithXUnit.Test
{
    public class CalculatorTestWithCustomAttributeData
    {
        [Theory]
        [CustomData]
        public void Add_ShouldReturnCorrectSum_CustomData(int a, int b, int expected)
        {
            // Arrange
            Calculator calculator = new Calculator();

            // Act
            int result = calculator.Add(a, b);

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


    }

    public class CustomDataAttribute : DataAttribute
    {
        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            // Custom data generation logic
            yield return new object[] { 2, 3, 5 }; // Test case 1
            yield return new object[] { -1, 1, 0 }; // Test case 2
        }
    }

}

结果
在这里插入图片描述

第4节.外部数据源

利用 JSON、CSV 或数据库等外部数据源,使测试能够使用来自外部文件或数据库的数据。局限性在于

  • 可能会引入对外部资源的依赖关系,从而导致潜在的测试不稳定。
  • 文件或数据访问可能会导致测试执行时间变慢。
using Newtonsoft.Json;

namespace DataDrivenWithXUnit.Test
{
    public class CalculatorTestWithExternalData
    {
        private static string TestDataFilePath = Path.Combine(Directory.GetCurrentDirectory(), "ExternalData.json");

        [Theory]
        [MemberData(nameof(GetCalculatorTestDataFromJson))]
        public void Add_ShouldReturnCorrectSum_CustomData(int a, int b, int expected)
        {
            // Arrange
            Calculator calculator = new Calculator();
            // Act
            int result = calculator.Add(a, b);
            // Assert
            Assert.Equal(expected, result);
        }

        public static IEnumerable<object[]> GetCalculatorTestDataFromJson()
        {
            if (!File.Exists(TestDataFilePath))
            {

                throw new FileNotFoundException($"File not found: {TestDataFilePath}");
            }

            string jsonContent = File.ReadAllText(TestDataFilePath);
            var testData = JsonConvert.DeserializeObject<List<TestData>>(jsonContent)?? new List<TestData>();

            foreach (var data in testData)
            {
                yield return new object[]
                {
                data.a,
                data.b,
                data.expected,
                };
            }
        }
    }

    public class TestData
    {
        public int a { get; set; }
        public int b { get; set; }
        public int expected { get; set; }
    }
}

结果
在这里插入图片描述

第5节.策略和最佳实践

1. 数据独立性

  • 将数据与测试分开:保持测试逻辑和测试数据之间的分离。这种分离有助于管理对数据的更改,而不会影响测试代码。
  • 集中测试数据:考虑集中测试数据,以避免测试套件之间出现重复和不一致。

2. 可维护性和可读性

  • 有意义的测试数据:使用描述性和有意义的数据值,使测试易于理解。避免晦涩或晦涩难懂的测试数据。
  • 清晰的测试用例描述:确保测试用例的意图从其描述或名称中清晰可见,从而更容易识别每个测试的目的。

3. 可扩展性和灵活性

  • 动态测试数据生成:如果可能,请使用允许动态生成测试数据的机制来处理大型数据集或动态更改的数据。
  • 参数化数据:选择参数化测试,无需修改现有测试方法即可添加新的测试用例。

4. 保持测试的一致性和可靠性

  • 避免硬编码值:避免在测试中对值进行硬编码。利用常量、变量或数据源来存储和重用值。
  • 定期数据更新:确保定期更新数据源以反映应用程序行为的变化。

5. 测试套件性能

  • 数据粒度:考虑测试数据的粒度。极其精细的测试数据可能会导致测试执行时间变慢。
  • 数据过滤和子集测试:在处理大型数据集时,有选择地测试子集以涵盖特定场景,而不是测试每个数据点。

6. 协作和文档

  • 文档:记录数据源、数据格式以及如何参数化测试。本文档有助于团队成员之间的协作和理解。
  • 协作数据审查:鼓励团队成员之间协作以审查和维护测试数据,确保其准确性和相关性。

7. 错误处理和报告

  • 处理无效数据:对测试中意外或无效的数据输入实施错误处理。确保清晰地报告失败的测试,并提供有关导致失败的数据的相关信息。

8. 测试边缘情况和边界值

  • 包括边缘情况:确保测试数据包括边界值、边缘情况和极端情况,以验证极端条件下的系统行为。
  • 不同的数据范围:在一系列数据值中进行测试,以验证不同输入范围内的系统行为。

9. 持续改进

  • 反馈循环:鼓励来自测试体验的反馈,以迭代方式提高测试数据质量和测试覆盖率。
  • 重构测试:定期重构测试以提高可维护性、可读性和效率,包括优化测试数据结构。

4. 总结:

通过考虑这些策略和最佳做法,开发人员可以在 .NET Core 项目中有效地利用 xUnit 中的数据驱动测试,确保可靠且可靠的测试套件,从而在各种方案和条件下有效地验证应用程序功能。

5. 参考文档

  • 官方网站:https://xunit.net/
  • 源码网站:https://github.com/xunit/xunit
  • 案例网站:https://github.com/xunit/samples.xunit

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2033127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git-GitLab-Jenkins结合

目录 1.Git-GitLab-Jenkins结合2. 在pycharm配置git3. 实现提交代码后触发自动化测试&#xff08;1&#xff09;打开gitlab&#xff08;2&#xff09;Jenkins配置Git&#xff08;3&#xff09;选择需要的远程仓库 4.报告存在问题&#xff1a;5.也可以在Jenkins中设置定时触发&a…

OpenCV图像滤波(10)Laplacian函数的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 功能描述 计算图像的拉普拉斯值。 该函数通过使用 Sobel 运算符计算出的 x 和 y 的二阶导数之和来计算源图像的拉普拉斯值&#xff1a; dst Δ src ∂…

Elasticsearch:引入 Serverless 精简索引分片

作者&#xff1a;来自 Elastic Tanguy Leroux 在本文中&#xff0c;我们将介绍 Elasticsearch 的精简索引分片&#xff08;thin indexing shards&#xff09;&#xff0c;这是我们为 Elastic Cloud Serverless 开发的一种新型分片&#xff0c;允许将 Elasticsearch 索引存储在云…

大数据技术现场工程师特色实训室解决方案

一、引言 在大数据时代背景下&#xff0c;数据已成为新的生产要素&#xff0c;驱动着各行各业的创新发展。面对这一趋势&#xff0c;市场对于既掌握大数据理论知识又具备实战能力的大数据技术人才的需求急剧增加。为了应对这一挑战&#xff0c;唯众精心设计了一套全面的大数据…

国产 麒麟 ARM 环境编译 RocketMQ-Client-CPP

1.环境 系统版本&#xff1a;Linux 5.4.18-87.76-generic KYLINOS SMP Thu Aug 31 09:05:44 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux GCC: gcc (Ubuntu 9.3.0-10kylin2) 9.3.0 G: g (Ubuntu 9.3.0-10kylin2) 9.3.0 RocketMQ服务端版本&#xff1a;5.1.1 RocketMQ-cpp …

修改docker的/var/lib/docker/overlay2储存路径

目录 目录 1.准备新的存储位置 1.创建新的存储目录 2.修改目录权限 2. 配置 Docker 使用新的存储位置 1.停止 Docker 服务 2.编辑 Docker 配置文件 3.迁移现有 Docker 数据 1.将现有的 Docker 数据从系统盘移动到新目录 2.启动 Docker 服务 3. 验证更改 4. 清理旧的…

RAGFlow v0.9 重磅升级,支持 GraphRAG,开启下一代 RAG 之旅!

一、引言 前面我们介绍过很多的关于大模型和RAG相关的技术&#xff0c;通过其关注程度足以看到市场上对RAG框架和成熟产品的迫切需求&#xff0c;因为想要个人独立从0开始实现一个RAG产品并非易事&#xff0c;虽然有相当多的RAG或者知识库开源产品&#xff0c;大部分其实很难应…

使用 Elasticsearch RestHighLevelClient 进行查询

Elasticsearch 提供了多种客户端库&#xff0c;以方便不同编程语言的用户进行操作。其中&#xff0c;Java 的 RestHighLevelClient 是 Elasticsearch 官方推荐的客户端之一&#xff0c;用于 Java 应用程序中。本文将介绍如何使用 Java 的 RestHighLevelClient 进行 Elasticsear…

Docker Hub 镜像代理加速

因为未知原因&#xff0c;docker hub 已经不能正常拉取镜像&#xff0c;可以使用以下代理服务来进行&#xff1a; "https://docker.m.daocloud.io", "https://noohub.ru", "https://huecker.io", "https://dockerhub.timeweb.cloud"…

深入浅出消息队列----【顺序消息的实现原理】

深入浅出消息队列----【顺序消息的实现原理】 何为顺序发消息的顺序性存储消息的顺序性消费消息的顺序性顺序消息消费的三把锁第一把锁&#xff1a;分布式锁第二把锁&#xff1a;Synchronized第三把锁&#xff1a;ReentrantLock 本文仅是文章笔记&#xff0c;整理了原文章中重要…

vue3仿飞书头像,根据不同名称生成不同的头像背景色

效果展示&#xff1a; 传递三个参数&#xff1a; name&#xff1a;要显示的名称&#xff1b;size&#xff1a;头像的大小&#xff1b;cutNum&#xff1a;分割当前名称的最后几位数&#xff1b; 代码如下&#xff1a; <template><div:style"{color: #fff,borde…

VMware虚拟机下安装Ubuntu22.04以及汉化配置保姆级教程

目录 一.VMware和Ubuntu下载 二.在VMware中创建Ubuntu 1.点击 创建新的虚拟机 2.选择典型 3.选择Ubuntu镜像包&#xff08;自定义存放的位置&#xff09; 4.创建个人信息&#xff08;密码一定要牢记&#xff09; 5.选择虚拟机的安装位置 6.其他配置项&#xff08;默认下…

在数字浪潮中扬帆远航,软件行业就业前景如何?

随着数字化转型的加速和信息技术的广泛应用&#xff0c;对于软件开发人员的需求持续增长。不仅传统IT企业需要大量的软件开发人才&#xff0c;各行各业的企业也普遍需要自主研发软件以满足其业务需求。对于具备较好的学习能力和适应能力的人来说&#xff0c;这个行业提供了更多…

jenkins一键推送到远程服务器并用docker容器启动

1.安装jenkins 我后端使用的是宝塔面板来安装的容器化jenkins,要选中允许外部访问&#xff0c;安装完之后没有那个选项了&#xff0c;一开始安装的时候要选中不使用域名和后面的允许外部访问。Jenkins 版本为&#xff1a; 2.462.1 2.配置Jenkins 2.1 Git plugin 安装完毕之…

江新安教授受邀引正基因进行《制药行业研发项目管理》培训

近日&#xff0c;科济管线创始人江新安教授应赛柏蓝邀请为北京引正基因科技有限公司&#xff08;简称引正基因&#xff09;进行《研发项目管理》授课。为提高项目管理水平&#xff0c;加强研发项目相关人员的管理能力&#xff0c;掌握研发项目管理技能与工具&#xff0c;江新安…

AI招聘在人才盘活中的作用:开启智慧人力新篇章

一、引言&#xff1a;AI赋能招聘新纪元 在21世纪的今天&#xff0c;随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到社会经济的各个角落&#xff0c;其中&#xff0c;人力资源管理领域也不例外。AI技术的引入&#xff0c;不仅颠覆了传统的招聘模…

代码规范 —— QMQ 开发规范

优质博文&#xff1a;IT-BLOG-CN 一、代码规范 【1】消费者必须以Consumer结尾&#xff0c;生产者必须以Producer结尾。 【2】选择合适的消费模式&#xff1a;根据业务判断消费模式是集群模式还是广播模式&#xff0c;具体为&#xff1a;MessageConsumerProvider.addListene…

R的行和列命名和类型的转换

下面内容摘录自&#xff1a; 4章8节&#xff1a;用R做数据重塑&#xff0c;行列命名和数据类型转换-CSDN博客 欢迎订阅我们专栏 一、行和列命名 在数据科学和统计分析中&#xff0c;命名是组织和管理数据的一个重要部分。尤其是在处理复杂的多维数据集时&#xff0c;为行和列命…

FPGA知识基础之--FIFO ip核的使用以及实例化clocking wizard ip产生一个异步FIFO,附RTL和仿真代码

目录 一、FIFO简介1.定义2.特点3.分类4.FIFO在FPGA中的应用 二、实验任务三、FIFO IP核1.接口2.写时序3.读时序1.Standara2 .FWFT 四、vivado设置五、程序设计1.模块2.时序3.异步信号传输4.RTL代码 五、仿真1.Testbench代码2.波形 一、FIFO简介 1.定义 FIFO是一种先进先出的数…

电能表在企业能源管理中的作用

电能表在企业能源管理中扮演着至关重要的角色&#xff0c;它不仅是能源计量的基础工具&#xff0c;更是企业实现高效能源管理、降低能源成本、提高竞争力的关键所在。 一、精确计量与实时监测 电能表作为能源计量的基础工具&#xff0c;其首要作用是实现电能的精确计量。相比…