У мене є скелетна реалізація, як у пункті 18 від Ефективна Java ( тут розширена дискусія ). Це абстрактний клас, який пропонує 2 відкритих методу methodA () та methodB (), які викликають методи підкласів для "заповнення прогалин", які я не можу визначити абстраговано.
Я розробив його спочатку, створивши конкретний клас та написав для нього одиничні тести. Коли прийшов другий клас, я зміг витягти загальну поведінку, реалізувати "пропущені пропуски" у другому класі, і він був готовий (звичайно, одиничні тести були створені для другого підкласу).
Час минув, і тепер у мене є 4 підкласи, кожен з яких реалізує 3 коротких захищених методу, які є дуже специфічними для їх конкретної реалізації, тоді як скелетна реалізація виконує всю загальну роботу.
Моя проблема полягає в тому, що коли я створюю нову реалізацію, я знову пишу тести:
- Чи підклас називає заданий необхідний метод?
- Чи має даний метод дану анотацію?
- Чи отримую я очікувані результати від методу А?
- Чи отримую я очікувані результати від методу B?
Хоча бачите переваги при такому підході:
- Він документує вимоги до підкласу за допомогою тестів
- Він може швидко вийти з ладу в разі проблемного рефакторингу
- Тестуйте підклас у цілому та за допомогою їх публічного API ("чи працює методA ()?", А не "чи працює цей захищений метод?")
Проблема, яка у мене є, полягає в тому, що тести для нового підкласу, в основному, не є мозковими: - Тести всі однакові у всіх підкласах, вони просто змінюють тип повернення методів (реалізація скелета є загальним) та властивості I перевірити утверджувальну частину тесту. - Зазвичай підкласи не мають тестів, які є специфічними для них
Мені подобається те, як тести фокусуються на результаті самого підкласу та захищають його від рефакторингу, але той факт, що реалізація тесту став просто "ручною роботою", змушує мене думати, що я роблю щось не так.
Чи поширене це питання під час тестування ієрархії класів? Як я можу цього уникнути?
ps: Я думав про тестування класу скелетів, але це також здається дивним, створюючи макет з абстрактного класу, щоб мати можливість його перевірити. І я думаю, що будь-який рефакторинг на абстрактний клас, який змінює поведінку, яку не очікує підклас, не буде помічений так швидко. Мої кишки говорять мені, що тестування підкласу "в цілому" є кращим підходом тут, але, будь ласка, не соромтесь сказати мені, що я помиляюся :)
ps2: Я гуглив і знайшов багато питань з цього питання. Один з них - це той, хто має чудову відповідь від Найджела Торна, мій випадок - його "номер 1". Це було б чудово, але в даний момент я не можу рефактор, тому мені доведеться жити з цією проблемою. Якби я міг рефактор, я мав би кожен підклас як стратегію. Це було б добре, але я все-таки перевіряв би "основний клас" і тестував стратегії, але я не помітив би жодного рефакторингу, який би порушив інтеграцію між основним класом і стратегіями.
ps3: Я знайшов кілька відповідей, які говорять про те, що "прийнятно" перевірити абстрактний клас. Я погоджуюся, що це прийнятно, але я хотів би знати, який є кращим підходом у цьому випадку (я все ще починаю з одиничних тестів)