【问题标题】:Applying one test to two separate classes将一项测试应用于两个单独的类
【发布时间】:2009-11-16 10:04:49
【问题描述】:

我有两个不同的类共享一个公共接口。尽管功能相同,但它们在内部的工作方式却大不相同。所以我很自然地想测试它们。

我能想到的最好的例子;我 将某些东西序列化到一个文件中,一个 类将其序列化为纯文本,即 其他到 xml。数据(应该)看起来 之前和之后都一样 不考虑方法的序列化 用过。

以相同方式测试这两个类的最佳方法是什么?测试仅在实例化不同类的方式上有所不同。我不想复制整个测试,重命名并更改一行。

测试目前在 JUnit 中,但我还是要将它们移植到 NUnit,所以代码并不重要。我更多的是寻找一种适用于这个测试套件的设计模式。

【问题讨论】:

    标签: c# java unit-testing design-patterns junit


    【解决方案1】:

    为测试创建一个通用的抽象基测试类。

    abstract class BaseTest{
    
     @Test
     public void featureX(){
        Type t = createInstance();
        // do something with t
     }
    
     abstract Type createInstance();
    }
    
    ConcreteTest extends BaseTest{
    
        Type createInstace(){
            return //instantiate concrete type here.
        }
    }
    

    【讨论】:

    • 不错的选择,但您还需要将BaseTest 标记为已忽略,以免xUnit 尝试运行它。
    • 取决于跑步者。或多或少有智能。前者认为该类是抽象的,后者可以配置为根据模式忽略该类。
    【解决方案2】:

    我会通过继承或聚合重用代码。

    为了获得最短的代码,我会将测试实例的创建移动到工厂方法中,例如 XmlImplementationTest 类,并从中继承 TextImplementationTest:

    XmlImplementationTest extends TestCase
    {
      Interface tested = null
      Interface createTested() { return new XmlImplementation() }
      ...
      void setUp() { tested = createTested(); }
    }
    
    TextImplementationTest extends XmlImplementationTest
    {
      override Interface createTested() { return new TextImplementation() }
    }
    

    这不是完全正确的 OO 设计,因为它的 TextImplementationTest 不是 XmlImplementationTest。但通常你不需要关心它。

    或者将测试方法调用重新寻址到一些常见的实用程序类。这将涉及更多代码,并且不会在测试报告中显示正确的测试类,但可能更容易调试。

    【讨论】:

      【解决方案3】:

      我倾向于避免测试类之间的任何关系。我喜欢尽可能保持测试用例(或类)的原子性。在这里使用继承的好处并没有超过您通过它获得的强耦合。

      我想这会很有帮助,如果您可以分享两个类的结果验证(假设黑盒测试)。如果这两个类都能够让您设置输出流,您可以验证这一点,而这些类本身会写入 PrintWriter 或 FileWriter(或您需要的任何内容)。

      此外,我会避免在单元测试期间创建文件,因为这可能会花费太多时间(+ 它可能无法在构建机器上运行)并因此延迟您的构建。

      【讨论】:

      • 确实是非常有效的点,但将它们完全分开将意味着 1000 行(几乎)相同的代码。当应该更新两个测试时,更改界面或它的工作方式似乎有点像一罐蠕虫。但也许你是对的,也许这就是你编写两个具有相似逻辑的类时得到的东西。
      • 你写了课程之前你写了测试也许这会给你一个教训。 ;-----)
      【解决方案4】:

      在 C# 中,我会使用通用辅助方法来测试这两种情况,例如:

      internal static void SerializationTestHelper<T>() where T : IMySerialize
      {
          T serialize = new T();
          // do some testing
      }
      
      [TestMethod]
      public void XmlTest()
      {
          SerializationTestHelper<XmlSerialize>();
      }
      
      [TestMethod]
      public void PlainTextTest()
      {
          SerializationTestHelper<PlainTextSerialize>();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 2014-06-28
        • 2018-09-02
        相关资源
        最近更新 更多