使用 NUnit 测试无限序列,但必须检查有限序列

Testing an infinite sequence with NUnit, but only a finite sequence must be checked

我有一个扩展方法可以提取字符串列表中的数字(bbb1、da21ds、dsa231djsla90 ==> 1、21、23190):

    public static int[] GetContainedNumbers(this string[] source)
    {
        if (source == null) throw new ArgumentNullException();
        int[] result = new int[] {};
        
        foreach (var s in source)
        {
            string onlyNumbers = new String(s.Where(Char.IsDigit).ToArray());
            if (String.IsNullOrEmpty(onlyNumbers)) throw new ArgumentException();
            int extractedNumber = Int32.Parse(onlyNumbers);
            
            result = result.Concat(new int[] { extractedNumber }).ToArray();
        }
        
        return result;
    }

我需要使用 NUnit 进行测试。请求是用无限的字符串序列(a1z,a2z,a3z,...)进行测试,但输出只需要检查前100个数字。

目前我不知道我应该做什么。我最初的想法是创建一个这样的测试:

        int[] expectedResult = Enumerable.Range(0, 99).ToArray();
        string[] source = new string[] {};
        int n = 0;
        
        while (true)
        {
            if (n == 99) break;
            source = source.Concat(new string[] { "a" + n + "z" }).ToArray();
            n++;
        }
        
        Assert.AreEqual(expectedResult, source.GetContainedNumbers());

但这实际上没有意义,因为数组是有限的而不是无限的。 我不知道创建无限的事物列表意味着什么以及我应该如何创建它或测试它。

如果需要,我可以编辑扩展方法。在此先感谢您的帮助,如果我的英语很烂,我深表歉意。


第一个任务是制作扩展方法本身,我在上面已经解决了。可以修改,但必须解析这段代码(我无法编辑):

foreach (var d in new[] { "1qui7", "q8u8o", "-1024", "0q0ua0" }.GetContainedNumbers())
        {
            Console.WriteLine("{0}, ", d);
            var strings = new [ ] { "1qui7" , " q8u8o " , " −1024" , " 0 q0ua0 " };
        }

预期输出:17、88、1024、0,

我相信这个练习的目的是调查惰性评估

目前您的方法接受 string[] 和 return 一个 int[] - 但问题中没有任何内容表明它 这样做。

相反,如果您要编写一个扩展方法来接受 IEnumerable<string> 和 returning 一个 IEnumerable<int>,那么您可以接受无限的元素序列和 return一个相应的无限输出序列,它被延迟评估:当调用者请求下一个输出元素时,您反过来请求下一个输入元素,处理它并产生输出。 C# 使用 iterator blocks.

使所有这些变得非常简单

所以我希望有这样的方法:

public static IEnumerable<int> GetContainedNumbers(IEnumerable<string> source)
{
    foreach (string inputElement)
    {
        int outputElement = ...; // TODO: your logic here
        yield return output;
    }
}

现在测试这个,你可以再次使用迭代器块来生成真正无限序列,或者你可以测试有效地 使用 LINQ 的无限序列,例如

IEnumerable<string> veryLargeInput = Enumerable
    .Range(0, int.MaxValue)
    .Select(x => $"a{x}z");

真正的无限版本可能是这样的:

IEnumerable<string> infiniteSequence = GetInfiniteSequence();
...
private static IEnumerable<string> GetInfiniteSequence()
{
    int value = 0;
    while (true)
    {
        yield return $"x{value}z";
        // Eventually this will loop round from int.MaxValue to
        // int.MinValue. You could use BigInteger if you really wanted.
        value++;
    }
}

测试结果时,您需要获取输出的前 100 个元素。例如:

var input = GetInfiniteSequence(); // Or the huge Enumerable.Range
var output = input.GetContainedNumbers(); // This is still infinite
var first100Elements = output.Take(100).ToList();
// Now make assertions against first100Elements