개발 조각글

Unity - 유닛테스트를 염두한 함수 설계

BaekNohing 2022. 8. 8. 19:30

 

a cute cat snail

유닛테스트를 염두한 함수설계


유닛테스트를 여기저기 붙이다보니, 붙이기 쉬운 구조가 있고 어려운 구조가 있다는 것을 느끼고 있다. 당연한 이야기일 수 있지만 정리도 할 겸 기록해 둔다. 

클래스 내에서 데이터를 가공하는 함수를 만들어야 할 때. 다음과 같은 함수를 생각해볼 수 있다. 

float stamina; 

float RecoverStamina(float recoverValue){
	stamina += recoverValue;
	return stamina;
}

이 경우 RecoverStamina는 호출 시 클래스 내의 Stamina에 접근해 RecoverValue를더한 뒤 Stamina를 반환한다. 기능적으로는 문제가 없는 함수라고 생각하지만, 이 경우에 테스트를 붙이기 정말 어려웠다.. 특히, 이 Stamina가 GetStamina()로 값을 바로 받아올 수 있는게 아니라 "bool CheckMoveAble(float CompareValue) { ... } " 따위의 함수로 오직 체크만 할 수 있도록 열려있는 경우. RecoverStamina가 제대로 작동하는지 확인하기 위해서는 CompareValue의 값이 True > False로 넘어가는 순간을 포착해서 Stamina의 값이 얼마인지 어림하는 수 밖에 없다..

이 경우 GetStamina()를 하나 만들어버리는게 나을 수 있겠지만, 기존의 모든 함수들이 저렇게 짜여있는 상태에서. 프로젝트 막바지인 상황을 생각한다면.. 유닛테스트 하나를 붙이기 위해 기존 코드와의 일관성을 깨트리는 GetStamina()를 붙여야 하는거니까, 그것도 옳은 대안이 될 수 없다고 생각했다.

대신 함수를 계획하는 단계에서 다음과 같은 형태를 갖도록 하는게 좋지 않을까? 생각했는데.  

float stamina; 

float RecoverStamina(float stamina, float recoverValue){
	return stamina + recoverValue;
}

RecoverStamina의 인자에 stamina와 recoverValue를 명시하는 것이다. Stamina의 값은 함수를 호출할 당시에 호출하는 주체가 들고있거나 or 보관하는 장소를 기억해뒀다가, 거기 있는 Stamina에 결과값을 넣어주는걸로 결과를 갱신하는 것이다. 

이렇게 하면, 1. 유닛테스트를 짤 때 저 외부의 stamina를 직접 참조하는게 아니니까. 내가 원하는 값들을 다양하게 만들어서 시험해볼 수 있고. 2. 이건 넣는 값에 따라서 항상 일정한 값이 나오니까, 만약에 문제가 생기면 함수 로직만 들여다보면 된다! ( 처음 함수는 외부에서 참조하고있는 Stamina에따라 recoverValue에 같은 값을 집어넣어도 매번 바뀌기 때문에 올바른 결과인지 직관적으로 깨닫기 어렵다. 특히.. 지금은 stamina 하나뿐이지만, HP, MP와 같은 여러 값을 동시에 참조하고 있다고 생각해보면.. )

이런 연유로, 당장 TDD를 도입하는 건 어려울 수 있지만, 아래와같은 방식을 염두해 두면서 설계한다면. 좀 더 테스트를 붙이기 쉬운 프로젝트가 될 수 있지 않을까 생각한다.