Більшість розробників, які додали функції до edx-платформи, знайомі з ModuleStoreTestCase. Якщо ваші тести вправляються з будь-яким предметом, пов’язаним із вмістом навчального матеріалу (навіть це просто створення порожнього курсу), успадкування від цього класу забезпечить належне очищення даних між окремими тестами. Це надзвичайно цінно, але також може бути марнотратним у багатьох ситуаціях. Під час хакатону минулого тижня я створив швидша альтернатива званий SharedModuleStoreTestCase.
на відміну від ModuleStoreTestCase, SharedModuleStoreTestCase тільки робить ModuleStore очищення на tearDownClass() рівень. Він призначений для використання в ситуаціях, коли один або кілька курсів можна ініціалізувати наперед, а потім поділитися між багатьма тестами в режимі лише для читання. Цей шаблон використання зазвичай зустрічається в тестах LMS, які часто просто відтворюють той самий курс знову і знову у своїх налаштування() методи
Вплив на продуктивність
Щоб отримати уявлення про ефект, який це може мати, я змінив кілька тестових модулів у рамках моєї роботи на хакатоні. Це лише приблизні цифри, оскільки вони базуються на відносно невеликій кількості тестів Дженкінса. При цьому результати є багатообіцяючими:
| Файл | # Тести | Перед тим як | після | Дельта |
| lms/djangoapps/ccx/tests/test_ccx_modulestore.py | 5 | 38s | 4s | -89% |
| lms/djangoapps/discussion_api/tests/test_api.py | 409 | 2м 45с | 51s | -69% |
| lms/djangoapps/teams/tests/test_views.py | 152 | 1м 17с | 33s | -57% |
Отже, як конвертувати власні тести?
Оформлення комутатор
Більшість класів, які успадковуються від ModuleStoreTestCase почати щось на зразок цього:

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

Важливо, щоб операції Django ORM залишалися налаштування(). Будь-які моделі, які ви створюєте setUpClass() потрібно вручну видалити у вашому tearDownClass() метод — SharedModuleStoreTestCase не очистить їх належним чином. Навіть якщо ви будете обережні, ви, ймовірно, порушите інші тести в системі непередбачуваним чином, оскільки вони роблять неправильні припущення щодо послідовностей і ідентифікаторів, які будуть створені під час налаштування своїх даних. Це може бути надзвичайно стомлюючим для налагодження.
Коли ми оновимо Django до 1.8, ви зможете використовувати setUpTestData() щоб безпечно виконувати ініціалізацію моделей Django на рівні класу з автоматичним очищенням. Будь ласка, зачекайте оновлення та внесіть маніпуляції з моделлю налаштування() поки що, навіть якщо це трохи повільніше.
Які тести слід конвертувати?
Найпростішим місцем пошуку цілей оптимізації тесту є Звіт про збірку тесту Дженкінса. Натисніть «Тривалість», щоб відсортувати за цим стовпцем.

Насамперед ми хочемо орієнтуватися на дорогі тести, які або створюють складні дані курсу (наприклад, CCX), або містять прості дані курсу, але багато, багато тестів (наприклад, обговорення). Створення навіть найпростішого курсу займає приблизно 250-300 мс або близько того, що дійсно збільшується при використанні таких інструментів, як ддт що ефективно збільшує кількість тестів у класі.
Загальний висновок
Доступ до бази даних є дорогою частиною виконання тестів, і ModuleStore є яскравим прикладом цього. сподіваюся, що SharedModuleStoreTestCase може бути корисним інструментом для скорочення часу виконання тесту. Але крім цього, я сподіваюся, що розуміння того, чому це працює, дозволить нам розробляти швидші набори тестів загалом.
Дейв Ормсбі — старший архітектор edX. Ця публікація була спочатку опублікована в його блозі, Болотний замок.
![]()