🧪

테스트 — RSpec 없이 사는 법

Go의 테스트는 표준 라이브러리에 내장되어 있다. gem install 불필요.

Ruby 테스트 환경을 세팅해본 사람은 안다. RSpec 설치, spec_helper.rb 설정, FactoryBot 세팅, DatabaseCleaner 추가, shoulda-matchers 연결... 처음 테스트 한 줄 돌리기까지 30분은 걸린다.

Go는? _test.go 파일을 만들고 go test를 실행하면 끝이다.

파일 이름이 규칙이다

user.go 파일의 테스트는 user_test.go에 쓴다. _test.go로 끝나는 파일은 go test 실행 시에만 컴파일된다. Ruby의 spec/ 디렉토리 분리 대신 소스 파일 옆에 테스트 파일을 놓는다.

RSpec의 describe/it vs Go의 Test함수

Ruby:

RSpec.describe User do
  it "has a name" do
    expect(user.name).to eq("kim")
  end
end

Go:

func TestUserName(t *testing.T) {
    user := User{Name: "kim"}
    if user.Name != "kim" {
        t.Errorf("expected kim, got %s", user.Name)
    }
}

RSpec의 DSL에 익숙하면 Go의 테스트가 원시적으로 보일 수 있다. expect/to 같은 매처(matcher)가 없다. if문으로 직접 비교한다. 이건 Go의 "표준 라이브러리로 충분하다" 철학이다.

테이블 주도 테스트 — Go의 핵심 패턴

Go에서 여러 케이스를 테스트할 때는 struct 슬라이스로 테스트 케이스를 정의한다:

tests := []struct{ input int; want int }{
    {1, 2}, {2, 4}, {3, 6},
}
for _, tt := range tests {
    got := double(tt.input)
    if got != tt.want {
        t.Errorf("double(%d) = %d, want %d", tt.input, got, tt.want)
    }
}

RSpec의 shared_examples와 비슷한 역할이다.

go test -v, -run, -cover

go test -v — 상세 출력 (RSpec --format documentation 같은 것)
go test -run TestUser — 특정 테스트만 실행 (rspec spec/models/user_spec.rb 같은 것)
go test -cover — 커버리지 확인 (simplecov 같은 것)

별도 gem 설치 없이 전부 내장이다.

Ruby에서 Go로

1

Ruby: spec/ 디렉토리 + RSpec gem → Go: _test.go 파일 (내장, gem 불필요)

2

Ruby: describe/it/expect → Go: func TestXxx(t *testing.T) + if + t.Errorf

3

Ruby: shared_examples → Go: 테이블 주도 테스트 (struct 슬라이스)

4

Ruby: rspec --format doc → Go: go test -v / -run / -cover (전부 내장)

장점

  • 설정 제로 — gem install, spec_helper, .rspec 파일 전부 불필요
  • go test -cover가 내장 — SimpleCov 없이 커버리지 확인 가능

단점

  • RSpec의 expect().to eq() 같은 가독성 높은 매처가 없다 — if문이 장황
  • FactoryBot 같은 테스트 데이터 생성 도구가 표준에 없다 — 직접 구현 필요

사용 사례

RSpec 없이도 충분한 테스트를 작성하고 싶을 때 (Go 표준 testing 패키지)

참고 자료