Поиск публикаций
Муниципальные услуги

Получите услугу онлайн

Перейти

Отладка

Инструменты для логирования, диагностики, профилирования и тестирования в WDSP

 Логирование

отладка.логирование(сообщение)

Выводит отладочное сообщение в поток стандартных ошибок (stderr). Полезно для диагностики без засорения основного вывода.

ПараметрТипОписание
сообщениестрокаТекст для вывода
Возвращает: ничего
Пример:
отладка.логирование("Начало выполнения функции");

 Определение типа

отладка.тип(значение)

Возвращает строковое имя типа переданного значения. Поддерживаемые имена: "число", "строка", "логический", "массив", "объект", "функция", "null".

ПараметрТипОписание
значениелюбойПеременная любого типа
Возвращает: строка (имя типа)
Пример:
₽тип = отладка.тип(42);  // "число"

 Дамп значения

отладка.дамп(значение [, глубина])

Возвращает строковое представление значения с учётом вложенности. Параметр глубина ограничивает уровень раскрытия вложенных объектов и массивов.

ПараметрТипОписание
значениелюбойДанные для дампа
глубина (необязательный)числоМаксимальный уровень вложенности (по умолчанию без ограничений)
Возвращает: строка (дамп)
Пример:
₽объект = {имя: "Анна", возраст: 30, хобби: ["чтение", "музыка"]};
отладка.логирование(отладка.дамп(₽объект, 1));

 Время в миллисекундах

отладка.времяМс()

Возвращает текущее системное время в миллисекундах с начала эпохи (Unix-время). Используется для измерения интервалов.

Возвращает: число (миллисекунды)
Пример:
₽начало = отладка.времяМс();
// ... выполняем код ...
₽конец = отладка.времяМс();
₽прошло = ₽конец - ₽начало;

 Стек вызовов

отладка.стек()

Возвращает массив строк с именами функций в текущем стеке вызовов. Первый элемент — самая глубокая (текущая) функция.

Возвращает: массив строк
Пример:
₽стек = отладка.стек();
для каждого (₽фрейм из ₽стек) {
    отладка.логирование(₽фрейм);
}

 Слежение за переменной

отладка.следить(имяПеременной, функцияОбработки)

Устанавливает обработчик, который вызывается при каждом изменении указанной переменной. Обработчик получает имя и новое значение переменной.

ПараметрТипОписание
имяПеременнойстрокаИмя переменной (с префиксом ₽ или без)
функцияОбработкифункцияПринимает два аргумента: имя и новое значение
Возвращает: ничего
Пример:
отладка.следить("₽счётчик", функция(₽имя, ₽значение) {
    отладка.логирование(₽имя + " изменено на " + отладка.дамп(₽значение));
});
₽счётчик = 10;  // вызовет обработчик

 Отмена слежения

отладка.отследить(имяПеременной)

Удаляет все обработчики слежения для указанной переменной. После этого изменения переменной больше не отслеживаются.

ПараметрТипОписание
имяПеременнойстрокаИмя переменной (с префиксом ₽ или без)
Возвращает: ничего
Пример:
отладка.отследить("₽счётчик");

 Бенчмарк

отладка.бенчмарк(функция, итерации [, колбэк])

Замеряет время выполнения переданной функции, повторяя её указанное количество раз. Результат (среднее время, общее время, количество итераций) передаётся в колбэк.

ПараметрТипОписание
функцияфункцияТестируемая функция
итерациичислоКоличество запусков
колбэк (необязательный)функцияПринимает объект результата
Возвращает: ничего (результат передаётся в колбэк)
Результат (объект): содержит поля времяМс (общее время), итерации, среднееМс, последнийРезультат (возврат функции).
Пример:
отладка.бенчмарк(функция() {
    // какой-то код
}, 100, функция(₽результат) {
    вывод("Среднее время: " + строка(₽результат.среднееМс));
});

 Профиль

отладка.профиль(функция, итерации [, колбэк])

Аналогичен бенчмарк, но дополнительно выводит подробную информацию о стеке вызовов (если доступно). Полезен для поиска узких мест.

ПараметрТипОписание
функцияфункцияТестируемая функция
итерациичислоКоличество запусков
колбэк (необязательный)функцияПринимает объект результата
Возвращает: ничего (результат в колбэке)
Пример:
отладка.профиль(₽мояФункция, 10, функция(₽рез) {
    вывод("Профиль завершён");
});

 Утверждение

отладка.утверждение(условие, сообщение)

Проверяет истинность условия. Если условие ложно, выбрасывает исключение с указанным сообщением. Используется для самопроверки кода.

ПараметрТипОписание
условиелогическийПроверяемое условие
сообщениестрокаТекст ошибки, если условие ложно
Возвращает: ничего (или выбрасывает исключение)
Пример:
попытка {
    отладка.утверждение(₽результат == 42, "Результат должен быть 42");
} ловушка(₽ошибка) {
    вывод("Ошибка: " + ₽ошибка);
}

 Полный тестовый скрипт

Ниже приведён полный тест, демонстрирующий все функции модуля «отладка».

// ============================================================
// Тест модуля отладка (исправленный, адаптивный)
// ============================================================

вывод("=== Тест модуля отладка ===\n");

₽отладка = отладка;
₽строки = строки;

// 1. Логирование
₽отладка.логирование("Тест логирования: сообщение 1");
₽отладка.логирование("Тест логирования: сообщение 2");
вывод("1. логирование: проверьте stderr\n");

// 2. Типы
₽число = 42;
₽строка = "Привет";
₽логический = истина;
₽массив = [1,2,3];
₽объект = {a:1,b:2};
₽функция = функция() { возврат "ok"; };
₽null = ничто;

