Go testify 패키지

1 개요[ | ]

Testify - Thou Shalt Write Tests
테스티파이 - 테스트를 작성하라
  • 코드가 의도대로 작동하는 것을 검증하기 위한 여러가지 도구를 제공하는 Go 패키지 세트
  • 장점
    • 쉬운 어설션(easy assertion)
    • 목 작성(mocking)
    • 테스트 스위트 인터페이스 및 함수

2 assert 패키지[ | ]

  • assert 패키지는 Go에서 더 나은 테스트 코드를 작성할 수 있는 몇 가지 유용한 메소드를 제공한다.
    • 친절하고 읽기 쉬운 오류 설명 프린트
    • 가독성 있는 코드 작성 가능
    • 필요시 각 어설션에 설명 메시지 추가
  • 다음 예시를 보자.
package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {

  // 같음 확인
  assert.Equal(t, 123, 123, "they should be equal")

  // 같지 않음 확인
  assert.NotEqual(t, 123, 456, "they should not be equal")

  // nil 확인 (오류에 적절하다)
  assert.Nil(t, object)

  // nil 아님 확인 (뭔가 있기를 기대할 때 적절하다)
  if assert.NotNil(t, object) {

    // object가 nil이 아니라는 것을 확인했으므로
    // 오류 없이 안전하게 추가 확인을 할 수 있다
    assert.Equal(t, "Something", object.Value)

  }

}
  • 모든 assert func는 testing.T 객체를 첫 번째 인수로 사용한다. 이것이 일반적인 go 테스트 기능을 통해 오류를 작성하는 방법이다.
  • 모든 assert func는 어설션이 성공했는지 여부를 나타내는 bool을 반환한다. 이는 특정 조건에서 계속해서 어설션을 계속하려는 경우에 유용하다.
  • 여러 번 어설션하려는 경우, 다음과 같이 하자.
package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {
  assert := assert.New(t)

  // 같음 확인
  assert.Equal(123, 123, "they should be equal")

  // 같지 않음 확인
  assert.NotEqual(123, 456, "they should not be equal")

  // nil 확인 (오류에 적절하다)
  assert.Nil(object)

  // nil 아님 확인 (뭔가 있기를 기대할 때 적절하다)
  if assert.NotNil(object) {

    // object가 nil이 아니라는 것을 확인했으므로
    // 오류 없이 안전하게 추가 확인을 할 수 있다
    assert.Equal("Something", object.Value)
  }
}

3 require 패키지[ | ]

require 패키지는 assert 패키지와 동일한 글로벌 함수를 제공하지만 boolean 결과를 반환하는 대신 현재 테스트를 종료한다.

자세한 내용은 t.FailNow를 참조하자.

4 mock 패키지[ | ]

mock 패키지는 테스트 코드를 작성할 때 실제 객체 대신 사용할 수 있는 모의 객체를 쉽게 작성할 수 있는 메커니즘을 제공한다.

예시 테스트 함수는, 외부 객체 testObj에 의존하는 코드 조각을 테스트하며, 기대값를 설정해두고 실제로 그렇게 되는지 확인할 수 있다.

package yours

import (
  "testing"
  "github.com/stretchr/testify/mock"
)

/*
  테스트 객체
*/

// MyMockedObject는 테스트하는 코드가 의존하는 객체를 기술한 인터페이스를 구현한 모의 객체이다.
type MyMockedObject struct{
  mock.Mock
}

// DoSomething은 일부 인터페이스를 구현하고 활동을 기록하고, 모의 객체가 지시한대로 return하는 MyMockedObject의 메소드이다.
//
// 실제 객체에서 이 메소드는 유용한 작업을 수행하지만 이것은 모의 객체이므로 스텁으로 처리할 것이다.
//
// NOTE: 이 메소드는 여기서 테스트되지 않으며 이 객체를 사용하는 코드가 테스트된다.
func (m *MyMockedObject) DoSomething(number int) (bool, error) {

  args := m.Called(number)
  return args.Bool(0), args.Error(1)

}

/*
  실제 테스트 함수
*/

// TestSomething은 테스트 객체를 사용하여 테스트할 일부 대상 코드에 대한 어설션을 만드는 방법의 예시이다.
func TestSomething(t *testing.T) {

  // 테스트 객체의 인스턴스 생성
  testObj := new(MyMockedObject)

  // 기대값 설정
  testObj.On("DoSomething", 123).Return(true, nil)

  // 테스트할 코드 호출
  targetFuncThatDoesSomethingWithObj(testObj)

  // 기대값을 충족하는지 확인
  testObj.AssertExpectations(t)


}

// TestSomethingWithPlaceholder는 테스트 객체를 사용하여 테스트할 일부 대상 코드에 대한 어설션을 만드는 방법에 대한 두 번째 예시이다.
// 이번에는 플레이스홀더를 사용한다. 전달되는 데이터가 일반적으로 동적으로 생성되고 미리 예측할 수 없는 경우(예: 시간에 민감한 해시 포함) 플레이스홀더가 사용될 수 있다.
func TestSomethingWithPlaceholder(t *testing.T) {

  // 테스트 객체의 인스턴스 생성
  testObj := new(MyMockedObject)

  // 인수 목록의 플레이스홀더를 가지고 기대값 설정
  testObj.On("DoSomething", mock.Anything).Return(true, nil)

  // 테스트할 코드 호출
  targetFuncThatDoesSomethingWithObj(testObj)

  // 기대값을 충족하는지 확인
  testObj.AssertExpectations(t)


}

