在不违反 SRP、OCP、DRY 的情况下编写测试

Posted

技术标签:

【中文标题】在不违反 SRP、OCP、DRY 的情况下编写测试【英文标题】:Writing tests without violating SRP, OCP, DRY 【发布时间】:2015-10-27 15:18:24 【问题描述】:

我正在努力更好地理解这三个原则。

我的问题是... 如何在不违反 SRP、OCP 和 DRY 的情况下编写测试?

由于测试文件中的代码相似,我当前的设计违反了 DRY。

我无法将测试文件合并在一起,因为这会违反打开/关闭原则。 (以后增加更多模块的可能性很大)

这里有什么我遗漏的吗? 如果有帮助,我正在为此使用 Ruby 和 Minitest。

模块文件

a.rb:

module A
  # does an algorithm
end

b.rb:

module B
  #does another algorithm
end

测试文件

a_test.rb:

class ModuleATest
  # tests the algorithm
end

b_test.rb:

class ModuleBTest
  # tests the algorithm
end

【问题讨论】:

我发现这个链接谈到了sharing examples。我需要进一步研究这个话题。 【参考方案1】:

测试代码与常规代码完全不同,因此尽管所有这些设计原则在测试代码中通常都有效,但它们的重要性是不同的。

关于 DRY,测试代码首先需要可读性,因此测试代码中的重复比常规代码多一点是正常的。听起来测试您的两种算法中的每一种都需要您没有显示的重复;通过将重复提取到测试辅助方法中来解决这个问题。但只有在保持测试的清晰性时才这样做。

关于 OCP,测试需要做它需要做的任何事情来测试它正在测试的模块。如果一开始你的模块设计错误并且不得不将一个模块分成两个或其他东西,那么你必须对测试做同样的事情。所以不要担心你的测试是否遵循 OCP,担心你的常规代码和测试会遵循。

关于 SRP,再一次,测试需要做它需要做的任何事情来测试它正在测试的模块。如果一个模块有太多的职责,那么它的测试也会如此。这表明模块需要重构以解决模块和测试的问题。

此外,还有不同类型的测试。就其本质而言,集成测试比单元测试承担更多的责任。

【讨论】:

【参考方案2】:

这就是我的做法。 过氧化氢: 测试模块的类不必修改 建议零售价: 这些类只测试模块 干燥: 通过创建包含模块测试器,您可以避免测试中的代码重复。

module A
    def algorithm(foo)
        #some implementation 
    end
end

module B
    def algorithm(foo)
        #some implementation    
    end
end

module Module_Tester
    def test_module_test
        assert_equal(@expected, @obj.algorithm(@to_test))
        # you test them
    end
end


class ModuleATest < test_framework
    include Module_Tester
    def before 
        @obj = Object.new.extend(A)
        @expected = 'Expected Outcome goes here'
        @to_test = 'The thing to test goes here'
    end
end

class ModuleBTest < test_framework
    include Module_Tester

    def before
        @obj = Object.new.extend(B)
        @expected = 'The Expected Outcome'
        @to_test = 'The thing to test'
    end
end

【讨论】:

以上是关于在不违反 SRP、OCP、DRY 的情况下编写测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用flutter_test.dart包的情况下编写用于在flutter集成测试中点击屏幕点的测试脚本?

如何在不超过最大文档大小的情况下编写聚合?

我可以在不编写扩展的情况下编写 FlexBuilder 脚本吗?

是否可以在不使用 main() 函数的情况下编写程序?

在不指定初始和结束日期的情况下编写每月查询的自动方式?

在不使用标准库的情况下编写 scipy 函数(指数幂)