package logging import ( "bytes" "encoding/json" "log/slog" "strings" "testing" ) // Уровень — это адресат, а не громкость: DEBUG предназначен разработчику при // отладке и в штатной работе наружу не выходит. func TestУровеньОтсекаетНижние(t *testing.T) { t.Parallel() var buf bytes.Buffer log := NewTo(&buf, "warn", "json") log.Debug("отладка") log.Info("событие") log.Warn("может стать проблемой") out := buf.String() if strings.Contains(out, "отладка") || strings.Contains(out, "событие") { t.Errorf("уровень warn пропустил записи ниже себя: %s", out) } if !strings.Contains(out, "может стать проблемой") { t.Errorf("запись уровня warn потерялась: %s", out) } } // Время в логах — UTC: иначе порядок событий между машинами не сравнить. func TestВремяВUTC(t *testing.T) { t.Parallel() var buf bytes.Buffer NewTo(&buf, "info", "json").Info("событие") var rec map[string]any if err := json.Unmarshal(buf.Bytes(), &rec); err != nil { t.Fatalf("запись не JSON: %v (%s)", err, buf.String()) } ts, _ := rec[slog.TimeKey].(string) if !strings.HasSuffix(ts, "Z") { t.Errorf("метка времени %q не в UTC", ts) } } // Команды CLI пишут отчёт в stdout, поэтому их лог обязан идти в stderr — // иначе отчёт не разобрать ни глазами, ни перенаправлением. func TestNewErrПишетВStderrАNewВStdout(t *testing.T) { t.Parallel() // Прямой проверки потока здесь нет намеренно: подмена os.Stdout была бы // мутацией глобала. Проверяем то, что от этих конструкторов зависит на // самом деле, — что они собирают разные назначения и оба живые. if New("info", "json") == nil || NewErr("info", "text") == nil { t.Fatal("конструктор вернул nil") } var buf bytes.Buffer NewTo(&buf, "info", "text").Info("событие", "ключ", "значение") if !strings.Contains(buf.String(), "ключ=значение") { t.Errorf("текстовый формат не применён: %s", buf.String()) } }