【问题标题】:how to organize test data in integration tests如何在集成测试中组织测试数据
【发布时间】:2015-02-25 19:27:11
【问题描述】:

我正在处理一个包含数千个集成测试的大型测试项目。 有很多代码重复,有点混乱。大多数测试由几个步骤组成,并创建了许多“虚拟”对象。对于 dummy,我的意思是这样的:

new Address {
    Name = "fake address",
    Email = "some@email.com",
    ... and so on
}

数据是什么通常并不重要。这种代码在测试、测试基类和帮助程序中展开和复制。

我想要的是有一个单一的“测试数据构建器”,有一个单一的职责,生成测试使用的测试数据。

一种方法是创建一个包含一堆静态方法的类,如下所示:

Something CreateSomething(){
    return new Something {
    // set default dummy values
}

还有一个重载:

Something CreateSomething(params){
    return new Something {
    // create the Something from the params
}

另一种方法是让 xml 文件包含数据,但我担心它离测试太远了。

我们的目标是将这种代码从测试中移出,因为现在测试很大且不可读。典型情况下,50行测试代码中,有20-30行是这种代码。

有什么模式可以做到这一点吗?或者有什么大型开源代码库的例子,我可以看看?

【问题讨论】:

    标签: c# integration-testing readability


    【解决方案1】:

    对于代码,使用简单的方法链构建器模式:

    public class TestOrderBuilder
    {
        private order = new Order();
    
        //  These methods represent sentances / grammar that describe the sort   
        //  of test data you are building
        public AnObjectBuilder AddHighQuantityOrderLine()
        {
             //... code to add a high quantity order line
    
             return this; // for method chaining
        }
    
        //  These methods represent sentances / grammar that describe the sort   
        //  of test data you are building
        public AnObjectBuilder MakeDescriptionInvalid()
        {
             //... code to set descriptions etc...
    
             return this; // for method chaining
        }
    
        public Order Order
        {
             get { return this.order; }
        }
    }
    
    // then using it:
    var order = new TestOrderBuilder()
                     .AddHighQuantityOrderLine()
                     .MakeDescriptionInvalid()
                     .Order
    

    【讨论】:

    • +1 我本来会写的另一个答案,但你打败了我......但是您想稍后在另一种方法中添加更多内容?如果您再次定义相同的设置,大多数模拟框架通常会破坏任何先前的设置。例如使用起订量,我如何在一种方法中设置.Returns,然后在另一种方法中(或直接在我的测试中)定义.Callback?我的解决方法是将.Returns 复制到所述回调设置区域或维护设置的集合。
    • 我不相信我必须这样做。使用 Moq 时,设置通常非常简洁,老实说,我倾向于不使用回调,通常只需在断言中使用给定参数验证方法调用即可。但是,您可以应用相同的 Builder 模式来构建您的 Mock ?
    • 是的,我已经采用了这种方法,并且我还尝试过使用 Castle.DynamicProxy 将功能与 Mocks 混合在一起......非常冒险!
    【解决方案2】:

    我会回避指定测试依赖项的 xml 文件。

    我的思考过程源于缺乏重构工具,这些 xml 文件无法在 Visual Studio 生态系统中利用。

    相反,我会创建一个 TestAPI。 该 API 将负责为测试客户端提供依赖数据。

    请注意,被请求的依赖数据已经用通用数据初始化,并准备好发送给请求依赖的客户端。

    作为特定测试所需测试输入的任何值都将在测试本身内分配。这是因为我希望测试能够自我记录其意图或目标,并抽象出未测试的依赖项。

    XUnit Test Patterns 为我编写测试提供了很多见解。

    【讨论】:

    • TestAPI 到底是什么意思?一个流利的测试API,静态的“纯”方法,还有别的吗?谢谢你的书提示:)
    • 一个例子:见我帖子的单元测试部分...stackoverflow.com/questions/26871519/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多