Енуми - це просто кінцеві типи, що мають власні (сподіваюся, значимі) назви. Перерахунок може мати лише одне значення, void
яке містить лише null
одне (деякі мови називають це unit
, і використовують ім'я void
для enum без елементів!). Він може мати два значення, наприклад, bool
яке має false
і true
. Це може бути три, як colourChannel
з red
, green
і blue
. І так далі.
Якщо два перерахунки мають однакову кількість значень, то вони "ізоморфні"; тобто якщо ми вимикаємо всі імена систематично, ми можемо використовувати одне замість іншого, і наша програма не поводитиметься інакше. Зокрема, наші тести не поводяться інакше!
Наприклад, result
що містить win
/ lose
/ draw
ізоморфно вище colourChannel
, так як ми можемо замінити , наприклад , colourChannel
з result
, red
з win
, green
з lose
і blue
з draw
, і до тих пір , як ми робимо це всюди (виробники і споживачі, парсери і serialisers, записи бази даних, файли журналів і т.д. ) тоді змін у нашій програмі не буде. Будь-які " colourChannel
тести", які ми писали, все-таки пройдуть, хоча більше немає colourChannel
!
Крім того, якщо enum містить більше одного значення, ми завжди можемо переставити ці значення, щоб отримати новий перерахунок з однаковою кількістю значень. Оскільки кількість значень не змінилася, нове розташування є ізоморфним для старого, а значить, ми могли б вимкнути всі імена, і наші тести все-таки пройдуть (зауважте, що ми не можемо просто вимкнути визначення; ми повинні все-таки вимкніть і всі сайти, які використовують).
Це означає, що що стосується машини, то перерахунки - це "розрізнені назви" та більше нічого . Єдине, що ми можемо зробити із перерахунком - це розгалуження, чи є два значення однаковими (наприклад, red
/ red
) чи різними (наприклад, red
/ blue
). Тож це єдине, що може зробити "одиничний тест", наприклад
( red == red ) || throw TestFailure;
(green == green) || throw TestFailure;
( blue == blue ) || throw TestFailure;
( red != green) || throw TestFailure;
( red != blue ) || throw TestFailure;
...
Як говорить @ jesm00, такий тест - це перевірка мовної реалізації, а не вашої програми. Ці тести ніколи не є хорошою ідеєю: навіть якщо ви не довіряєте мовній реалізації, ви повинні перевірити її ззовні , оскільки не можна довіряти правильному виконанню тестів!
Так це теорія; як щодо практики? Основна проблема при цій характеристиці переліків полягає в тому, що програми "реального світу" рідко є автономними: у нас є застарілі версії, віддалені / вбудовані розгортання, історичні дані, резервні копії, живі бази даних тощо, тому ми ніколи не можемо реально "вимкнути" всі зустрічі імені без пропуску деяких застосувань.
Але такі речі не є "відповідальністю" самого перерахунку: зміна перерахунку може порушити спілкування з віддаленою системою, але, навпаки, ми можемо вирішити таку проблему, змінивши перерахунок!
У таких сценаріях перерахунок є червоношкірим оселедцем: що робити, якщо одна система потребує цього таким чином, а інша - це саме так? Це не може бути обом, незалежно від того, скільки тестів ми пишемо! Справжнім винуватцем в цьому є інтерфейс введення / виводу, який повинен створювати / споживати чітко визначені формати, а не "будь-яке ціле число, яке вибирає інтерпретатор". Таким чином, справжнє рішення полягає в тестуванні інтерфейсів вводу-виводу : з тестовими одиницями, щоб перевірити, чи він розбирає / друкує очікуваний формат, і тестами інтеграції, щоб перевірити, чи формат насправді прийнятий іншою стороною.
Ми все ще можемо задатись питанням, чи переживають «досконалі вправи», але в цьому випадку енту - це червона оселедець. Що нас насправді хвилює, це сам тестовий набір . Ми можемо завоювати тут впевненість двома способами:
- Покриття коду може нам сказати, чи достатньо різноманітності значень перерахувань, що надходять із тестового набору, для запуску різних гілок коду. Якщо ні, ми можемо додати тести, які запускають незакриті гілки, або генерують більшу кількість переліків у існуючих тестах.
- Перевірка властивості може сказати нам, чи достатньо різноманітності гілок у коді, щоб обробити можливості виконання. Наприклад, якщо код обробляє лише
red
ми, а ми лише тестуємо red
, ми маємо 100% охоплення. Перевірка властивості (спробує) генерує контрприклади до наших тверджень, таких як генерування значень green
та blue
значень, які ми забули перевірити.
- Мутаційне тестування може нам сказати, чи насправді наші твердження перевіряють перелік, а не просто слідкувати за гілками та ігнорувати їхні відмінності.