NUnit 子序列断言

NUnit subsequence assertion

NUnit 有多种方法可以使用 CollectionAssert and Collection Constraints 相互测试集合。但是我没有看到一种方法来测试一个 IEnumerable 是否是另一个的子序列,即它是子集,其元素的顺序与超集中的顺序相同。

我是不是忽略了什么,还是需要自己实现?

编辑:这就是我想要的那种测试

[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })] // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
    AssertSubsequence(subsequence, supersequence, Comparer<int>.Default);
}

这不是针对 O(n log(n)) 最坏情况的最有效算法,但您可以按照以下方法进行操作

[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })]   // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })]            // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })]         // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })]         // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })]            // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })]         // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
    AssertSubsequenceWithGaps(subsequence, supersequence);
}

public static void AssertSubsequenceWithGaps(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
    // iterating multiple times, cast sequences to List
    var listSub = subsequence.ToList();
    var listSuper = supersequence.ToList();

    int expected = listSub.Count;
    int innerPointer = 0;
    int actual = 0;
    for (int i = 0; i < listSub.Count; i++)
    {
        for ( /* start from where we left before */; innerPointer < listSuper.Count; innerPointer++)
        {
            var valueSub = listSub[i];
            var valueSuper = listSuper[innerPointer];
            if (valueSub == valueSuper)
            {
                actual++;
                break;
            }
        }
    }

    Assert.AreEqual(expected, actual);
}

由于似乎没有开箱即用的解决方案,这里是我同时想到的。

private static void AssertSubsequence<T>(IEnumerable<T> subsequence, IEnumerable<T> superSequence, IComparer<T> comparer)
{
    var superEnumerator = superSequence.GetEnumerator();

    foreach (var subElement in subsequence)
    {
        if (!superEnumerator.MoveNext())
        {
            Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence.", subElement);
        }

        while (comparer.Compare(subElement, superEnumerator.Current) != 0)
        {
            if (!superEnumerator.MoveNext())
            {
                Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence", subElement);
            }
        }
    }
}