将JUnit测试方法放入测试类是不好的做法?

时间:2017-02-16 12:06:26

标签: java junit

考虑一个带有小型库式静态方法的Java类。

将JUnit测试方法放在同一个类中是不是很糟糕?

我看到以下专业人士:

  • JUnit测试作为自我文档就在方法代码
  • 附近
  • 将此代码移动到另一个类或包中会很容易

对比是什么,为什么始终将测试代码分开是一般做法?

一个例子:

import org.junit.*;

public class HtmlUtils {
    public static String normalizeBrs(String html) {
        return html.replaceAll("<br\\s*/?>", "<br/>");
    }

    @Test
    public void testNormalizeBrs() {
        Assert.assertEquals(normalizeBrs("hello <br /> world <br>"), "hello <br/> world <br/>");
    }
}

6 个答案:

答案 0 :(得分:4)

(将JUnit测试方法放入测试类中是不好的做法?)

<强>绝对

这里的关键原因是: single responsibility principle 。编程中的类,方法,任何事物应该支持/提供一个责任。

您的生产代码的核心职责是实现其“生产目的”。

换句话说:业务逻辑是业务逻辑。没有 else

任何不属于该存储桶的东西...... 某处其他

测试是一种“事物”,方面,责任,无论你如何命名。

更典型的方法是为生产和测试代码提供不同的项目。

当你的生产类是x.y.Z ...那么测试类将是x.y.ZTest;但是虽然它们位于同一个包中,但通常会将它们放在不同的源位置文件夹中。

除此之外:对于Java来说,重构可以被视为2017年的“解决问题”。将方法转移到不同的类中,或者更改包名称是如此简单,以至于你(绝对)做到了不用担心。 (如果重构对你来说太危险了,你考虑用测试代码污染你的生产代码,那么:学习如何使用现代工具)

此外,如果您将测试方法放在测试类中,您可能最终会测试内部实现。这不是你应该测试的。你应该测试类API;你的测试应该独立于内部实现。

答案 1 :(得分:2)

如果您的包裹很小,您可能不会发现任何差异。

但是想象一下,你有一个包含1000个类的包,然后拥有数以万计的方法。意味着数以万计的测试。

那么如果将所有代码+测试放在一起会发生什么?

对于类似的东西,你最终可能会用垃圾装载内存,而垃圾实际上永远不会用于任何目的。

这就是为什么一般练习总是鼓励你将它们分开。通过遵循这个较小的包装,你实际上也在为更大的项目进行自我训练。

答案 2 :(得分:1)

我们将源代码与测试代码分开。

以下是我所知道的原因。

  1. 我们为生产创建源代码的构建,它不应包含测试代码。代码大小不必要的增加。
  2. 单独的测试项目有帮助。这样我们就可以在定期间隔后对源进行测试构建,以检查是否所有内容都在检查中。例如通常的做法是,当您进行代码更改并推送代码时,会触发这些测试版本,然后根据它检查您的新更改。
  3. 测试用例仅供内部使用,以确保我们保持代码质量。大多数客户对此不感兴趣。
  4. 随意在此列表中添加更多内容。

    干杯!!!

答案 3 :(得分:1)

nafas

的答案外

将测试与源代码保持在同一位置

如果测试源与测试类保持在同一位置,则测试和类将在构建期间进行编译。这会强制您在开发期间保持测试和类的同步。实际上,未被视为正常构建的一部分的单元测试很快变得过时且无用。

http://www.javaworld.com/article/2076265/testing-debugging/junit-best-practices.html http://www.kyleblaney.com/junit-best-practices/

答案 4 :(得分:1)

如果您在生产代码中进行了测试,那么:

  1. 你的生产代码(例如Mockito,......)你将有额外的依赖关系(因此需要更大的jar / war / ear文件大小,更多的加载时间,更多的内存资源),这对于应用程序运行
  2. 您的类中将有其他属性,需要内存资源,并且可能与应用程序属性的属性冲突
  3. 测试方法必须是公开的,因此测试方法是生产代码的api的一部分(对于想要使用您的应用程序代码的人来说这完全令人困惑)。
  4. 课程变得越来越难以维护
  5. 你正在伤害惯例,例如maven

答案 5 :(得分:0)

一个久经考验的模型是标准Maven项目布局和许多其他构建框架所使用的模型。

我们有单独的src/mainsrc/test目录,但它们都在同一个项目中。

src/main包含所有生产代码,没有别的。

src/test包含单元测试。

构建配置指定依赖项,并且知道测试类和生产类之间的区别。

测试需要一些依赖项。最根本的是,jUnit本身。也像嘲笑库(JMock,Mockito),像Hamcrest这样的工具,像WireMock或RestClientDriver这样的工具,你自己的测试库等等。

您不需要这些库来运行生产代码,因此您不应将它们捆绑在构建中,也不要将构建声明为依赖项。

在测试驱动的项目中,您通常希望拥有比生产代码更多的测试代码行。所以包括测试代码会严重增加您的发行版的大小。

Maven在编译和运行测试时将测试依赖项放在类路径中,但在编译生产代码时将它们放在类路径中。这意味着如果您尝试在生产类中使用jUnit,Mockito等,您将收到编译错误 - 这就是您想要的。

所以:

  • 生产代码及其相应的测试位于同一项目中的单独目录中
  • 构建分发包括编译和运行测试
  • 构建的工件不会超过必要的,因为它不包含测试代码

所有这些还具有Java程序员倾向于熟悉此布局的优点。程序员不要惊讶。

您的观察:

  • “作为自我文档的JUnit测试就在方法代码附近”

这是一个有效的观察,并且有一些写作的先例 为此原因进行内联测试。但是,它往往存在于分布式代码的大小无关紧要的环境中,或者存在剥离或忽略作为构建的一部分的测试代码的方法。例如,在C中,测试可能在#IFDEF TEST预处理程序指令中。这样可以避免在删除“测试”代码时删除软件实际工作所需的内容 - 即仅在测试代码存在时才有效的代码!

因为Maven布局对Java程序员来说非常熟悉,所以他们知道在哪里 找单元测试。许多IDE(或插件)允许您通过击键在类及其单元测试之间切换 - 只要遵循命名约定。

  • “很容易将此代码移动到另一个类或包”

在实践中,这很少是一个问题,但是一些IDE(或插件)无论如何都会使它自动化。例如,我相信在IntelliJ IDEA中,如果你重命名一个类,或者将它移动到另一个包,它的相应测试类也会被重命名或移动 - 只要你遵循命名约定。

-

我建议您采用这些完善的做法,无论是使用Maven,Gradle还是其他一些构建系统。