Skip to content

테스트 보조

DD 는 LoggerRecorder를 테스트 시나리오에 제공하여 로그 항목을 캡처해 단언에 사용할 수 있습니다.

LoggerRecorder

스레드 안전한 로그 레코더로, 테스트에서 로그 출력을 캡처하고 검사하는 데 사용합니다.

경고 텍스트 형식 파싱 제한

텍스트 모드 파서는 기본 시간 형식 (ISO 8601) 과 기본 레벨 문자열 (DEBUG/INFO/WARN/ERROR/FATAL) 을 가정합니다. TimeFormat을 커스터마이징한 경우 텍스트 모드는 레벨과 타임스탬프를 올바르게 추출하지 못할 수 있습니다. 커스텀 형식에는 JSON 형식 (FormatJSON) 을 권장하며, SetFormat으로 설정할 수 있습니다.

생성

go
recorder := dd.NewLoggerRecorder()

핵심 메서드

메서드시그니처설명
Writer() io.Writerio.Writer 가져오기
SetFormat(format LogFormat)로그 형식 설정 (파싱에 사용)
NewLogger(cfg ...Config) (*Logger, error)이 레코더에 쓰는 Logger 생성
Entries() []LogEntry모든 로그 항목 가져오기
Count() int항목 수
Clear()모든 항목 제거
HasEntries() bool항목 존재 여부
LastEntry() *LogEntry가장 최근 항목 (nil 안전)

단언 메서드

메서드시그니처설명
EntriesAtLevel(level LogLevel) []LogEntry레벨별 항목 필터
ContainsMessage(msg string) bool지정 메시지 포함 여부 (정확히 일치 또는 부분 문자열 일치)
ContainsField(key string) bool지정 필드 포함 여부
GetFieldValue(key string) any첫 번째로 일치하는 필드값 가져오기

사용 예

기본 테스트

go
func TestLogger(t *testing.T) {
    rec := dd.NewLoggerRecorder()
    logger, _ := rec.NewLogger()

    logger.Info("hello")
    logger.Warn("warning")

    if rec.Count() != 2 {
        t.Errorf("expected 2 entries, got %d", rec.Count())
    }

    if !rec.ContainsMessage("hello") {
        t.Error("should contain 'hello'")
    }
}

레벨 단언

go
func TestLogLevel(t *testing.T) {
    rec := dd.NewLoggerRecorder()
    // 주의: Recorder 는 ISO 8601 타임스탬프로 레벨을 파싱하며, DevelopmentConfig 의
    // 시간 형식 ("15:04:05.000") 은 호환되지 않으므로 DefaultConfig 로 수동 설정 DEBUG.
    cfg := dd.DefaultConfig()
    cfg.Level = dd.LevelDebug
    logger, _ := rec.NewLogger(cfg)

    logger.Debug("debug")
    logger.Info("info")
    logger.Error("error")

    errors := rec.EntriesAtLevel(dd.LevelError)
    if len(errors) != 1 {
        t.Errorf("expected 1 error, got %d", len(errors))
    }

    debugs := rec.EntriesAtLevel(dd.LevelDebug)
    if len(debugs) != 1 {
        t.Errorf("expected 1 debug, got %d", len(debugs))
    }
}

구조화 필드 단언

go
func TestStructuredLog(t *testing.T) {
    rec := dd.NewLoggerRecorder()
    logger, _ := rec.NewLogger()

    logger.InfoWith("user login",
        dd.String("user", "admin"),
        dd.String("ip", "192.168.1.1"),
    )

    if !rec.ContainsField("user") {
        t.Error("should contain 'user' field")
    }

    user := rec.GetFieldValue("user")
    if user != "admin" {
        t.Errorf("expected user=admin, got %v", user)
    }
}

마지막 로그

go
func TestLastEntry(t *testing.T) {
    rec := dd.NewLoggerRecorder()
    logger, _ := rec.NewLogger()

    logger.Info("first")
    logger.Error("second")

    last := rec.LastEntry()
    if last.Level != dd.LevelError {
        t.Errorf("expected Error level, got %v", last.Level)
    }
    if last.Message != "second" {
        t.Errorf("expected 'second', got %s", last.Message)
    }
}

LogEntry

캡처된 로그 항목 구조.

go
type LogEntry struct {
    Level     LogLevel
    Message   string
    Fields    []Field
    Timestamp time.Time
    Format    LogFormat
    RawOutput string
}

다음 단계