Соглашение об именах для тестовых пакетов

11

На самом деле мы называем наши тестовые пакеты так же, как их тестовые аналоги. Таким образом, мы в конечном итоге с этой структурой:

src/main/java
    com.hello.world
        helloWorld.java
src/test/java
    com.hello.world
        helloWorldTest.java

Я всегда чувствовал, что это не очень умно, так как вы не можете различить «тест» и «тестировать», только если указаны с именем пакета. С другой стороны, я не нашел случая, чтобы это как-то значило. Является ли хорошей практикой иметь одинаковые соглашения об именах для обоих пакетов (для тестовых случаев и исходных классов)? Если нет, то какой подход лучше?

OddDev
источник
1
Не знаю, хорошая ли это практика, но популярная. Другой вариант (поместить «Test» в имя пакета, имена методов и т. Д.) Слишком сильно напоминает «Smurf naming». Как вы говорите, трудно представить себе случай, когда не удастся «различить« test »и« to-test », если он предоставляется только с именем пакета».
Дэвид Арно
@DavidArno Спасибо за ваш вклад :) Как избежать смарф-имен? Я имею в виду, мы бы закончили с com.hello.world.test.helloWorld.java, не так ли?
OddDev
Проблема "smurf" больше, когда у вас есть метод XXXTest()в com.hello.world.test.helloWorldTest.java. Общим советом было бы, чтобы «Test» появлялся только один раз в пути, поэтому либо (a) используйте test в имени пакета (и назовите тестовый файл так же, как и тестируемый файл), либо (b) сделайте имя пакета то же самое и добавьте «test» к имени файла / класса.
Дэвид Арно
@DavidArno Ах, спасибо за разъяснения! Я неправильно понял ваш первый комментарий. Я понял.
OddDev
Ну, я бы сказал, что, если неясно, я ошибся в своем первом комментарии :)
David Arno

Ответы:

11

Это хорошая конвенция.

Иногда вы также хотите написать модульные тесты для закрытых пакетов классов и методов. Вы не сможете вызывать их из класса юнит-теста, помещенного в другой пакет.

Не должно быть никакой путаницы в том, что классы модульных тестов должны находиться в одном и том же пространстве имен, поскольку их не должно быть в пути к классам при компиляции или запуске производственного кода.

Вот пример небольшого модуля с общедоступным интерфейсом, общедоступным классом фабрики и двумя частными классами реализации пакета:

src/main/java:
    com.hello.transmogrifier
        public interface Transmogrifier
        public class TransmogrifierFactory
        class MapTransmogrifier implements Transmogrifier
        class ListTransmogrifier implements Transmogrifier

scr/test/java:
    com.hello.transmogrifier
        public class TransmogrifierFactoryTest
        public class MapTransmogrifierTest
        public class ListTransmogrifierTest

Скрытие реализаций интерфейса Transmogrifier может быть правильным выбором дизайна. Возможно, ответственность за выбор реализации лежит на классе фабрики.

Поскольку реализации являются пакетно-частными, вам нужно поместить классы модульного тестирования в один и тот же пакет, если вы хотите проверить их напрямую. Если у вас есть классы модульных тестов в каком-то другом пакете, у вас есть только прямой доступ к общедоступному интерфейсу и классу фабрики из ваших тестов.

РОДОМ ИЗ
источник
1
Msgstr "Обычно вы хотите написать модульные тесты для приватных классов и методов". Нет! Это действительно плохая практика. Закрытые типы пакетов являются деталями реализации и никогда не должны тестироваться напрямую. Только тестируйте публичные API.
Дэвид Арно
1
@DavidArno Я не согласен. Однако я заменил слово «обычно» словом «иногда», чтобы избежать этого конкретного обсуждения.
Приходите с
1
Вы можете не соглашаться со всем, что хотите, но тестирование внутренней работы фрагмента кода приводит как к тесной связи между этими внутренними работами и тестами, так и к хрупким тестам, которые легко ломаются даже при простом рефакторинге. Это очень плохая практика.
Дэвид Арно,
Если я хочу убедиться, что все мои реализации Transmogrifier работают, независимо от того, что делает фабрика, я собираюсь написать модульные тесты, которые тестируют каждую реализацию. Обратите внимание, что реализации имеют общий публичный API, хотя классы являются частными для пакета. Эти тесты не должны нарушаться, если я не изменю публичный API. На самом деле, я бы, вероятно, написал общий тест для Transmogrifier, а затем запускал его для каждой реализации. Хотя каждую реализацию можно получить с использованием фабрики, лучше не иметь такой зависимости при тестировании трансмогрификаторов.
Приходите с
Тогда один день, вы смотрите MapTransmogrifierи ListTransmogrifierи решить , что они могут быть сделаны в один класс, так что вы создаете ListMapTransmogrifier, измените завод , чтобы использовать этот и удалить эти два класса. Код теперь не компилируется, поэтому вы должны изменить каждый тест в обоих MapTransmogrifierTestи ListTransmogrifierTestполучить его компиляцию. Тест не пройден. Было ли это из-за изменения тестов или создания ListMapTransmogrifier? Выходит отладчик, чтобы выяснить ... альтернативно, когда тесты используют фабрику, вы делаете этот рефакторинг и все еще компилирует ...
Дэвид Арно