很抱歉这么晚才跳进去。有类似的需求,我开发了许多演示文稿和培训,展示了重构后给定类随时间的变化。因此,测试是相同的,但类本身会发生变化。每个版本都包含在不同的包中。类名保持不变。这听起来与OP所面临的相似。
我发现参数化解决方案很麻烦。我使用了两种解决方案。它们都是用 Groovy 编写的,但下面的第二个示例应该可以作为纯 Java 解决方案来实现。
这是第一个:
public class ItemTest {
def defaultConstructedClasses = [
new com.groovifyingjava.essentialgroovification.Item()
,new com.groovifyingjava.rewriteequals.Item()
,new com.groovifyingjava.removesemicolons.Item()
,new com.groovifyingjava.removeparentheses.Item()
,new com.groovifyingjava.removeaccessors.Item()
,new com.groovifyingjava.removeconstructors.Item()
,new com.groovifyingjava.removeimports.Item()
,new com.groovifyingjava.removereturn.Item()
,new com.groovifyingjava.clarifyidentityequality.Item()
,new com.groovifyingjava.coercetypes.Item()
,new com.groovifyingjava.defaultaccessmodifiers.Item()
,new com.groovifyingjava.eachiteration.Item()
,new com.groovifyingjava.fieldaccessnotation.Item()
,new com.groovifyingjava.namedparameters.Item()
,new com.groovifyingjava.optionaldatatyping.Item()
,new com.groovifyingjava.safelynavigate.Item()
,new com.groovifyingjava.simplifylistmapsetcreation.Item()
,new com.groovifyingjava.stringinterpolation.Item()
,new com.groovifyingjava.useelvisoperator.Item()
,new com.groovifyingjava.useequalsoperator.Item()
,new com.groovifyingjava.usemathoperators.Item()
,new com.groovifyingjava.useprintln.Item()
]
def overloadedConstructorArgs = [itemId: "14-101", manufacturer: "Raleigh", model: "Superbe Roadster", cost: 179.89, quantityOnHand: 10]
def overloadedConstructedClasses = [
new com.groovifyingjava.essentialgroovification.Item(overloadedConstructorArgs)
,new com.groovifyingjava.rewriteequals.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removesemicolons.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removeparentheses.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removeaccessors.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removeconstructors.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removeimports.Item(overloadedConstructorArgs)
,new com.groovifyingjava.removereturn.Item(overloadedConstructorArgs)
,new com.groovifyingjava.clarifyidentityequality.Item(overloadedConstructorArgs)
,new com.groovifyingjava.coercetypes.Item(overloadedConstructorArgs)
,new com.groovifyingjava.defaultaccessmodifiers.Item(overloadedConstructorArgs)
,new com.groovifyingjava.eachiteration.Item(overloadedConstructorArgs)
,new com.groovifyingjava.fieldaccessnotation.Item(overloadedConstructorArgs)
,new com.groovifyingjava.namedparameters.Item(overloadedConstructorArgs)
,new com.groovifyingjava.optionaldatatyping.Item(overloadedConstructorArgs)
,new com.groovifyingjava.safelynavigate.Item(overloadedConstructorArgs)
,new com.groovifyingjava.simplifylistmapsetcreation.Item(overloadedConstructorArgs)
,new com.groovifyingjava.stringinterpolation.Item(overloadedConstructorArgs)
,new com.groovifyingjava.useelvisoperator.Item(overloadedConstructorArgs)
,new com.groovifyingjava.useequalsoperator.Item(overloadedConstructorArgs)
,new com.groovifyingjava.usemathoperators.Item(overloadedConstructorArgs)
,new com.groovifyingjava.useprintln.Item(overloadedConstructorArgs)
]
@Test public void canCreateDefaultInstance() {
for(def item in defaultConstructedClasses) {
assertNull "Default construction of class ${item.class.name} failed to properly initialize field.", item.itemId
assertNull "Default construction of class ${item.class.name} failed to properly initialize field.", item.manufacturer
assertNull "Default construction of class ${item.class.name} failed to properly initialize field.", item.model
assertNull "Default construction of class ${item.class.name} failed to properly initialize field.", item.cost
assertEquals "Default construction of class ${item.class.name} failed to properly initialize field.", 0, item.quantityOnHand
assertEquals "Default construction of class ${item.class.name} failed to properly initialize field.", BigDecimal.ZERO, item.inventoryValue as BigDecimal
}
}
@Test public void canCreateInstancesFromOverloadedConstructor() {
for(def item in overloadedConstructedClasses) {
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.","14-101", item.itemId
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", "Raleigh", item.manufacturer
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", "Superbe Roadster", item.model
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", 179.89, item.cost
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", 10, item.quantityOnHand
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", new BigDecimal("1798.90"), item.inventoryValue as BigDecimal
}
}
}
这很好用并且很容易实现。它使用 Groovy 鸭子类型来测试每个类。缺点是 Eclipse 中的 junit 控制台将显示最后一次测试运行。这可能没什么大不了的。此外,它会因测试失败而停止执行。请注意,我在断言消息字符串中包含了类名。这使得识别失败的类变得容易。
第二个版本需要一个抽象测试类,每个包中都有一个测试类,对应于被测类的每个包。这些只是存根,但允许您谨慎地或在套件中运行测试。
public abstract class CommonItemTest {
def overloadedConstructorArgs = [itemId: "14-101", manufacturer: "Raleigh", model: "Superbe Roadster", cost: 179.89, quantityOnHand: 10]
@Test public void canCreateDefaultInstance() {
def item = defaultConstructedClass
assertNull "Default construction of class ${item.class.name} failed to properly initialize field. Expected itemId to be null.", item.itemId
assertNull "Default construction of class ${item.class.name} failed to properly initialize field. Expected manufacturer to be null.", item.manufacturer
assertNull "Default construction of class ${item.class.name} failed to properly initialize field. Expected model to be null.", item.model
assertNull "Default construction of class ${item.class.name} failed to properly initialize field. Expected cost to be null.", item.cost
assertEquals "Default construction of class ${item.class.name} failed to properly initialize field. Expected quantityOnHand to be zero.", 0, item.quantityOnHand
assertEquals "Default construction of class ${item.class.name} failed to properly initialize field. Expected inventoryValue to be zero.", BigDecimal.ZERO, item.inventoryValue as BigDecimal
}
@Test public void canCreateInstancesFromOverloadedConstructor() {
def item = overloadedConstructedClass
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.","14-101", item.itemId
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", "Raleigh", item.manufacturer
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", "Superbe Roadster", item.model
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", 179.89, item.cost
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", 10, item.quantityOnHand
assertEquals "Instantiation of class ${item.class.name} using overloaded constructor failed to properly initialize field.", new BigDecimal("1798.90"), item.inventoryValue as BigDecimal
}
abstract Object getDefaultConstructedClass();
abstract Object getOverloadedConstructedClass();
}
和实施...
public class ItemTest extends CommonItemTest {
public Object getDefaultConstructedClass() {
return new Item()
}
public Object getOverloadedConstructedClass() {
return new Item(overloadedConstructorArgs)
}
}