Чи існує принцип розробки програмного забезпечення, який стосується вартості тесту на повторне використання та регресію у виробничій системі?


12

Я працював над великою системою фінансових операцій для банку, який доглядав за пенсіями та інвестиціями. Після 15 років зміни функцій вартість ручного регресійного тесту зросла до 200 000 доларів за випуск. (10 млн. LOC, $ 10 млн у день). Ця система також взаємодіє з 19 іншими системами навколо компанії, переміщуючи безліч даних. Ця система була реалізована в Java.

Однак ми спостерігаємо, що чим більше ми повторно використовуємо, тим більше збільшуються витрати на тест регресії. (Причина в тому, що вам потрібно "протестувати код, який ви торкаєтесь" - і повторно використаний / спільний код впливає на безліч місць при його торканні. Тому, незважаючи на "DRY - не повторюйте себе" - тобто не копіюйте та не вставляйте код - ми спостерігаємо фінансовий стимул для копіювання та вставки коду. Це полягає у зменшенні витрат на тест регресії, оскільки ми не хочемо змінювати код, який можна поділити, оскільки це спричинить великий вплив регресійного тесту.)

Моє запитання: чи існує принцип інженерії програмного забезпечення, який описує залежність між витратами на повторне використання та регресійними тестами?

Причиною, що я задаю це питання, є те, що, мабуть, є корисна вигода від розкладання системи на менші частини, які підлягають тестуванню.

Припущення:

  1. "Тест регресії" означає "тест на прийняття" - тобто інша група проводить час для написання нових і повторного використання старих тестів проти системи від імені бізнесу, включаючи середовище та налаштування даних.

  2. Я знаю, що реагування на коліна на велику вартість тесту на регресію - це "більш автоматизовані тести". Це хороший принцип. У цьому середовищі є пара викликів.

    (a) Автоматизовані тести є менш корисними через кордони системи, за винятком випадків, коли ця система також має високе автоматизоване покриття тесту. (Сфера впливу виклику).

    (b) Культурно важко набирати обертів часу програміста або капітальних вкладень на високому автоматизованому тестовому покритті, коли ваша система вже велика і складна.

    (c) Витрати на підтримку автоматизованих тестів приховані за проектом, і тому вони легко відкидаються на рівні проекту.

    (d) Це лише культурна реальність роботи в банку.

    (д) Я працюю над тим, щоб вирішити цю проблему по-іншому (розкладання).


2
Ви робите зауваження вручну, що " ми спостерігаємо […], що чим більше" повторного використання ми робимо, тим більше [приймання] тестових витрат зростає "- ви могли б розширити це? Чи не повинен тест на прийняття бути агресивним щодо деталей реалізації, таких як ієрархії спадкування, а замість цього, наприклад, грати через сценарії використання?
амон

2
Ваше запитання цікаве, але воно містить деякі дуже необ’єктивні припущення на кшталт "повторне використання є наслідком ОО" або згадувана частина @amon. Я пропоную вам видалити частину "OO" повністю з неї, оскільки ваше основне питання не залежить від мови програмування або будь-якого програмування OO. І досить незрозуміло, який тип "повторного використання" ви маєте на увазі - "повторне використання" - це широкий термін, повторне використання копіювальної пасти відрізняється від повторного використання компонентів або бібліотеки.
Док Браун

Дякую, що корисно. Я видалив посилання на ОО - і розширив ідею доторкнутися до спільного коду (або коду, який стане загальним кодом).
хокі

1
У теперішній формі я думаю, що я відповів би просто "ні, я не думаю так" на ваше запитання - що, напевно, не дуже задовольнило б ваше. Або вас цікавлять принципи та практика фактичного зниження витрат на тестування при створенні такої великої системи, як ваша, з деякими самостійно виготовленими компонентами для повторного використання?
Док Браун

Відповіді:


11

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

Вище звучить про мене. Чим важливіший код, чим більше він ділиться, тим вищими є вимоги до якості, тим більше гарантії якості повинно бути залучено, коли він змінюється.