₽типЧисло = ₽отладка.тип(₽число);
₽типСтрока = ₽отладка.тип(₽строка);
₽типЛогический = ₽отладка.тип(₽логический);
₽типМассив = ₽отладка.тип(₽массив);
₽типОбъект = ₽отладка.тип(₽объект);
₽типФункция = ₽отладка.тип(₽функция);
₽типNull = ₽отладка.тип(₽null);

если (₽типЧисло == "число" && ₽типСтрока == "строка" && ₽типЛогический == "логический" &&
    ₽типМассив == "массив" && ₽типОбъект == "объект" && ₽типФункция == "функция" &&
    ₽типNull == "null") {
    вывод("2. тип: OK\n");
} иначе {
    вывод("2. тип: ОШИБКА\n");
}

// 3. Дамп
₽сложный = {имя:"Анна", возраст:30, хобби:["чтение","музыка"], адрес:{город:"Москва",улица:"Тверская"}};
₽дамп = ₽отладка.дамп(₽сложный,2);
если (₽строки.содержит(₽дамп,"имя") && ₽строки.содержит(₽дамп,"хобби")) {
    вывод("3. дамп: OK\n");
} иначе {
    вывод("3. дамп: ОШИБКА, получено:\n" + ₽дамп + "\n");
}

// 4. Время
₽время1 = ₽отладка.времяМс();
пауза(100);
₽время2 = ₽отладка.времяМс();
₽разница = ₽время2 - ₽время1;
если (₽разница >= 90 && ₽разница <= 150) {
    вывод("4. времяМс: OK (" + строка(₽разница) + " мс)\n");
} иначе {
    вывод("4. времяМс: ОШИБКА, разница " + строка(₽разница) + " мс\n");
}

// 5. Стек
₽стек = ₽отладка.стек();
₽типСтека = ₽отладка.тип(₽стек);
если (₽типСтека != "массив") {
    вывод("5. стек: ПРЕДУПРЕЖДЕНИЕ - getStackTrace() возвращает null\n");
} иначе {
    ₽дампСтека = ₽отладка.дамп(₽стек);
    если (₽стек.длина > 0) {
        вывод("5. стек: OK (содержит " + строка(₽стек.длина) + " элементов)\n");
    } иначе {
        вывод("5. стек: ПРЕДУПРЕЖДЕНИЕ - стек пуст\n");
    }
}

// 6. Слежение
₽отладка.логирование("=== Тест слежения ===");
₽лог = "";
₽отладка.следить("₽тест", функция(₽имя, ₽значение) {
    ₽лог = ₽лог + "Изменение " + ₽имя + " -> " + ₽отладка.дамп(₽значение) + "; ";
    ₽отладка.логирование("Слежение: " + ₽имя + " = " + ₽отладка.дамп(₽значение));
});
₽тест = 10;
₽тест = 20;
₽отладка.отследить("₽тест");
₽тест = 30;
если (₽строки.содержит(₽лог,"10") && ₽строки.содержит(₽лог,"20") && !₽строки.содержит(₽лог,"30")) {
    вывод("6. следить/отследить: OK\n");
} иначе {
    вывод("6. следить/отследить: ОШИБКА, лог=" + ₽лог + "\n");
}

// 7. Бенчмарк
₽тестФункция = функция() {
    ₽сумма = 0;
    для (₽i=0; ₽i<100000; ₽i=₽i+1) { ₽сумма = ₽сумма + ₽i; }
    возврат ₽сумма;
};
₽бенчмаркРезультат = ничто;
₽отладка.бенчмарк(₽тестФункция, 3, функция(₽рез) {
    ₽бенчмаркРезультат = ₽рез;
});
пауза(10);
если (₽бенчмаркРезультат != ничто && ₽отладка.тип(₽бенчмаркРезультат)=="объект" && ₽бенчмаркРезультат.итерации==3) {
    вывод("7. бенчмарк: OK (время " + строка(₽бенчмаркРезультат.времяМс) + " мс)\n");
} иначе {
    вывод("7. бенчмарк: ОШИБКА, результат=" + ₽отладка.дамп(₽бенчмаркРезультат) + "\n");
}

// 8. Профиль
₽профРезультат = ничто;
₽отладка.профиль(₽тестФункция, 1, функция(₽рез) {
    ₽профРезультат = ₽рез;
});
пауза(10);
если (₽профРезультат != ничто && ₽отладка.тип(₽профРезультат)=="объект" && ₽профРезультат.итерации==1) {
    вывод("8. профиль: OK\n");
} иначе {
    вывод("8. профиль: ОШИБКА\n");
}

// 9. Дамп с глубиной (упрощённо)
₽глубокий = [1,[2,[3,[4,[5]]]]];
₽дамп1 = ₽отладка.дамп(₽глубокий,1);
₽дамп3 = ₽отладка.дамп(₽глубокий,3);
₽длина1 = ₽строки.длина(₽дамп1);
₽длина3 = ₽строки.длина(₽дамп3);
если (₽длина1 < ₽длина3) {
    вывод("9. дамп с глубиной: OK (глубина1 короче глубины3)\n");
} иначе {
    вывод("9. дамп с глубиной: ОШИБКА (длина1=" + строка(₽длина1) + ", длина3=" + строка(₽длина3) + ")\n");
}

// 10. Утверждение
попытка {
    ₽отладка.утверждение(ложь, "Тест утверждения");
    вывод("10. утверждение: ОШИБКА (не бросило исключение)\n");
} ловушка(₽ошибка) {
    если (₽строки.содержит(₽ошибка, "Тест утверждения")) {
        вывод("10. утверждение: OK\n");
    } иначе {
        вывод("10. утверждение: ОШИБКА, сообщение=" + ₽ошибка + "\n");
    }
}

вывод("\n=== Все тесты модуля отладка завершены ===\n");