Відповіді:
Організація ваших тестів є досить неважливою порівняно з важливістю їх взагалі.
Найголовніше для хорошого тестового набору - це те, що він охоплює всю функціональність; що гарантує, що щоразу, коли буде введено дефект регресії, ви помітите відразу. Незалежно від того, чи потрібно писати один тест для кожного методу, один тест для кожної комбінації вхідних значень методу або навіть один тест для кожного можливого кодового шляху в межах цього методу, є менш важливим. Чи організувати ці тести на кілька або декілька тестових класів, це ще менш важливо: тестовий набір завжди повинен мати успіх у повному обсязі, тому не має значення, чи не виходить один із трьох чи двох із сімнадцяти тестів - обидва помиляються та повинні бути фіксований.
Звичайно, тестовий код також є кодом, тому він повинен дотримуватися звичайних найкращих практик щодо того, щоб бути ремонтопридатним, модульним тощо. Але це повинно вирішуватись наскільки добре ремонтоване саме тестовий набір, а не те, як тестові класи ставляться до класи, які вони тестують. Обидві політики, які ви згадуєте, можуть допомогти вам запам'ятати, де знайти речі, якщо ви послідовно їх дотримуєтесь, але для цього важливіша послідовність, ніж вибір політики.
До вашого конкретного питання, умовою JUnit, є відповідність 1: 1 між вашими класами додатків ( Foo1.java
, Foo2.java
) та тестовими класами JUnit ( Foo1Test.java
,Foo2Test.java
).
З цього приводу я щиро погоджуюся з наголосом Кіліана на важливості духу / цілей тестування підрозділів у будь-яких організаційних схемах, які можуть бути використані. Вибирайте деякі умови і дотримуйтесь їх більшу частину часу, при цьому обережно допускайте винятки зі своїх конвенцій, коли вони мають гарантію.
Чи краще мати окремий клас для кожного методу або мати лише один тестовий клас для кожного фактичного класу?
Якщо у вас є необхідність писати окремі тестові класи для методів одного класу, то у вас неправильна конструкція. Методи повинні бути невеликими, легкими для читання, легкими для тестування та легкими для зміни. Тести можуть бути трохи довше, ніж оригінальний код через складання тестових даних, глузування тощо, але не повинні бути значно довшими. Якщо вони є, ваш тестовий клас занадто складний і напевно більше, ніж одне ( принцип єдиної відповідальності ): Працюйте над своїм дизайном.
Я думаю, що "один тестовий клас на метод" і "один тестовий клас на клас", як правило, занадто екстремальні.
Загалом, ви хочете мати одну перевірку на кожний метод випробування / одиницю тесту. Наприклад, це можуть бути декілька тверджень, щоб перевірити, чи є, list.isEmpty = true
і list.Length = 0
таким чином один тестовий метод / одиничний тест на поведінку.
Це дозволяє легко придумати назву методу тестування, що описує поведінку. Ви хочете згрупувати методи тестування в тестовому класі, тому коли ви читаєте test classname.test method
, це має сенс. Зазвичай у них є якийсь спільний код налаштування, який легко вставити в тестові установки / кріплення. Залежно від тестуваного класу, це може бути один тестовий клас для всього класу, а також може бути один тестовий клас для одного методу. Але зазвичай це буде десь посередині.
Як і у звичайному коді, ви хочете, щоб тести були максимально читабельними. Що мені допомагає - це дотримання стилю BDD, який дається коли-коли або організувати-діяти-стверджувати, щоб організувати тестовий код. Тестовий клас міг би дати це, це налаштування. Тоді кожен метод тестування в цьому класі використовує заданий (або його частину) і має один, коли і тоді.
Розгляньте також одиничні тести як документацію щодо використання функціональності тестового класу. Завдяки хорошим одиничним тестам, ви можете прочитати тести, щоб дізнатися, як використовувати функціональність класу, який ви хочете використовувати, і якими саме будуть ефекти.
Коли щось виходить з ладу, і тест не працює, ви хочете, щоб це було якомога простіше зрозуміти, що зламалося, одне твердження за тест дуже допомагає тут. Якщо в одному тесті є кілька тверджень, тільки перше виходить з ладу, а потім метод виходить, тож ви не знаєте, чи порушена й інша поведінка, перевірена в наступних тестах, поки ви не виправите те, що призвело до того, що перше твердження не вдалося. З одного твердження, всі ваші інші методи тестування все ще виконуються, і набагато швидше зрозуміти глибину відмови.
Звичайно, я згоден з Кіліаном Фотом: на практиці ти можеш пощастити зробити кілька одиничних тестів на код, над яким ти працюєш. І будь-який невеликий локалізований тест краще, ніж взагалі ніякий тест, або лише великі інтеграційні тести, які працюють на сервері збірки, займають багато часу і зазвичай не дуже локалізовані (вони не підкажуть швидко, де помилка - ви доведеться трохи попрацювати над цим).
Я думаю, що правильно, що кожен клас має свій тестовий клас. Ідея полягає в централізації всіх одиничних тестів, пов’язаних із цільовим класом, в одному тестовому класі. Тоді, наприклад, MyClass.java
буде проведений тестовий клас під назвою MyClassTest.java
.