Оскільки ваша система реалізована на Java, ви можете побачити приклад для цього прямо у стандартних бібліотеках Java (JDK). Основні його випуски нечасті і супроводжуються дуже трудомісткими тестуваннями. І навіть незначні випуски проходять через дуже вичерпний тестовий набір JCK, щоб перевірити відсутність регресій.

Ви можете подумати, що це якось гальмує еволюцію спільного коду, і ... так, це правильно. Чим більше вплив і ризик пов'язаний зі зміною коду, чим уважніше ви повинні бути в цьому, тим більше зусиль потрібно докласти до тестування його версій.

В ідеалі якість випусків широко розповсюдженого коду повинна бути такою, що він взагалі не потребує великих змін (окрім нечастого вдосконалення). Ця думка відображена у відомій цитаті Джошуа Блоха :

Публічні API, як алмази, назавжди. У вас є один шанс виправити це, тому дайте все можливе.


Однак, як сказано вище, схоже, що деякі описані вами проблеми викликані неефективною стратегією спільної розробки коду. Зокрема, це виглядає особливо клопітно, що для повторно використаного коду розглядаються лише два варіанти: або дублювати цей код, або негайно включити його до "основних" спільних бібліотек.

Обмеження лише цих двох варіантів не є зайвим, і, знову ж таки, ви можете знайти приклади того, як це можна зробити краще в тому самому JDK, який ви використовуєте. Погляньте на java.util.concurrentпакети ( JSR 166 ) - до випуску Java 5 це були окрема бібліотека, а не частина основних версій JDK.

Подумайте, це третій варіант, який ви не помітили, і досить прагматичний, той, який вам потрібно врахувати при "створенні" нового спільного коду. Коли ви просто розраховуєте якийсь код, який можна поділити між 2-3 компонентами, ніщо не змушує вас негайно включити його в основний API системи.

Ви можете упакувати та випустити цей "незрілий" спільний код як окрему бібліотеку, як це було зроблено для одночасних утиліт Java. Цей спосіб позбавляє вас від необхідності повного регресійного тестування, оскільки ви можете використовувати лише відносно невелику кількість залучених компонентів. Як результат, у вас є більше можливостей змінити та вдосконалити цей спільний код та перевірити, як він працює у виробництві.

Після того, як ваша бібліотека дозріває і стабілізується достатньо, щоб дати вам впевненість, що подальші зміни в ній малоймовірні, ви можете розглянути можливість її включення до основних бібліотек системи, подібно до того, як сумісні утиліти з часом були включені в JDK.


Конкретний приклад того, скільки зусиль (включаючи тестування) може бути залучено до зміни сильно використаного коду, можна знову знайти в JDK. У випуску 7u6 вони змінили внутрішнє Stringпредставлення, що передбачало зміну substringпродуктивності. У коментарях розробника функцій Reddit вказується, скільки зусиль було залучено до цієї зміни:

Початковий аналіз вийшов із групи GC у 2007 році ...

Внутрішня команда продуктивності Oracle підтримує набір репрезентативних та важливих додатків та орієнтирів, які вони використовують для оцінки змін у роботі. Цей набір додатків мав вирішальне значення при оцінці зміни в підрядках. Ми уважно розглядали як зміни в продуктивності, так і зміни площі. Неминуче, як це стосується будь-яких суттєвих змін, в деяких додатках були регресії, а в інших - і збільшення. Ми досліджували регресії, щоб перевірити, чи продуктивність все-таки прийнятна і чи зберігається правильність ...

Моя відповідь не має бути вичерпною, але це дуже короткий підсумок того, що було майже шість місяців самовідданої роботи ...


Здається, ми обидва працювали над відповіддю паралельно, маючи багато подібних думок ...
Док Браун

@DocBrown Так, цікаво, що ми також відповіли майже одночасно, приблизно через годину після того, як питання було відредаговано у формі
gnat

9

