有两种常量:
1) 方便/可读性的常量
使用 TDD 编写代码时,生产代码的每一行都应该存在,因为首先需要编写该代码的测试失败。当你重构代码时,一些魔法值将被提升为常量。其中一些可能也可以作为应用程序设置,但为了方便(更少代码),它们已在代码中而不是外部配置文件中进行配置。
在这种情况下,我编写测试的方式,生产代码和测试代码都将使用相同的常量。测试将指定常量按预期使用。但是测试不会重复常量的值,例如在“assert MAX_ITEMS == 4”中,因为那将是重复的代码。相反,测试将检查某些行为是否正确使用了常量。
例如,here 是一个示例应用程序(由我编写),它将打印指定长度的 Longcat。如您所见,Longcat 被定义为一系列常量:
public class Longcat {
// Source: http://encyclopediadramatica.com/Longcat
public static final String HEAD_LINES = "" +
" /\\___/\\ \n" +
" / \\ \n" +
" | # # | \n" +
" \\ @ | \n" +
" \\ _|_ / \n" +
" / \\______ \n" +
" / _______ ___ \\ \n" +
" |_____ \\ \\__/ \n" +
" | \\__/ \n";
public static final String BODY_LINE = "" +
" | | \n";
public static final String FEET_LINES = "" +
" / \\ \n" +
" / ____ \\ \n" +
" | / \\ | \n" +
" | | | | \n" +
" / | | \\ \n" +
" \\__/ \\__/ \n";
...
测试验证常量使用正确,但不会重复常量的值。如果我改变一个常数的值,所有的测试都会自动使用新的值。 (而且 Longcat ASCII 艺术看起来是否正确,需要手动验证。尽管您甚至可以通过验收测试自动化,这对于更大的项目是值得推荐的。)
public void test__Longcat_with_body_size_2() {
Longcat longcat = factory.createLongcat(2);
assertEquals(Longcat.BODY_LINE + Longcat.BODY_LINE, longcat.getBody());
}
public void test__Fully_assembled_longcat() {
Longcat longcat = factory.createLongcat(2);
assertEquals(Longcat.HEAD_LINES + longcat.getBody() + Longcat.FEET_LINES, longcat.toString());
}
2) 通用常量
同样的应用程序也有一些永远不会改变的常数,例如米和英尺之间的比率。这些值可以/应该硬编码到测试中:
public void test__Identity_conversion() {
int feet1 = 10000;
int feet2 = FEET.from(feet1, FEET);
assertEquals(feet1, feet2);
}
public void test__Convert_feet_to_meters() {
int feet = 10000;
int meters = METERS.from(feet, FEET);
assertEquals(3048, meters);
}
public void test__Convert_meters_to_feet() {
int meters = 3048;
int feet = FEET.from(meters, METERS);
assertEquals(10000, feet);
}
生产代码如下:
public enum LengthUnit {
METERS("m", 1.0), FEET("ft", 0.3048), PETRONAS("petronas", 451.9), LINES("lines", 0.009);
private final String name;
private final double lengthInMeters;
...
public int from(int length, LengthUnit unit) {
return (int) (length * unit.lengthInMeters / this.lengthInMeters);
}
}
请注意,我没有为Petronas Twin Towers 的高度编写任何测试,因为该信息是声明性的(声明性数据很少被破坏)并且我已经为转换逻辑编写了测试(见上文)。如果添加更多类似的常量(埃菲尔铁塔、帝国大厦等),它们将由应用程序自动定位并按预期工作。