Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试-基于算法还是基于样本?_C#_Unit Testing_Language Agnostic - Fatal编程技术网

C# 单元测试-基于算法还是基于样本?

C# 单元测试-基于算法还是基于样本?,c#,unit-testing,language-agnostic,C#,Unit Testing,Language Agnostic,假设我正在测试一个简单的集合类 public IntSet : IEnumerable<int> { Add(int i) {...} //IEnumerable implementation... } public IntSet:IEnumerable { 加(整数i){…} //IEnumerable实现。。。 } 假设我试图测试集合中不存在重复的值。我的第一个选择是向集合中插入一些样本数据,并使用我对所用数据的了解测试重复数据,例如: //OPTIO

假设我正在测试一个简单的集合类

public IntSet : IEnumerable<int>
{
    Add(int i) {...}
    //IEnumerable implementation...
}
public IntSet:IEnumerable
{
加(整数i){…}
//IEnumerable实现。。。
}
假设我试图测试集合中不存在重复的值。我的第一个选择是向集合中插入一些样本数据,并使用我对所用数据的了解测试重复数据,例如:

    //OPTION 1
    void InsertDuplicateValues_OnlyOneInstancePerValueShouldBeInTheSet()
    {
        var set = new IntSet();

        //3 will be added 3 times
        var values = new List<int> {1, 2, 3, 3, 3, 4, 5};
        foreach (int i in values)
            set.Add(i);

        //I know 3 is the only candidate to appear multiple times
        int counter = 0;
        foreach (int i in set)
            if (i == 3) counter++;

        Assert.AreEqual(1, counter);
    }
//选项1
void InsertDuplicateValues\u仅在INSTANCEPERVALUE应位于ESET()中
{
var set=new IntSet();
//3将被添加3次
var值=新列表{1,2,3,3,3,4,5};
foreach(值中的int i)
增加(i);
//我知道3是唯一出现多次的候选人
int计数器=0;
foreach(集合中的int i)
如果(i==3)计数器++;
断言.AreEqual(1,计数器);
}
我的第二个选择是测试我的一般情况:

    //OPTION 2
    void InsertDuplicateValues_OnlyOneInstancePerValueShouldBeInTheSet()
    {
        var set = new IntSet();

        //The following could even be a list of random numbers with a duplicate
        var values = new List<int> { 1, 2, 3, 3, 3, 4, 5};
        foreach (int i in values)
            set.Add(i);

        //I am not using my prior knowledge of the sample data 
        //the following line would work for any data
        CollectionAssert.AreEquivalent(new HashSet<int>(values), set);
    } 
//选项2
void InsertDuplicateValues\u仅在INSTANCEPERVALUE应位于ESET()中
{
var set=new IntSet();
//下面甚至可以是一个随机数列表,其中有一个重复
var值=新列表{1,2,3,3,3,4,5};
foreach(值中的int i)
增加(i);
//我没有使用我对样本数据的先验知识
//以下行适用于任何数据
集合Assert.AreEquivalent(新哈希集(值),集合);
} 
当然,在本例中,我方便地有一组要检查的实现,以及比较集合的代码(CollectionAssert)。但如果我两个都没有呢?这段代码肯定比前面的选项更复杂!这就是您在测试真实生活中的自定义业务逻辑时遇到的情况

诚然,针对预期条件的测试通常会覆盖更多的情况——但它变得非常类似于再次实现逻辑(这既单调又无用——您不能使用相同的代码来检查自身!)。基本上,我是在问我的测试应该是“插入1,2,3然后检查关于3的内容”还是“插入1,2,3然后检查一般的内容”


编辑-为了帮助我理解,请在回答中说明您是否喜欢选项1或选项2(或两者都不喜欢,或视情况而定,等等)。只是想澄清一下,很明显在这种情况下(
IntSet
),选项2在所有方面都更好。但是,我的问题与没有替代实现可供检查的情况有关,因此选项2中的代码肯定比选项1更复杂。

如果有替代实现,那么一定要使用它

在某些情况下,您可以避免重新实现替代实现,但总体上仍然可以测试功能。例如,在您的示例中,您可以首先生成一组唯一值,然后在将其传递给实现之前随机复制元素。您可以测试输出是否等同于起始向量,而无需重新实现排序

只要可行,我就尝试采用这种方法

更新:本质上,我提倡OP的“选项2”。使用这种方法,只有一个输出向量允许测试通过。使用“Option#1”,可接受的输出向量数量是无限的(它正在测试一个不变量,但不测试与输入数据的任何关系)。

根据,测试被测系统的状态通常更有利。如果要测试其行为和算法的运行方式,可以使用模拟对象测试

也就是说,您的两个测试都称为数据驱动测试。通常可以接受的是使用API提供的尽可能多的知识。记住,这些测试也可以作为软件的文档。因此,让它们尽可能简单是至关重要的——不管这对您的具体情况意味着什么

基本上我是在问我的测试 应该像“插入1,2,3然后 检查大约3”或“插入1”, 2号,3号,检查一下里面有什么东西 “一般”

我不是一个TDD纯粹主义者,但人们似乎在说,如果你试图测试的条件被打破,测试应该被打破。e、 i.如果您实施了一项检查一般情况的测试,那么您的测试将在多个情况下中断,因此它不是最优的

如果我测试不能添加重复项,那么我只会测试它。所以在这种情况下,我会说我会先选择

(更新) 好的,现在你已经更新了代码,我需要更新我的答案


我会选择哪一个?它取决于
CollectionAssert.arequivalent(新HashSet(value),set)的实现。例如,
IEnumerable
确实保持了顺序,而
HashSet
却没有,因此即使这样也可能破坏测试,而它本不应该这样做。对我来说,首先仍然是优越的。

我通常更喜欢一个接一个地测试用例——这很好地用TDD的方式工作:“编写一点代码,测试一点”。当然,过了一段时间,我的测试用例开始包含重复的代码,所以我重构了。验证结果的实际方法对我来说并不重要,只要它确实有效,并且不会妨碍测试本身。因此,如果有一个“参考实现”进行测试,那就更好了

然而,重要的是,测试应该是可复制的应该清楚每个测试方法实际测试的内容。对我来说,向集合中插入随机值两者都不是——当然,如果涉及大量数据/用例,欢迎使用各种工具或方法来帮助更好地处理这种情况,而不会让我产生错误的安全感。

第一步应该是
Assert.AreEqual(values.Distinct().Count(), set.Count());