Мене запитали про те, як запустити набір з 65 000 000 000 тестів, і мені цікаво, чи нормально мати проект з такою величезною кількістю тестів.
Ви працювали в проектах з цією характеристикою?
Мене запитали про те, як запустити набір з 65 000 000 000 тестів, і мені цікаво, чи нормально мати проект з такою величезною кількістю тестів.
Ви працювали в проектах з цією характеристикою?
Відповіді:
З 65 мільярдів тестів здається, що вас просять перевірити всі можливі дані. Це не корисно - ви, по суті, перевірите, чи правильно працює ваш процесор, а не правильність вашого коду.
Натомість вам слід тестувати класи еквівалентності . Це різко скоротить діапазон випробувань.
Також врахуйте, чи можете ви поділити вашу систему на більш дрібні шматочки. Кожен фрагмент буде простіше перевірити ізольовано, і тоді ви зможете виконати кілька інтеграційних тестів, які об'єднують усі шматки.
Якщо ви все ще хочете запевнити, що деякі з цих комбінацій вводу працюють, можливо, ви можете спробувати нечітке тестування . Ви отримаєте деякі переваги тестування безлічі різних вхідних даних, але не використовуючи всі 65 мільярдів.
Якщо це справжній тестовий набір, то ви не хочете ніколи близько працювати над ним.
Вся робота тестера полягає в тому, щоб досягти балансу між тестуванням достатньо ретельно, щоб бути впевненим, що ви отримали «правильні» результати, і написати декілька достатньо тестів, щоб їх можна було запустити за розумну кількість часу.
Багато тестів можна віднести до «класів еквівалентності», це означає, що замість того, щоб провести 3 мільярди тестів, ви запускаєте 1, що дає вам розумний рівень впевненості, що всі інші тести в цьому класі еквівалентності будуть успішно виконуватись, якщо ви вирішили витрачати відходи час їх запуску.
Ви повинні сказати тому, хто думає провести 65 мільярдів тестів, що їм потрібно зробити кращу роботу, абстрагуючи тести на класи еквівалентності.
Більш ніж ймовірно, ви досягли вашої цифри в 65 мільярдів тестів, обчисливши всі можливі комбінації входів у тестувану систему або обчисливши цикломатичну складність і припускаючи, що тест повинен бути записаний для кожного з цих унікальних контурів виконання.
Це не так, як написані реальні тести, тому що, як вказували інші плакати та коментатори, технічна потужність, необхідна для виконання 65 мільярдівтести приголомшливі. Це було б як написання тесту, який використовує метод додавання двох цілих чисел, підключаючи кожну можливу перестановку двох 32-бітних значень та перевіряючи результат. Це повне божевілля. Ви повинні провести лінію та визначити підмножину всіх можливих тестових випадків, що між ними забезпечить, що система буде вести себе так, як очікувалося, у всьому діапазоні входів. Наприклад. ви тестуєте додавання кількох "звичайних" чисел, ви перевіряєте кілька сценаріїв негативних чисел, ви перевіряєте технічні обмеження, такі як сценарії переповнення, і ви перевіряєте будь-які сценарії, які можуть призвести до помилки. Як було сказано, ці різні типи тестів здійснюють "класи еквівалентності"; вони дозволяють вам взяти репрезентативну вибірку можливих даних разом із будь-якими відомими "випускниками",
Розглянемо один з основних катальних кодів, генератор римських чисел. Завдання, яке слід виконати з використанням методів TDD у стилі "доджо", - написати функцію, яка може приймати будь-яке число від 1 до 3000 та створити правильну римську цифру для цього значення числа.
Ви не вирішите цю проблему, написавши 3000 тестів одиниці, по одному і здавши їх по черзі. Ось лунатик; вправа зазвичай займає від однієї до двох годин, і ви будете там днями, перевіряючи кожне окреме значення. Натомість ви стаєте розумними. Ви починаєте з найпростішого базового випадку (1 == "Я"), реалізуєте це, використовуючи стратегію "найменшого коду" ( return "I";
), а потім шукаєте, як код, який ви маєте, буде вести себе неправильно в іншому очікуваному сценарії (2 == " II "). Промийте і повторіть; більш ніж ймовірно, ви замінили свою початкову реалізацію чимось, що повторює символ "Я" так часто, як потрібно (як return new String('I',number);
). Це, очевидно, пройде тест на III, так що ви не турбуєтесь; натомість ви пишете тест для 4 == "IV", який ви знаєте, що поточна реалізація виграла "
Або, більш аналітичним стилем, ви вивчаєте кожне умовне рішення, яке приймається за кодом (або потрібно), і пишете тест, призначений для введення коду для кожного можливого результату кожного рішення. Якщо у вас є 5, якщо висловлювання (кожне з яких має істинну і хибну гілку), кожне з них повністю незалежне від інших, ви кодуєте 10 тестів, а не 32. Кожен тест буде розроблений, щоб стверджувати дві речі про певне можливе рішення; спочатку про те, що прийнято правильне рішення, а потім, що введений код з урахуванням цієї умови є правильним. Ви не кодуєте тест для кожної можливої перестановки незалежних рішень. Якщо рішення залежать, вам доведеться перевірити їх більше у поєднанні, але таких комбінацій менше, оскільки деякі рішення приймаються лише тоді, коли інше рішення мало певний результат.
Це "нормально" ?, ні. Де "нормальний" визначається як середній або типовий досвід. Не можу сказати, що мені коли-небудь доводилося працювати над таким проектом, але я був над проектом, де кожен кожні кілька мільйонів біт буде перевернутий. Перевірка цього була ... викликом.
Це потенційно потрібно? Ну, це залежить від гарантій та специфіки проекту. Спочатку це трохи недовірливо розуміти, але ваше питання легке щодо конкретики.
Як вказували інші (MichaelT), час на виконання цього завдання серійним тестуванням робить це непрактичним. Тож паралелізація стає вашою першою увагою. Скільки тестових систем ви можете вирішити з цією проблемою, і яку підтримку ви маєте для збору результатів цих кількох систем?
Які гарантії у вас є, що пристрій чи алгоритм, який ви тестуєте, надійно копіюються? Програмне забезпечення досить надійне в реплікації, але апаратні пристрої (особливо першого покоління) можуть мати проблеми з виробництвом. Помилкова помилка тесту в цьому випадку може вказувати або на поганий алгоритм, або пристрій неправильно зібрано. Чи потрібно розрізняти ці два випадки?
Вам також потрібно буде розглянути, як ви збираєтеся перевірити самі системи тестування. Припускаючи законну причину для багатьох тестових випадків, вам знадобиться багато автоматизації. Цю автоматику потрібно перевірити, щоб переконатися, що вона не помиляється при створенні ваших тестових випадків. Точкові перевірки на помилки справді були б еквівалентом пошуку голки в стозі сіна.
Це посилання arstechnica може або не може пролити деяке розуміння ваших міркувань щодо тестування. Кластери GPU зазвичай використовуються для злому паролів з грубою силою. Той, що цитується у статті, може can cycle through as many as 350 billion guesses per second
, таким чином, ви ставите перспективними ваші 65B тести. Ймовірно, це інша область, але це показує, як підхід до завдання з різних кутів може дати життєздатне рішення.
Я не думаю, що доцільно підтримувати 6.5e + 10 тестів, це перше місце, тому запуск їх може бути суперечливим. Навіть найбільші проекти, як Debian з усіма його пакетами, мають всього кілька сотень мільйонів SLOC.
Але якщо вам все одно доведеться провести величезну кількість тестів, існує кілька стратегій.
Не запускайте їх усіх. Швидше за все, не кожен тест залежить від кожного кодового шляху. Визначте залежності між підсистемами та їх тестами, а також між тестовими наборами, і ви зможете запускати тільки тести одиниць, що стосуються певної зміни, лише тести інтеграції залежно від цих одиничних тестів тощо.
Виконайте їх паралельно. Маючи базу коду величезну, напевно, у вас є масивна ферма побудови (назад у JetBrains, порівняно невелика операція, у нас було 40-50 агентів побудови, які працюють лише на фермі безперервного збирання / інтеграції IDEA). Оскільки одиничні тести є незалежними, а інтеграційні тести можуть повторно використовувати вже вбудований код, тести порівняно легко паралелізувати.
Перестань бігати рано. Якщо ви знаєте, що певний тестовий набір залежить від його розумного функціонування від правильності іншого тестового набору, ви можете розрізати весь ланцюг, як тільки побачите, що одна ланка виходить з ладу.
Відмова: Я не професійний інженер-тестувальник. Візьміть вищезгадане із зерном солі.
Хоча тут було кілька хороших пропозицій щодо того, як спробувати прокрастись за допомогою меншої кількості тестів, я серйозно сумніваюся, що ваша система має лише 65 мільярдів вхідних комбінацій. Це менше 36 біт вводу. Припустимо, ви вже прийняли всі поради, наведені вище.
Якщо для кожного тесту потрібно близько мілісекунди, і ви поширите тести лише на 10 процесорів (один звичайний ПК), тест запуститься трохи більше 69 днів. Це деякий час, але не зовсім безпідставно. Розподіліть по 100 процесорів (десяток звичайних ПК або один розумний серверний ПК), і тести будуть завершені протягом менш ніж 7 днів. Ви можете запускати їх щотижня, щоб перевірити регресії.