在测试和真实代码之间复制数据是好是坏?例如,假设我有一个Python类FooSaver
,该类将具有特定名称的文件保存到给定目录:
class FooSaver(object):
def __init__(self, out_dir):
self.out_dir = out_dir
def _save_foo_named(self, type_, name):
to_save = None
if type_ == FOOTYPE_A:
to_save = make_footype_a()
elif type == FOOTYPE_B:
to_save = make_footype_b()
# etc, repeated
with open(self.out_dir + name, "w") as f:
f.write(str(to_save))
def save_type_a(self):
self._save_foo_named(a, "a.foo_file")
def save_type_b(self):
self._save_foo_named(b, "b.foo_file")
现在,在我的测试中,我想确保所有这些文件均已创建,因此我想说一下这样的话:
foo = FooSaver("/tmp/special_name")
foo.save_type_a()
foo.save_type_b()
self.assertTrue(os.path.isfile("/tmp/special_name/a.foo_file"))
self.assertTrue(os.path.isfile("/tmp/special_name/b.foo_file"))
尽管这会在两个位置上复制文件名,但我认为这很好:它迫使我准确写下我希望输出的另一端内容,它增加了防止错别字的保护层,并且通常使我对一切正常充满信心完全符合我的期望。我知道,如果将来更改a.foo_file
为type_a.foo_file
,则必须在测试中进行一些搜索和替换,但是我认为这没什么大不了的。如果我忘记更新测试以换取确保我对代码和测试的理解是同步的,我宁愿有一些误报。
一位同事认为这种重复是不好的,因此建议我将双方重构为以下形式:
class FooSaver(object):
A_FILENAME = "a.foo_file"
B_FILENAME = "b.foo_file"
# as before...
def save_type_a(self):
self._save_foo_named(a, self.A_FILENAME)
def save_type_b(self):
self._save_foo_named(b, self.B_FILENAME)
并在测试中:
self.assertTrue(os.path.isfile("/tmp/special_name/" + FooSaver.A_FILENAME))
self.assertTrue(os.path.isfile("/tmp/special_name/" + FooSaver.B_FILENAME))
我不喜欢这样,因为它不能使我确信代码是否按预期工作了---我只是out_dir + name
在生产端和测试端重复了这一步骤。在理解+
字符串的工作方式时,它不会发现错误,也不会捕获错别字。
另一方面,它比两次写出这些字符串要容易得多,并且在这样的两个文件之间复制数据似乎有点不对劲。
这里有明确的先例吗?是否可以在测试和生产代码之间复制常量,还是太脆弱了?