Модульні тести Java, верстка каталогу [закрито]


76

Створюючи набір модульних тестів для коду Java, чи існує домовленість про те, де розмістити тестовий код стосовно вихідного коду?

Наприклад, якщо у мене є каталог, /javaякий містить купу .javaвихідних файлів, то краще поставити тестові кейси в /javaсебе або використовувати щось на зразок /java/test.

Якщо останній є кращим, як перевірити внутрішні елементи коду, коли private / protectedчлени класу недоступні поза пакетом?

Відповіді:


73

Ви можете помістити тести в той самий пакет, що і оригінальні класи, навіть якщо вихідний код знаходиться у власному кореневому каталозі:

PROJECT_ROOT
    +--- src/
    +----test/

Ви можете оголосити клас com.foo.MyClassпід srcта його тест com.foo.MyClassTestпід test.

Що стосується доступу до приватних членів, ви можете використовувати рефлексію для виклику методів (зміна їхньої доступності через Class.getDeclaredMethod.setAccessible), або ви можете використовувати щось на зразок testng / junit5, щоб поставити деякі тести, керовані анотаціями, на сам вихідний код (я особисто думаю, що це погана ідея).

Чому б не перевірити деякі проекти, java.netщоб побачити, як вони організували щось, наприклад swinglabs (сховище SVN працює досить повільно, боюся)?


117

Я рекомендую слідувати стандартній структурі каталогів Apache Software Foundation , яка дає такий результат:

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

Це зберігає тести окремо від джерела, але на одному рівні в структурі каталогів. Якщо ви прочитаєте, як Apache визначає їх структуру, ви побачите, що це допомагає розділити й інші проблеми, включаючи ресурси, конфігураційні файли, інші мови тощо.

Ця структура також дозволяє модульним тестуванням тестувати пакет та методи захищеного рівня тестованих блоків, припускаючи, що ви поміщаєте свої тестові кейси в той самий пакет, що і те, що вони тестують. Щодо тестування приватних методів - я б не заважав. Щось інше, або загальнодоступне, або пакетне, або захищене викликає їх, і ви повинні мати можливість отримати повне тестове покриття, тестуючи ці речі.

До речі, посилання вище посилається на Maven, стандартний інструмент побудови Apache. Кожен проект Java, який у них є, відповідає цьому стандарту, а також кожен проект, з яким я стикався, створений за допомогою Maven.


6
+1 Навіть якщо ви не використовуєте maven, непогано дотримуватися цього макета (свого роду фактичний стандарт, заснований на найкращих галузевих практиках).
Паскаль Тивент,

7
Єдина причина, за якою тут згадується Maven, полягає в тому, що веб-сайт - це одне місце, де задокументовано стандартне розташування каталогів Apache. Ваше вподобання чи не подобається йому не має значення щодо того, чи є відповідна структура каталогів належною. Можливо, ви можете прокоментувати відповідь, яка відповідає вашій думці, щоб вказати, чому ця структура каталогів вища.
SingleShot

1
Якщо ви кодуєте на чистій Java, javaкаталог є непотрібним доповненням
oxbow_lakes

6
Ну, слід зазначити, що зазвичай mainі testпапки, і папки мають resourcesвихідну папку, яка компілюється в ту саму вихідну папку, що javaробить папка, що дозволяє легко відокремити код Java та файли ресурсів на вихідному рівні. Мені також подобається ця структура, оскільки вона зберігає верхній рівень без кількох вихідних папок ... це дуже логічна організація. І так, це не має нічого спільного з тим, подобається комусь Мейвен чи ні.
ColinD

3
Я зробив цей коментар вісім років тому. Відтоді я зрозумів і люблю Мейвен. Я без цього зараз не працюватиму. Люди можуть змінитися.
duffymo

8

Найчастіше це робиться так:

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

Отже, ви тримаєте їх окремо, і ви все ще можете протестувати пакет / захищену функціональність, оскільки тест знаходиться в тому самому пакеті.

Ви не можете перевірити приватні речі, якщо це не оголошено всередині класу.

Після доставки ви просто запаковуєте .classзгенеровані src, а не тести


1
тест повинен знаходитись у папці src. maven.apache.org/guides/introduction/…
Філіп Рего,

5

Насправді має великий сенс розділити ваші виробничі та тестові проекти на 2 окремі сутності, але мати однакову структуру пакету в обох проектах.

Отже, якщо у мене є проект "my-project", я також створюю "my-project-test", тому у мене є така структура каталогів:

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

Цей підхід гарантує, що залежності тестового коду не забруднюють виробничий код.

На мою особисту думку, пакетні приватні та захищені методи повинні бути протестовані, а також загальнодоступні. Отже, я хочу, щоб мої тестові класи були в тому самому пакеті, що і виробничі класи.


2

Ось як у нас це налаштовано, і нам це подобається.

build/
src/
test/build/
test/src/

Весь код тестування компілюється у власний каталог побудови. Це тому, що ми не хочемо, щоб виробництво містило тестові класи помилково.


1

При створенні модуля бібліотеки Java в Android Studio він створює клас за замовчуванням під:

[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, а ваші файли внизу будуть включені в модуль.

Я припускаю, що ця структура є рекомендованим макетом для коду та тестів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.