除了在实际的dbunit网站上推荐的那些之外,还有哪些最佳实践/原则可以大大加快测试速度并使其保持可维护性?我渴望java的library like factory girl,但由于静态类型,它看起来不太可能。
我目前的想法是,此时每个测试类有1个xml数据集 - 也许我会分享其中一些,也许我不会。虽然一些测试数据可能是复制的交叉数据集,但我发现在3000个单元/集成测试中维护共享数据集太难了 - 而且我还有很长的路要走。
非常感谢遵循的任何原则,导致测试表现良好且易于维护。
答案 0 :(得分:8)
在我之前的一项任务中,我们有数百个涉及数据集的集成测试,但不是在DBUnit中 - 测试环境是从头开始编写的,因为它是一个非常大的公司,可以负担这种东西。
数据集按层次结构组织。被测系统由几个(5-10)模块组成,测试数据遵循该模式。单元测试脚本如下所示:
include(../../masterDataSet.txt)
include(../moduleDataSet.txt)
# unit-specific test data
someProperty=someData
属性名称通过一些我不记得的奇怪工具直接映射到DB记录。
相同的模式可以应用于DBUnit测试。在主数据集中,您可以放置始终需要的记录 - 比如字典,数据库的初始加载,就像从头开始安装一样。
在模块数据集中,您可以将涵盖大多数测试的测试用例的记录放入模块中;我不认为你的平均测试涉及所有70个数据库表,是吗?您肯定必须拥有一些可构成模块的功能组,即使应用程序是单片的。尝试围绕它组织模块级测试数据。
最后,在测试级别,您只需修改测试集,并且只需要为此特定测试所需的最少记录数。
这种方法具有学习的巨大好处;因为数据文件很少,所以你实际上开始记住它们。您可以轻松地了解任何两个数据集的差异,而不是看到数百个大数据集只有不明显的细节(每次您在一段时间后再次进行测试时都必须找到)。
最后谈到表现。在我的2.4 GHz 2核WinXP机器上进行DBUnit测试,包括:
需要1-3秒。日志显示前3个操作只需不到一秒钟,大部分测试时间都由Spring消耗。每个测试都执行此逻辑,以避免测试顺序依赖性。所有东西都在一个带有嵌入式Derby的虚拟机中运行,这可能就是为什么它如此之快。
编辑:我认为DBUnit XML数据集不支持包含其他测试文件,可以通过为所有集成测试使用基类来克服它,例如:
public class AbstractITest {
@Before
public void setUp() throws Exception {
//
// drop and recreate tables here if needed; we use
// Spring's SimpleJdbcTemplate executing drop/create SQL
//
IDataSet masterDataSet = new FlatXmlDataSetBuilder().build("file://masterDataSet.xml");
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, dataSet);
}
}
public class AbstractModuleITest extends AbstractITest {
@Before
public void setUp() throws Exception {
super.setUp();
IDataSet moduleDataSet = new FlatXmlDataSetBuilder().build("file://moduleDataSet.xml");
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection, moduleDataSet);
}
}
public class SomeITest extends AbstractModuleITest {
// The "setUp()" routine only here if needed, remember to call super.setUp().
@Test
public void someTest() { ... }
}
答案 1 :(得分:3)
Junit in Action 2e中的建议实际上并不是创建太多数据集(如每个测试类一个),但只是足够被认为是可维护的。除了一些例外情况,我发现可以使用主数据集进行大多数单元测试,并使用单个数据集进行集成测试。限制ExpectedDataSets的使用也是一种选择。
此外,我将Unitils与dbunit结合使用以简化测试数据的一些设置和加载,因此您可能需要在适当的时候考虑它。