Go testify 패키지

Jmnote (토론 | 기여)님의 2024년 3월 11일 (월) 19:14 판 (→‎suite 패키지)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

1 개요[ | ]

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

2 assert 패키지[ | ]

  • assert 패키지는 Go에서 더 나은 테스트 코드를 작성할 수 있는 몇 가지 유용한 메소드를 제공한다.
    • 친절하고 읽기 쉬운 오류 설명 프린트
    • 가독성 있는 코드 작성 가능
    • 필요시 각 어설션에 설명 메시지 추가
  • 다음 예시를 보자.
Go
Copy
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을 반환한다. 이는 특정 조건에서 계속해서 어설션을 계속하려는 경우에 유용하다.
  • 여러 번 어설션하려는 경우, 다음과 같이 하자.
Go
Copy
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에 의존하는 코드 조각을 테스트하며, 기대값를 설정해두고 실제로 그렇게 되는지 확인할 수 있다.

Go
Copy
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 예시는 다음과 같다.

Go
Copy
// 기본 임포트
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 객체에는 어설션 메서드가 있다.

Go
Copy
// 기본 임포트
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을 사용하자.
Bash
Copy
go get github.com/stretchr/testify
  • 이렇게 하면 다음 패키지들을 사용할 수 있게 된다.
Go
Copy
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 패키지를 임포트해보자.

Go
Copy
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 참고[ | ]