.net持续集成测试篇之Nunit参数化测试

简介: .net持续集成测试篇之Nunit参数化测试系列目录在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进行测试.

.net持续集成测试篇之Nunit参数化测试
系列目录

在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进行测试.其实Nunit框架本身提供了为测试用例提供值的能力.我们可以对它进行扩展来实现导入外部的值来填充到测试方法内部.很多朋友也自己写了不少按照一定规则生成值的方法.但是往往都是在方法内部直接调用,这样就会和单元测试的逻辑混杂在一块,导致测试方法本身不够简洁.其实可以根本测试框架本身的能力改造成为注解的方式,这样参数生成逻辑和测试逻辑一目了然.后面我们还会讲解基于Autofixture框架来生成填充数据,autofixture相比我们自己写的值填充方法,往往功能更加强大.后面我们将见证其强大之处.

提供普通参数
很容易发现,单元测试的方法都是不带参数的,有些时候我们需要为一个要测试的方法(并非单元测试方法)提供多个参数进行测试,这就会导致一个问题:我们需要写很多类似的测试方法,只是参数不一样,这样维护起来不方便,同时大量重复的工作也很烦.下面介绍Nunit里如何为测试提供参数

    int  Add(int x, int y)
    {
        return x + y;
    }

以上是我们要测试的方法.

虽然Nunit测试方法正常情况下是不支持参数的,但是如果对参数添加的values注解,Nunit便会把这些参数应用到测试.
我们看一下编写的测试方法

    [Test]
    public void DemoTest([Values(3,4,5)]int a,[Values(6,7,8)]int b)
    {
        var result = Add(a, b);
        Assert.AreEqual(a + b, result);
    }

我们运行以上方法,可以看到测试结果通过,但是我们看一下测试面板(Test Explorer)

avatar
通过截图我们很容易发现,这个测试方法一共运行的九次!再仔细看看方法对应的参数,可以看到它是使用组合的方式把所有的可能都组合一遍.

但是有些时候我们想要的不是这样的组合,我们想要的更多时候是(3,6),(4,7),(5,8)这样的组合,如何做到呢,仍然看一段示例代码

    [Test]
    [Sequential]
    public void DemoTest([Values(3,4,5)]int a,[Values(6,7,8)]int b)
    {
        var result = Add(a, b);
        Assert.AreEqual(a + b, result);
    }

我们看看运行结果

avatar

这次只运行了三次,并且参数的组合正如我们期待的.
这个方法和上面的一样,只是多了一个[Sequential]注解

注意Values注解里的参数都是Object类型,运行时候转换为参数的真正类型,如果无法转换则会抛出异常.比如[Values("a")]int x由于a是字符串类型,通过内置方法无法转换为int,因些会抛出异常.

提供基于范围的参数
上面的测试Values(3,4,5)和Values(6,7,8)都是连续的数字,如果连接的参数更多,我们可以使用基于范围的参数.

看以下示例代码

    [Test]
    [Sequential]
    public void DemoTest([Range(3,5)]int a,[Range(6,8)]int b)
    {
        var result = Add(a, b);
        Assert.AreEqual(a + b, result);
    }

我们把Values注解改为Range注解,就ok了

提供随机参数
我们还可以为测试提供一些随机数,以使测试变得更随机,覆盖范围更大

这里要使用Random注解
请看下面示例

   [Test]
   [Sequential]
    public void DemoTest([Random(3)]int a, [Random(3)]int b)
    {
        var result = Add(a, b);
        Assert.AreEqual(a + b, result);
    }

Random的参数为要生成随机数的个数.

Random还有一重载以支持生成随机数的最大值和最小值

   [Test]
   [Sequential]
    public void DemoTest([Random(3,10,2)]int a, [Random(5,9,3)]int b)
    {
        var result = Add(a, b);
        Assert.AreEqual(a + b, result);
    }

示例中Random的三个参数分别是最小值,最大值和个数

[info]Random的最大值和最小值不仅可以是整数,也可以是小数

提供计算参数
先看一个示例

   [Test]
   [Sequential]
    public void DemoTest(DateTime dt1)
   {
       DateTime dt2 = default(DateTime);
       Assert.Greater(dt1, dt2);
   }

这里测试方法的参数是Datetime类型,我们如何给给它提供值呢,很多人可能会想使用Values[DateTime.Now] 来注解dt1参数,然而不幸的是Values注解只接受const类型的值,这里介绍ValueSource注解来解决这个问题.

ValueSource的机制是使用一个方法来获取值,然后提供给测试方法参数,它接受一个字符串类型的参数,用于指定提供值的方法名.

我们用以下方法生成一些DateTime值

static IEnumerable GetPeople()

    {
        yield return DateTime.Now;
        yield return DateTime.Now.AddDays(2);
    }

以上方法生成了一个包含两个DateTime值的集合.下面我们看如何使用它

   [Test]
    public void DemoTest([ValueSource(nameof(FirstUnitTest.GetPeople))]DateTime dt1)
   {
       DateTime dt2 = default(DateTime);
       Assert.Greater(dt1, dt2);
   }

我们使用nameof获取刚才生成的用于提供值的方法,作为ValueSource的参数.

使用nameof而不是使用手写字符串的好处在于nameof可以有智能提示,防止手写出现错误,另外就是如果方法名更改,这里将会抛出了一个错误,静态字符串不会提示错误,如果在运行时找不到这个方法则会抛出运行时错误

用于为ValueSource提供值的方法必须是静态的

