Unit testing 单元测试及;冗长的设置字符串:样式/最佳实践

Unit testing 单元测试及;冗长的设置字符串:样式/最佳实践,unit-testing,Unit Testing,我对在单元测试中使用冗长的设置字符串的观点、实践和推荐的最佳实践感兴趣 您更喜欢在线声明测试、在测试附近声明测试,还是将测试外部化到某个文件中 注意,我所说的测试资产是特定于单个单元测试的,因此不一定适合使用setup()方法 我看到了这两种方法的优点/缺点——我非常喜欢让对测试重要的东西尽可能靠近测试,但是在测试方法中,几行字符串设置可能会很快变得很刺耳 例如,我正在编写一个快速解析器来从文件中去除未使用的css声明。我想测试给定一个特定的输入字符串,正确的文本被删除。我的测试已经变得非常嘈杂

我对在单元测试中使用冗长的设置字符串的观点、实践和推荐的最佳实践感兴趣

您更喜欢在线声明测试、在测试附近声明测试,还是将测试外部化到某个文件中

注意,我所说的测试资产是特定于单个单元测试的,因此不一定适合使用setup()方法

我看到了这两种方法的优点/缺点——我非常喜欢让对测试重要的东西尽可能靠近测试,但是在测试方法中,几行字符串设置可能会很快变得很刺耳

例如,我正在编写一个快速解析器来从文件中去除未使用的css声明。我想测试给定一个特定的输入字符串,正确的文本被删除。我的测试已经变得非常嘈杂与所有的字符串连接

public void removesStyleFromText() 
{
    StyleCleaner styleCleaner = new StyleCleaner();
    String source = ".presentInFileOne {\r\n" + 
            "}\r\n" + 
            "\r\n" + 
            ".presentInFileTwo {\r\n" + 
            "   bottom-corners-rounded : false;\r\n" + 
            "}\r\n" + 
            ".notUsed {\r\n" + 
            "}\r\n" + 
            "";

    String actual = styleCleaner.removeDeclaration(source , "notUsed");

    String expected = ".presentInFileOne {\r\n" + 
    "}\r\n" + 
    "\r\n" + 
    ".presentInFileTwo {\r\n" + 
    "   bottom-corners-rounded : false;\r\n" + 
    "}\r\n";

    assertEquals(expected , actual);
}
在这个例子中,我可以将实际的/预期的内容外部化到外部文件中,但这也使得测试对于它实际测试的目的有点不清楚


想法?

我会将字符串外部化,并就您测试的内容编写一些注释。注释还具有比这些字符串结构可读性强得多的优点。

当然是代码,它更容易立即告诉您正在测试什么,并且在您想要重用它时更容易重构。我喜欢让它保持干燥,所以我通常倾向于将它移动到构建器或具体类(取决于我正在做什么),这会为我提供一个默认配置,我可以为特定的测试查看它。

我个人更喜欢在这样的情况下保持字符串内联。字符串对于理解测试应该做什么很重要,因此必须从外部查找它似乎适得其反


如果您有很多相同的测试,它们只在输入的字符串和输出的字符串上有所不同,那么故事就有点不同了,您可能需要看看基于表的测试解决方案。在.Net中,您有mbunit。它允许您使用不同的预期输入/输出运行相同的测试,或者您可以查看Fitnesse之类的工具,这些工具允许您定义要测试的数据表。

我同意这种方式,因为这对于该测试非常重要,如果您在测试中依赖于“外部”的东西,则可以严格查看这不是一个严格的单元测试。

如果您使用支持正确字符串文本的编程语言,您的问题将消失。例如,Python支持多行字符串:

source = """
.presentInFileOne {
}

.presentInFileTwo {
       bottom-corners-rounded : false;
}
.notUsed {
}
"""

expected = """
.presentInFileOne {
}

.presentInFileTwo {
       bottom-corners-rounded : false;
}
"""

assert removeDeclaration(source, "notUsed") == expected
这样的语言结构将使您的测试比其他任何东西都更具可读性。

有一种方法需要改进。性能可能不是您希望在生产中看到的东西,但对于测试来说已经足够好了

我的规则是:如果字符串很小(<10行),我将它们保持在内联状态,但我可以始终将“”之间的所有内容剪切掉,然后粘贴新版本(这意味着如果需要,我将在assertEquals()中转换字符串)

如果字符串文字更长、更复杂,或者当我有一个好的编辑器(带有语法高亮显示等)时,我喜欢将它们保存在一个测试数据文件夹中,以测试名称作为文件名。然后,您可以在JUnit测试中使用一个实用函数,该函数使用getName()加载字符串,您将不需要任何魔法就能知道哪个文件属于哪个测试

如果有很多这样的文件,我会使用测试类名(class.getSimpleName())作为文件夹名来保持对它们的控制