2015-08-24 23 views
3

一个NUnit测试我有这样的方法:上创建无限序列

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测试,我该怎么办呢?

+1

不知道你期望从无限序列测试(序列的创建将明显重复的东西像http://stackoverflow.com/questions/9399717/linq-statement-for-an-infinite-sequence-of-逐次半部)。我假设你知道https://en.wikipedia.org/wiki/Halting_problem ... –

回答

3

这可能会有助于认识到单元测试比数学更像(科学)科学。一个单元测试套件很少证明任何东西,但它使其越来越可能,如果所有测试通过,被测系统行为正确。

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

虽然不能测试一个无限序列,则可以采取元件的任意数量从这样的序列,并且使针对这样的有限序列的断言。

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

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


这么说,我觉得很难理解到底是什么呢Jumping,但它似乎是在做多件事情。 AFAICT,它会重复输入序列,并跳过元素。这种复杂的行为可能会导致难以根据它定义属性。

将这种行为分解成更小的函数是否可能?

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

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

在C#中,你也许可以做一个while(true)环和一些yield语句类似的东西。

这将会是相当容易的定义属性为这样的cycle功能,包括:

  • 如果xs是无限的,以及,take count xs应等于 take count (cycle xs)用于count任何值。
  • 如果xs是有限的,xs应该等于(take (length xs) (cycle xs))
  • 如果xs是有限的,的take count (cycle xs)最后length xs元素应该等于xs任何count这就是length xs的倍数。

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