以上代码,我们把提供值的方法直接写在测试类里,这并不是一种很好的实践,一种好的做法是把所有的用于提供值的方法放在一个外部的类中.

我们把这个类移动到一个叫作MyValueProvider的类中
代码如下

public class MyValueProvider

{
    public static IEnumerable<DateTime> GetPeople()
    {
        yield return DateTime.Now;
        yield return DateTime.Now.AddDays(2);
    }
}

单元测试方法改成如下:

   [Test]
    public void DemoTest([ValueSource(typeof(MyValueProvider),nameof(MyValueProvider.GetPeople))]DateTime dt1)
   {
       DateTime dt2 = default(DateTime);
       Assert.Greater(dt1, dt2);
   }

如果把值提供方法不在本类中(当前测试方法所在的类),提供一个Type类型(提供值的方法所在的类的类型)作为第一个参数,方法名作为第二个参数.

上面讲的都是基于参数注解的值提供方法,这里基于方法的注解的值提供方法.当然,它完成的功能基于参数注解的方法也同样能完成.

TestCaseAttribute注解
看以下代码片段

   [TestCase(3,4)]
    public void DemoTest(int x,int y)
   {
       var val = Add(x, y);
       Assert.AreEqual(x + y, val);
   }

其中用到的Add方法代码如下

int Add(int x, int y)

    {
        return x + y;
    }

TestCase的工作原理是这样的,它提供的值是基于位置的,每一个位置处的值赋值给第一个参数,第二个位置处的值提供给第二个参数...

有了TestCase注解之后,Test注解不再是必要的.

TestCaseSourceAttribute注解
从上ValueSource我们很容易想到可能会有TestCaseSource,实际上也确实是这样的,TestCaseSource功能也同ValueSource一样,用于提供基于计算的结果.

用于提供值的类如下

public class MyValueProvider
{

   public static ArrayList ar = new ArrayList
   {
       new int[] {3, 4},
       new int[] {5, 9},
       new int[] {9, 22}
   };

}
测试方法如下

   [TestCaseSource(typeof(MyValueProvider),nameof(MyValueProvider.ar))]     
    public void DemoTest(int x,int y)
   {
       var val = Add(x, y);
       Assert.AreEqual(x + y, val);
   }

从这个例子我们可看到,不仅方法可以提供值,属性,普通字段也可以提供值

为TestCaseSource提供值的字段,方法,属性也必须是静态的

TestCase和TestCaseSource都支持多重注解,有几个注解,测试方法就会运行几次.
原文地址https://www.cnblogs.com/tylerzhou/p/11312957.html

相关文章
|
5天前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
27天前
|
测试技术 持续交付 API
深入挖掘探索.NET单元测试
【10月更文挑战第11天】
35 2
|
22天前
|
测试技术 C# 数据库
C# 单元测试框架 NUnit 一分钟浅谈
【10月更文挑战第17天】单元测试是软件开发中重要的质量保证手段,NUnit 是一个广泛使用的 .NET 单元测试框架。本文从基础到进阶介绍了 NUnit 的使用方法,包括安装、基本用法、参数化测试、异步测试等,并探讨了常见问题和易错点,旨在帮助开发者有效利用单元测试提高代码质量和开发效率。
132 64
|
4天前
|
人工智能 API C#
使用Microsoft.Extensions.AI简化.NET中的AI集成
使用Microsoft.Extensions.AI简化.NET中的AI集成
使用Microsoft.Extensions.AI简化.NET中的AI集成
|
20天前
|
Kubernetes 测试技术 持续交付
C# 一分钟浅谈:集成测试与系统测试
【10月更文挑战第19天】本文详细介绍了集成测试和系统测试的概念、目的及其在软件开发中的重要性。通过分析常见问题和易错点,结合代码示例,探讨了如何通过代码规范、自动化测试和持续集成等方法提高测试效果,确保软件质量和可靠性。
43 1
|
1月前
|
测试技术
软件质量保护与测试(第2版)学习总结第十三章 集成测试
本文是《软件质量保护与测试》(第2版)第十三章的学习总结,介绍了集成测试的概念、主要任务、测试层次与原则,以及集成测试的不同策略,包括非渐增式集成和渐增式集成(自顶向下和自底向上),并通过图示详细解释了集成测试的过程。
59 1
软件质量保护与测试(第2版)学习总结第十三章 集成测试
|
27天前
|
测试技术 API 开发者
精通.NET单元测试:MSTest、xUnit、NUnit全面解析
【10月更文挑战第15天】本文介绍了.NET生态系统中最流行的三种单元测试框架:MSTest、xUnit和NUnit。通过示例代码展示了每种框架的基本用法和特点,帮助开发者根据项目需求和个人偏好选择合适的测试工具。
37 3
|
4天前
|
开发框架 安全 .NET
.NET使用Moq开源模拟库简化单元测试
.NET使用Moq开源模拟库简化单元测试~
|
2月前
|
Devops jenkins 测试技术
DevOps实践:持续集成与自动化测试的融合之道
【9月更文挑战第29天】在软件开发的快节奏竞赛中,DevOps如同一位智慧的舵手,引领着船只驶向效率与质量的彼岸。本文将揭开DevOps的神秘面纱,探索其核心理念如何通过持续集成(CI)和自动化测试的实践,实现软件开发流程的优化与加速。我们将一同见证代码从构思到部署的旅程,以及这一过程中的关键技术和工具如何协同工作,确保软件质量和交付速度的双重提升。
|
2月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
58 0

热门文章

最新文章