Fixture 관리
테스트를 짜다보면 테스트 준비에 항상 공통으로 나오는 데이터들이 생기고 여기서 데이터를 조금만 바꿔서 코드를 짜게되는 상황이 자주 발생합니다.
이럴때 사용할만한 팁이 몇 가지 있습니다.
create function 생성
제일 좋은 방법은 fixture 생성 함수를 trait로 만들고 이를 필요한 테스트마다 상속받아 공유하는 방법입니다.
아래 코드는 간단한 예제입니다.
case class Request(id: Long, target: Option[String], requestedAt: LocalDateTime)
trait RequestFixture {
def createRequest(
id: Long,
target: Option[String] = None,
requestedAt: LocalDateTime = LocalDateTime.now()
): Request = Request(id, target, requestedAt)
}
class RequestFixtureSpec extends AnyFunSuite with RequestFixture {
test("픽스쳐 테스트") {
val request = createRequest(-1L)
// ....test
}
}
이렇게 함수로 만들어둘경우 좋은 점은 팀 단위로 서비스를 개발할 때 리팩터링을 진행하면 테스트에서도 같이 수정이 진행되고, 어느 부분까지 영향 범위 내인지 빌드 단계에서 확인이 가능하고 추적할 수 있다는 것입니다.
유지보수하기 편하기 때문에 가장 좋아하는 방법입니다.
테스트 클래스 내부에서 object 활용
하나의 테스트 클래스에서만 공유하는 데이터가 있다면 private object 를 활용해서 공통으로 사용할 수 있습니다.
아래 코드는 간단한 예제입니다.
class RequestFixtureSpec extends AnyFunSuite {
import Fixture._
test("픽스쳐 테스트") {
val request = RequestFixture
// ....test
}
private object Fixture {
private final val Id: Long = -1
private val Now = LocalDateTime.now()
private val RequestFixture = Request(
id = Id,
data = None,
requestedAt = Now,
)
}
}
이렇게 하나의 테스트 클래스 내부에서만 공유하는 데이터를 사용할 때는 private object를 만들어 사용하면 편리합니다.
이 방법의 장점은 private fixture이어서 내부에서만 조작하기 때문에 관리가 용이하고, fixture 데이터가 외부에 영향을 끼치지 않습니다. 또한, fixture 데이터를 하나의 파일 내부에서 한 번에 확인이 가능하여 사용하고 수정하기도 편합니다.
given 데이터 case class 카피하기
위의 함수로 만들거나 private object를 활용하지 않는다면 공통의 object에 필요한 fixture들을 모아두고 사용하게 될 텐데, 이러한 방식으로 사용하게 되면 fixture의 정보가 수정되면 모든 테스트 suite가 실행할 때 깨지게 된다는 문제가 있습니다.
배포할 때 테스트를 자동으로 수행하게 만들지 않았다면 이 수정의 영향을 프로그래머가 직접 테스트를 수행하기 전까지는 모르게 된다는 문제점이 있습니다 (create 함수로 만들면 대부분 build 단계에서 문제가 발생해 프로그래머가 인지하기 좋습니다).
fixture의 수정에 영향을 받지 않게 만들려면 case class일경우 copy해서 사용하면 됩니다.
class RequestFixtureSpec extends AnyFunSuite with RequestFixture {
test("픽스쳐 테스트") {
val request = RequestFixture.copy(id = ???, data = ???)
// ....test
}
}
trait RequestFixture {
val RequestFixture = Request(
id = Id,
data = None,
requestedAt = Now,
)
}
object 활용 팁에서 단순히 copy 코드만 추가되었습니다.
이러한 검증은 대부분 필요한 정보만 수정하면 되므로 필요한 id, data만 copy에서 수정하여 코드를 짰습니다.
copy를 사용해 given 데이터를 만들게 되면 팀에서 개발 중 Fixture를 수정해도 내가 검증할 테스트에는 문제가 발생하지 않을 가능성이 높아져 테스트를 개발하기 편해집니다.
다만 여전히 build 단계에서 문제를 발견할 수 없기 때문에 create 함수를 만드는 방법을 더욱 추천합니다.