Загрузка данных
ПРАКТИЧЕСКАЯ РАБОТА
Тема: Комплексное тестирование и рефакторинг критической бизнес-логики методом «Белого ящика»
ЦЕЛЬ РАБОТЫ
Освоить навыки глубокого анализа исходного кода со сложной бизнес-логикой, выявлением скрытых уязвимостей, состояний гонки (Race Condition), мутаций данных, некомпенсированных транзакций и ошибочной обработки граничных условий. Научиться проводить рефакторинг и составлять исчерпывающее тестовое покрытие.
МЕТОДИКА ВЫПОЛНЕНИЯ
1. Анализ требований и поиск логических уязвимостей
Проанализируйте представленный код функции и сопоставьте его с техническим заданием. Найдите логические изъяны:
● Побочные эффекты (Side Effects) и непреднамеренные мутации входных объектов;
● Ошибки в обработке отрицательных значений, нуля, типов null / undefined / NaN;
● Нарушение атомарности операций и логики ветвления при комбинации флагов;
● Ошибки в математических округлениях и плавающей точке (Float Precision Issue).
2. Проведение рефакторинга
Перепишите функцию, устранив все выявленные архитектурные и логические дефекты:
● Обеспечьте чистоту функции (Pure Function) или изолированность изменений;
● Исправьте порядок проверок (Guard Clauses);
● Корректно обработайте все edge-cases (граничные сценарии).
3. Разработка полного тестового покрытия
Составьте набор тестов, покрывающий:
● Положительные сценарии (Happy Path);
● Граничные условия и экстремальные значения (Boundary Conditions);
● Негативные сценарии (передача некорректных или поврежденных данных).
СТРУКТУРА ОТЧЕТА ПО ПРАКТИЧЕСКОЙ РАБОТЕ
Отчет оформляется студентом в текстовом редакторе со следующими разделами:
1. Титульный блок
● Наименование учебного заведения, кафедры и дисциплины
● Тема практической работы
● Сведения о студенте (ФИО, группа, номер варианта) и преподавателе
2. Исходные данные
● Текст задания и исходный код функции с ошибками
3. Аналитическая часть (Аудит кода)
● Детализированный список всех найденных ошибок и уязвимостей с объяснением, к какому сбою в реальной системе (например, списанию лишних денег или зависанию сессии) приведет каждая из них
4. Рефакторинг (Исправленный код)
● Итоговый исправленный вариант функции с комментариями к ключевым изменениям
5. Набор тестовых сценариев
● Список проверочных тестов: идентификатор теста, проверяемая ветка/сценарий, входные аргументы, ожидаемое поведение (возврат значения или проброс ошибки) и фактический результат
6. Вывод по работе
● Анализ влияния проведенного рефакторинга на надежность, безопасность и поддерживаемость модуля
ВАРИАНТЫ ЗАДАНИЙ ДЛЯ САМОСТОЯТЕЛЬНОЙ РАБОТЫ
Вариант 1. Модуль проведения транзакции и применения промокодов в корзине
Технические требования:
1. Функция принимает объект cart (корзину) и объект promo.
2. Если в корзине нет товаров или она не валидна, выбрасывать исключение Error("Empty cart").
3. Базовая скидка по промокоду не должна быть больше 50% от суммы заказа.
4. Если пользователь является VIP-клиентом (cart.user.isVip === true), ему начисляется дополнительная скидка 10% на итоговую сумму после применения промокода.
5. Промокоды одноразовые: если промокод уже использован (promo.isUsed === true), скидка не применяется. После успешного применения статус промокода должен меняться на isUsed = true.
6. Функция должна возвращать итоговую сумму с точностью до 2 знаков после запятой, не изменяя исходные цены товаров в объекте cart.
Код с ошибками:
JavaScript
function processPayment(cart, promo) {
let total = 0;
// 1. Некорректная проверка массива товаров
for (let i = 0; i <= cart.items.length; i++) {
total += cart.items[i].price * cart.items[i].count;
}
// 2. Ошибка работы с объектом promo и состояниями
if (promo && promo.isUsed = false) {
if (promo.discountPercent > 50) {
promo.discountPercent = 50;
}
total = total - (total * (promo.discountPercent / 100));
promo.isUsed = true; // Побочный эффект при незавершенной операции
}
// 3. Логическая ошибка в проверке VIP и мутация входных данных
if (cart.user.isVip = true) {
total = total * 0.9;
cart.user.bonusPoints += total * 0.05; // Мутация объекта
}
// 4. Проблема плавающей точки и отрицательных сумм
if (total < 0) return 0;
return total; // Нет округления до 2 знаков
}
Вариант 2. Системный модуль бронирования и распределения слотов ресурсов
Технические требования:
1. Функция bookSlot принимает массив доступных слотов slots (объекты с id, startTime, endTime, isBooked), желаемый интервал request (startTime, endTime) и userId.
2. Интервал считается корректным, если startTime < endTime и время начала не находится в прошлом относительно системного времени.
3. Слоты бронируются, только если желаемый интервал полностью помещается внутри одного свободно находящегося слота (isBooked === false).
4. При успешном бронировании выбранный слот должен помечаться как isBooked = true, привязываться к userId, а функции должен возвращаться объект ответа { success: true, slotId: ... }.
5. Если подходящего слота нет или входные данные некорректны, функция должна возвращать { success: false, reason: "..." } без изменения состояния исходных слотов.
Код с ошибками:
JavaScript
function bookSlot(slots, request, userId) {
// 1. Отсутствие проверки на корректность дат и прошедшее время
if (request.startTime > request.endTime) {
return { success: false, reason: "Invalid time" };
}
for (let i = 0; i < slots.length; i++) {
let slot = slots[i];
// 2. Ошибка в проверке пересечения интервалов и флага
if (slot.isBooked == false || slot.startTime <= request.startTime) {
// 3. Ранняя мутация до полной проверки интервала окончания
slot.isBooked = true;
slot.userId = userId;
if (slot.endTime >= request.endTime) {
return { success: true, slotId: slot.id };
}
}
}
// 4. Частично мутированные слоты остаются с измененным флагом isBooked!
return { success: false, reason: "No slot found" };
}
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ И ЗАЩИТЫ РАБОТЫ
1. Что такое «чистая функция» (Pure Function) и почему функции с побочными эффектами (Side Effects) сложно тестировать методом «Белого ящика»?
2. К каким последствиям в многопоточной или асинхронной среде приводит ранняя мутация состояния объекта до завершения всех валидаций?
3. В чем заключается опасность оператора присваивания (=) внутри условных конструкций if и как ее предотвратить на уровне линтеров и тестов?
4. Как правильно тестировать код, работающий с финансовыми данными и числами с плавающей точкой (0.1 + 0.2 !== 0.3)?
5. Что такое паттерн Guard Clauses (защитные условия) и как он упрощает вложенную логику if-else?