Поиск публикаций
Отладка
Содержание
Логирование
отладка.логирование(сообщение)
Выводит отладочное сообщение в поток стандартных ошибок (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");