【问题标题】:Create a NUnit test on an infinite sequence在无限序列上创建 NUnit 测试
【发布时间】:2015-08-24 20:42:31
【问题描述】:

我有这个方法:

public static IEnumerable<T> Jumping<T>( this IEnumerable<T> sequence, int step)
{
    if(sequence==null)
        throw new ArgumentNullException();
    if(step<0)
        throw new ArgumentOutOfRangeException();
    var s = sequence.GetEnumerator();
    for (int i = 0; i <= step; i++)
    {
        if (!s.MoveNext())
        {
            s.Reset();
            s.MoveNext();
        }
        if (i == step)
        {
            i = 0;
            yield return s.Current;
        }
    }
}

请求是创建一个无限序列的NUnit测试,我该怎么做?

【问题讨论】:

标签: c# unit-testing testing nunit


【解决方案1】:

意识到单元测试比数学更等同于(硬)科学,这可能会有所帮助。单元测试套件很少证明任何东西,但它越来越有可能表明,如果所有测试都通过,则被测系统运行正常。

有了这个认识,当你有一个无限序列时,你需要编写一组测试来共同证明Jumping 的行为是正确的。

虽然您无法测试无限序列,但您可以从此类序列中获取任意数量的元素,并对此类有限序列进行断言。

这听起来很适合基于属性的测试。从无限序列中获取随机数量的元素,并开始定义必须满足一系列随机生成的输入序列和元素计数的前置条件和后置条件。

您可能需要定义多个属性才能覆盖Jumping 方法的所需行为。


也就是说,我很难理解 Jumping 的确切作用,但它似乎做的不止一件事。 AFAICT,它既重复输入序列,又跳过元素。这种复杂的行为可能会导致难以针对它定义属性。

是否有可能将该行为分解为更小的函数?

例如,为了无限地重复一个序列,Haskell 定义了一个cycle function。在 F# 中,您可以轻松地从现有函数中定义 cycle 函数:

let cycle xs = Seq.initInfinite (fun _ -> xs) |> Seq.concat

在 C# 中,您可能可以使用 while(true) 循环和一些 yield 语句执行类似的操作。

为这样的cycle 函数定义属性相当容易,包括:

  • 如果xs 也是无限的,对于count 的任何值,take count xs 应该等于 take count (cycle xs)
  • 如果xs 是有限的,则xs 应该等于(take (length xs) (cycle xs))
  • 如果xs 是有限的,那么对于任何counttake count (cycle xs) 的最后一个length xs 元素应该等于xs,这是length xs 的倍数。

这会给你一个无限的重复值序列。然后你能在任何序列上定义一个“跳转”函数吗?

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 2010-12-31
    • 2014-07-17
    相关资源
    最近更新 更多