【问题标题】:Best Practices/Ideas for setting up system state when integration testing?集成测试时设置系统状态的最佳实践/想法?
【发布时间】:2010-11-01 01:25:29
【问题描述】:

我有许多 C# 集成测试使用由 cucumber 推广的 Given/When/Then 样式编写。我使用的框架与 NBehave 基本相同。

我面临的一个反复出现的问题是设置和连接集成测试所需的所有应用程序状态的问题。我的大多数测试看起来像这样:

给定一个空系统 和一个新的 NetworkServer 和一个新的 ServerDatabase 还有一个新的事件记录器 和一个新的网络连接 还有一个新的 LoggingClient 当客户端记录新事件时 然后它应该出现在服务器数据库中

如您所见,动作和断言是单行的,但我有 6 行“连线”。几乎我的每个测试都重复了这 6 行。

这对我来说似乎是一种代码味道,但我不确定如何处理。我可以将 6 行重构为一行(Given "a valid system..." 或类似的),但这似乎太过分了,我会隐藏太多信息。

如果其他人在这方面有更多经验,我将不胜感激。非常感谢。

【问题讨论】:

    标签: c# cucumber integration-testing nbehave


    【解决方案1】:

    在我看来,这听起来像是您希望有一个基类来做一些设置类的事情,然后让您的测试类从这个基类继承并只添加新的测试功能。

    Base():
      constructor():
        do your wiring
        test if everything's ok
    
    
    TestClass : Base
      constructor():
        Base.constructor()
        additional setup?
    
      test_functions()
        ..
    

    【讨论】:

    • Hrm... 感谢您的意见。我必须承认我不喜欢基类模型,因为这意味着一半的设置代码隐藏在一个完全不同的文件中的基本构造函数中......虽然总是很高兴看到不同的观点。 +1
    【解决方案2】:

    我们有这样的东西

    public abstract class ContextSpecification
    {
        [FixtureSetUp]
        public void SetUp()
        {
            EstablishContext();
            Act();
        }
    
        protected abstract void Act();
    
        protected abstract void EstablishContext();
    
        [FixtureTearDown]
        public void TidyUpCore()
        {
            TidyUp();
        }
    
        protected virtual void TidyUp()
        {
    
        }
    }
    

    然后,我们为每组类似的测试创建一个 BaseContext,如下所示:

    internal class TestClassTests 
    {
        internal abstract class BaseContext : ContextSpecification
        {
            protected TestClass _sut;
    
            protected override void Act()
            {
    
            }
    
            protected override void EstablishContext()
            {
                _sut = new TestClass ();
               // common wiring
            }
        }
    
       internal class Given_this_situation : BaseContext
       {
           protected override void EstablishContext()
           {
               base.EstablishContext();
               // test specific wiring
           }
    
           protected override void Act()
           {
               // carry out the test actions
           }
    
           [UnitTest]
           public void ThisShouldBeTrue()
           {
              Assert.IsTrue();
           }
       }
    }
    

    【讨论】:

    • 有趣的是看到一个单一的“Act”方法,然后所有的断言都在之后单独处理。你觉得这在实践中如何运作?我认为单元测试的目标之一是让每个测试方法都是自主的(不依赖于在它之前运行的“Act”)......
    • 它工作得很好——我们倾向于将每个断言放在它自己的测试方法中,这样在测试中断时会传达更多信息:我们不必寻找失败的断言。使用这种技术,我们只是将原理在层次结构中上移了一层——每个测试类都是自治的。
    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    相关资源
    最近更新 更多