Java单元测试,目录结构

85

在构建Java代码的单元测试套件时,是否有惯例来确定测试代码放置的位置?

例如,如果我有一个包含许多.java源文件的目录 /java ,是将测试用例放置在 /java 中好还是使用诸如 /java/test 的其他目录更好。

如果后者更可取,那么当类的 private / protected 成员在包外不可用时,如何测试代码的内部?

6个回答

129

我建议跟随Apache软件基金会的标准目录结构,这将产生以下结果:

module/
  src/
    main/
      java/
    test/
      java/

这样可以将测试与源代码分离,但在目录结构中保持相同级别。如果你阅读Apache如何定义他们的结构,你会发现它也有助于将其他关注点分开,包括资源、配置文件、其他语言等。

这种结构还允许单元测试来测试被测试单元的包和受保护级别方法,只要你把测试用例放在与所测试内容相同的包中。至于测试私有方法,我不会去烦恼。其他某些东西(公共的、包内的或受保护的)会调用它们,你应该能够通过测试这些东西来获得完整的测试覆盖率。

顺便说一下,上面的链接是指Maven,Apache的标准构建工具。他们所有的Java项目都符合此标准,我遇到的每个使用Maven构建的项目都是如此。


7
即使您不使用Maven,遵循这种布局(一种基于行业最佳实践的事实标准)也是一个好主意。 - Pascal Thivent
8
之所以提到Maven,只是因为它的网站是Apache标准目录布局文档的一个来源。你对它喜欢或不喜欢与该目录结构是否好无关。也许你可以评论一个符合你意见的答案,说明为什么该目录结构更优秀。 - SingleShot
1
如果您正在使用纯Java编码,则“java”目录是不必要的附加项。 - oxbow_lakes
6
通常情况下,maintest 文件夹都有一个名为 resources 的源文件夹,其编译成与 java 文件夹相同的输出文件夹,这样在源代码级别上可以轻松分离 Java 代码和资源文件。我喜欢这种结构,因为它使得顶层文件夹不会有多个源文件夹...这是一个非常合理的组织方式。是的,这与是否喜欢 Maven 没有任何关系。 - ColinD
3
我在八年前发表了那个评论。此后我逐渐理解并喜爱上了Maven。现在我已经离不开它了。人是会改变的。 - duffymo
显示剩余7条评论

83

即使源代码位于自己的目录根目录下,您也可以将测试放在与原始类相同的包中:

PROJECT_ROOT
    +--- src/
    +----test/
你可以在src下声明一个com.foo.MyClass类,它的测试com.foo.MyClassTest可以在test下进行。至于访问私有成员,你可以使用反射来调用方法(通过Class.getDeclaredMethod.setAccessible更改其访问权限),或者你可以使用像testng / junit5这样的工具将一些基于注释的测试放在源代码本身上(我个人认为这是个坏主意)。为什么不去看看一些在java.net上的项目,比如 swinglabs(我恐怕SVN存储库非常慢)?

11

大多数情况下是这样完成的:

<SOME_DIR>/project/src/com/foo/Application.java
<SOME_DIR>/project/test/com/foo/ApplicationTest.java

因此,您将它们分开,仍然可以测试包/受保护的功能,因为测试位于相同的包中。

除非私有内容在类内部声明,否则无法测试私有内容。

交付时,只需打包由src生成的.class文件,不包括测试文件。


1
测试应该在src文件夹中。https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html - Philip Rego

7

将生产和测试项目分开成两个单独的实体,但是在两个项目中保持相同的包结构是有很多道理的。

因此,如果我有一个项目“my-project”,我还会创建“my-project-test”,这样我就有了以下目录结构:

my-project
  +--- src/com/foo
my-project-test
  +---test/com/foo

这种方法确保测试代码的依赖不会污染生产代码。
在我个人看来,包私有和受保护的方法也应该像公共方法一样进行测试。因此,我希望我的测试类与生产类在同一个包中。

2
这是我们的设置方式,我们很喜欢它。
build/
src/
test/build/
test/src/

所有测试代码编译到自己的构建目录中。这是因为我们不希望生产环境中错误地包含测试类。


1
Android Studio中创建一个Java库模块时,它会在以下位置创建一个默认类:
[module]
   + src/main/java/[com/foo/bar]

如果您查看[module].iml文件,您将找到该路径以及测试路径,您可以利用。以下是摘要:
<module>
  <component>
    <content>
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
    </content>
  </component>
</module>

你可以做的是为测试创建一个目录,具体结构如下:
[module]
   + src/main/java/[com/foo/bar]
   + src/test/java/[com/foo/bar]

上述结构将被 Android Studio识别,并且您的文件将被包含在模块中。
我假设该结构是代码和测试的推荐布局。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接