由于必须处理模拟对象而不是大型Grails项目中的集成测试,因此编写单元测试通常会更复杂。这article甚至表明我们甚至可以完全取消单元测试,只编写我倾向于同意的集成测试。
与同一单元测试相比,我看到的唯一缺点是集成测试的执行速度。
根据您在大型Grails项目上的实际经验,您对此有何看法?
如果我们编写一个单元测试,测试完全相同的方法,并编写集成测试,也测试完全相同的方法,这是编写测试的正常方法吗?
在实际大型Grails项目中,您在单元测试与集成测试的比率方面最终得到了什么?
您是否成功完成了大型Grails项目而未编写任何测试?
答案 0 :(得分:12)
如果可能的话,我总是将我的测试编写为单元测试。我这样做是因为:
我要编写集成测试的一个示例是我是否要测试我在resources.groovy
中定义的Spring bean。虽然我可以实例化该类并直接测试它,但我的测试需要知道该bean的当前实现类(可能会改变)。
从长远来看,我认为编写集成测试实际上更复杂,因为随着时间的推移维护它们的成本高于单元测试。 Groovy / Grails对模拟/存根提供了极好的支持,因此在单元测试中模拟依赖关系的成本相对较低。以下是我单位测试中的一个真实示例,其中我:
messageSource
Spring bean validate()
方法,检查.errors
属性等。class MyUnitTests extends GrailsUnitTestCase {
MessageSource messageSource
protected void setUp() {
super.setUp()
// mockForConstraintsTests is a method provided by GrailsUnitTestCase
[Complex, CategoryCommand].each {mockForConstraintsTests(it)}
// 'mockMessage' will be returned by every method call on messageSource
messageSource = {Object[] args -> "mockMessage"} as MessageSource
}
}
答案 1 :(得分:7)
我参与了3个大型应用程序,以及无数小型应用程序。我目前的项目包括单元测试和集成测试(目前有2110个单元测试和493个集成测试)。
我花了很多时间试图提高测试速度并使测试更易于维护。
我的集成测试通常是混合测试,如果我正在测试服务,我可能会模拟一些其他服务/方法被调用以确保我获得我想要的值,但留在其他集成部分来运用HQL或数据库集成。为此,我使用prototype instances of what are normally singleton services以便我可以使用服务实例,而不会污染以后的测试。
我发现build-test-data插件非常适合创建可维护的单元测试,因为它允许我创建测试数据,我明确填充我需要的部分并让插件填写其他所需的详细信息。在集成测试中创建测试数据对我来说比在单元测试中模拟它更容易。
如果你同时使用集成和单元测试,最终连续运行所有测试的速度将成为障碍。我的团队使用splitTests.groovy脚本来分离两个单独的线程,一个用于单元测试,一个用于集成测试。这使我们的测试速度提高了约40%。进一步的并行化是可能的,但是我们还没有去过那里(目前的grails gant脚本非常讨厌,我期待grails 2.0中的gradle重写。)
单元测试很适合击中方法的所有条件角落和缝隙(尽管如果你有太多,你的圈复杂度可能太高,你应该重构)。集成测试对于执行数据库和服务集成非常有用,并且可以帮助您了解更改代码时已损坏的内容。
我认为,从高测试覆盖率中获得的重构勇气部分取决于某些测试是集成测试。如果您所有的单元测试都不与其他代码片段交互,那么当您进行代码更改时,您不会收到受影响区域的警报,并且因为groovy是一种动态语言,编译器可能无法帮助您查找这些领域要么。
答案 2 :(得分:0)