// TestSomethingElse2는 Unset 메소드를 사용하여 핸들러를 정리한 다음 새 핸들러를 추가하는 방법을 보여주는 세 번째 예시이다.
func TestSomethingElse2(t *testing.T) {

  // 테스트 객체의 인스턴스 생성
  testObj := new(MyMockedObject)

  // 인수 목록의 플레이스홀더를 가지고 기대값 설정
  mockCall := testObj.On("DoSomething", mock.Anything).Return(true, nil)

  // 테스트할 코드 호출
  targetFuncThatDoesSomethingWithObj(testObj)

  // 기대값을 충족하는지 확인
  testObj.AssertExpectations(t)

  // 다른 핸들러를 추가할 수 있도록 기존 핸들러를 제거한다
  mockCall.Unset()

  // 이제 true 대신 false를 반환한다
  testObj.On("DoSomething", mock.Anything).Return(false, nil)

  testObj.AssertExpectations(t)
}

모의 코드를 작성하는 방법에 대한 자세한 내용은 mock 패키지에 대한 API 문서를 확인하자.

mockery 도구를 사용하면 인터페이스에 대한 모의 코드를 자동생성하여 mock을 훨씬 빠르게 사용할 수 있다.

5 suite 패키지[ | ]

suite 패키지는 보다 일반적인 객체 지향 언어에서 사용할 수 있는 기능을 제공한다. 이를 통해.0 테스트 스위트를 구조체로 빌드하고, 구조체에 셋업/해체 메서드와 테스트 메소드를 빌드하고, 'go test'로 실행할 수 있다.

suite 예시는 다음과 같다.

// 기본 임포트
import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/suite"
)

// suite를 정의하고, testify로부터 빌트인 기본 스위트 기능을 흡수하며, 여기에는 현재 테스트 컨텍스트를 반환하는 T() 메소드가 포함된다.
type ExampleTestSuite struct {
    suite.Suite
    VariableThatShouldStartAtFive int
}

// 각 테스트 전에 VariableThatShouldStartAtFive가 5로 설정되었는지 확인한다.
func (suite *ExampleTestSuite) SetupTest() {
    suite.VariableThatShouldStartAtFive = 5
}

// "Test"로 시작되는 모든 메소드는 스위트 내에서 테스트로서 실행된다.
func (suite *ExampleTestSuite) TestExample() {
    assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}

// 'go test'가 이 스위트를 실행하려면 일반적인 테스트 함수를 작성하고 스위트를 suite.Run에 전달해야 한다.
func TestExampleTestSuite(t *testing.T) {
    suite.Run(t, new(ExampleTestSuite))
}

suite 패키지에서 제공하는 모든 기능을 사용하는 보다 완전한 예시를 보려면, 예제 테스트 스위트를 살펴보자.

스위트 작성에 대한 자세한 내용은, suite 패키지에 대한 API 문서를 확인하자.

Suite 객체에는 어설션 메서드가 있다.

// 기본 임포트
import (
    "testing"
    "github.com/stretchr/testify/suite"
)

// suite를 정의하고, testify로부터 빌트인 기본 스위트 기능을 흡수하며, 여기에는 어설션 메소드가 포함된다.
type ExampleTestSuite struct {
    suite.Suite
    VariableThatShouldStartAtFive int
}

// 각 테스트 전에 VariableThatShouldStartAtFive가 5로 설정되었는지 확인한다.
func (suite *ExampleTestSuite) SetupTest() {
    suite.VariableThatShouldStartAtFive = 5
}

// "Test"로 시작되는 모든 메소드는 스위트 내에서 테스트로서 실행된다.
func (suite *ExampleTestSuite) TestExample() {
    suite.Equal(suite.VariableThatShouldStartAtFive, 5)
}

// 'go test'가 이 스위트를 실행하려면 일반적인 테스트 함수를 작성하고 스위트를 suite.Run에 전달해야 한다.
func TestExampleTestSuite(t *testing.T) {
    suite.Run(t, new(ExampleTestSuite))
}

6 설치[ | ]

  • testify를 설치하려면, go get을 사용하자.
go get github.com/stretchr/testify
  • 이렇게 하면 다음 패키지들을 사용할 수 있게 된다.
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
github.com/stretchr/testify/mock
github.com/stretchr/testify/suite
github.com/stretchr/testify/http (deprecated)

다음 템플릿을 활용하여 자신의 코드에 testify/assert 패키지를 임포트해보자.

package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {

  assert.True(t, true, "True is true!")

}

7 최신 유지[ | ]

  • testitfy를 최신 버전으로 업데이트하려면, go get -u github.com/stretchr/testify를 사용하자.

8 같이 보기[ | ]

9 참고[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}