在不违反 SRP、OCP、DRY 的情况下编写测试
Writing tests without violating SRP, OCP, DRY
我正在努力更好地理解这三个原则。
我的问题是...
如何在不违反 SRP、OCP 和 DRY 的情况下编写测试?
由于测试文件中的代码相似,我当前的设计违反了 DRY。
我不能将测试文件合并在一起,因为那样会违反Open/Closed原则。 (后面大概率会加更多模块)
我在这里遗漏了什么吗?
如果有帮助,我将为此使用 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
这是我的做法。
OCP:
测试模块的 类 不必修改
建议零售价:
类 只测试模块
干燥:
通过创建包含模块测试器,您可以避免测试中的代码重复。
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
测试代码与常规代码有很大不同,因此尽管所有这些设计原则在测试代码中通常都是有效的,但它们的重要性在测试代码中是不同的。
关于DRY,测试代码的可读性高于一切,因此测试代码中的重复比常规代码多一点是正常的。听起来好像测试您的两种算法中的每一种都需要您没有显示的重复;通过将重复提取到测试辅助方法中来解决这个问题。但只有在保持测试清晰度的情况下才这样做。
关于 OCP,测试需要做任何它需要做的事情来测试它正在测试的模块。如果一开始你的模块设计有误,不得不将一个模块分成两部分或类似的东西,你也必须对测试做同样的事情。所以不要担心你的测试是否遵循OCP,担心你的常规代码和测试会遵循。
关于 SRP,再次强调,测试需要做任何它需要做的事情来测试它正在测试的模块。如果一个模块的职责太多,那么它的测试也将如此。这表明模块需要重构以解决模块和测试的问题。
此外,还有不同种类的测试。集成测试本质上比单元测试承担更多责任。
我正在努力更好地理解这三个原则。
我的问题是... 如何在不违反 SRP、OCP 和 DRY 的情况下编写测试?
由于测试文件中的代码相似,我当前的设计违反了 DRY。
我不能将测试文件合并在一起,因为那样会违反Open/Closed原则。 (后面大概率会加更多模块)
我在这里遗漏了什么吗? 如果有帮助,我将为此使用 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
这是我的做法。 OCP: 测试模块的 类 不必修改 建议零售价: 类 只测试模块 干燥: 通过创建包含模块测试器,您可以避免测试中的代码重复。
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
测试代码与常规代码有很大不同,因此尽管所有这些设计原则在测试代码中通常都是有效的,但它们的重要性在测试代码中是不同的。
关于DRY,测试代码的可读性高于一切,因此测试代码中的重复比常规代码多一点是正常的。听起来好像测试您的两种算法中的每一种都需要您没有显示的重复;通过将重复提取到测试辅助方法中来解决这个问题。但只有在保持测试清晰度的情况下才这样做。
关于 OCP,测试需要做任何它需要做的事情来测试它正在测试的模块。如果一开始你的模块设计有误,不得不将一个模块分成两部分或类似的东西,你也必须对测试做同样的事情。所以不要担心你的测试是否遵循OCP,担心你的常规代码和测试会遵循。
关于 SRP,再次强调,测试需要做任何它需要做的事情来测试它正在测试的模块。如果一个模块的职责太多,那么它的测试也将如此。这表明模块需要重构以解决模块和测试的问题。
此外,还有不同种类的测试。集成测试本质上比单元测试承担更多责任。