Я не думаю, що існує жодна метрика для обчислення "витрати на тести регресії / побудований повторно використаний код". І я не думаю, що ніхто ніколи не вкладав стільки часу і грошей, щоб побудувати одну і ту ж «велику» систему двічі, одну версію з великою кількістю доступних компонентів і одну без, щоб зробити якісь серйозні дослідження з цього приводу.

Але я бачив проблеми, викликані повторним використанням, як і раніше, і, можливо, вас цікавлять деякі думки про те, як краще впоратися з цим.

По-перше, це фактично не повторне використання, яка є вашою проблемою - це скоріше спроба створити власні багаторазові компоненти та використовувати їх у всій системі. Я впевнений, що ви багато разів використовуєте великі програмні пакети, коли ваших проблем не виникає: придумайте весь стек Java, який ви використовуєте, або, можливо, деякі сторонні компоненти (припустимо, що ви були задоволені цими компонентами). Але чим відрізняється програмне забезпечення, наприклад, бібліотеки Java, а ваші власні багаторазові компоненти викликають у вас стільки додаткових витрат на тестування регресії? Ось деякі пункти, я думаю, що можуть бути різними:

  • ці компоненти дуже зрілі та стабільні

  • вони розроблені та повністю випробувані ізольовано, зовсім іншою організацією

  • щоб (повторно) використовувати їх, вам не потрібно їх змінювати (адже ви навіть не могли цього хотіти, оскільки не підтримуєте вихідний код)

  • ви не отримуєте щодня нову версію, лише незначні оновлення (максимум на місяць) або основні оновлення з інтервалом на рік

  • більшість оновлень розроблені так, щоб вони були на 100% суміснішими вниз, особливо незначні

Отже, щоб зробити власні компоненти, що повторно використовуються, більш успішними, ви повинні адаптувати деякі з цих елементів зверху для власної розробки:

  • будь-який компонент для багаторазового використання, несе чітку відповідальність за те, що здійснює обслуговування, і переконайтеся, що всі люди, які повторно використовують компонент, зможуть негайно отримати помилку, якщо виникнуть проблеми.

  • встановити сувору політику версій та випусків. Коли ви розвиваєте багаторазовий компонент, не випускайте його "кожному" щодня (принаймні, не, якщо це означатиме проведення повного регресійного тесту на 200 000 доларів у системі). Натомість нехай нові версії публікуються лише час від часу, і надайте механізми, щоб користувач цього компонента відклав зміни до нової версії.

  • чим частіше повторно використовується компонент, тим важливіше, що він забезпечує стабільний інтерфейс і сумісну поведінку.

  • Компоненти для багаторазового використання потребують дуже повних наборів тестів, щоб перевірити їх ізольовано.

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


0

Незважаючи на те, що може виникнути «помітне» подорожчання через необхідність проведення більш тестування, такий тип рефакторингу, як правило, робить код більш доступним у майбутньому, оскільки ви зменшуєте технічну заборгованість у системі.

Це, сподіваємось, зменшить майбутні помилки та полегшить впровадження нових функцій чи змін до існуючих функцій.

Простіше кажучи, я маю на увазі, що вони повинні зайняти менше часу і тому коштувати дешевше.

Зменшити, простіше і менше - це все досить неясні умови, і будь-яке майбутнє заощадження (або, скоріше, сподіваємось на економію) неможливо підрахувати, оскільки воно ще не відбулося.

Простіша база коду повинна дозволити новим працівникам або діючим працівникам, що рухаються на проект, швидше швидше, особливо для великих систем.

Це також може зменшити плинність кадрів у тому, що мораль існуючих членів проекту може бути покращена.

Звичайно, не гарантується, що ви отримаєте ці переваги, але це речі, які слід враховувати разом із витратами (наприклад, збільшення тестування), які можна виміряти.

Насправді, кращий код повинен врешті-решт знизити витрати на тестування, навіть якщо є початкове збільшення завдяки тому, що ви описуєте.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.