본문 바로가기
자동화

Python을 이용해 Builder 패턴으로 API 자동화 테스트 코드 구성하기

by 도천수 2025. 4. 29.

안녕하세요 원티드랩 QA팀 김명관입니다.
저는 올해 2월부터 원티드의 기업향 대시보드 제품을 대상으로 API 테스트 자동화를 구성하고 있었습니다. 최근 1차로 목표했던 기능 단위의 API 테스트 자동화를 마쳤고 중간 성과 점검을 진행했습니다. 2차로 목표하고 있는 유저 시나리오는 아직 도출하고 있는 단계이고 진행하지는 못했지만 앞으로 지속할 수 있을 정도의 충분한 성과와 가치를 확인할 수 있었어요.
그래서 오늘은 원티드랩 QA팀에서 어떻게 Python을 활용해 API 테스트 자동화를 구성했는지 공유해보겠습니다.


자동화 테스트 피라미드

자동화 테스트를 공부하다 보면 자동화 테스트 피라미드라는 개념을 접하게 됩니다. 이 피라미드의 의미는 전략적인 자동화 테스트를 구성하기 위해서 GUI 테스트보다 API 테스트를, API 테스트보다 Unit테스트를 더 적극적으로 시도해야 한다는 것입니다.
하지만 안타깝게도(저만 그런건지 모르겠지만) API 자동화 테스트보다는 GUI 자동화 테스트를 더욱 쉽게 접하게 되곤 합니다. 따라서 GUI 자동화 테스트를 먼저 학습하게 되죠. 그러다보면 "자동화"에 대한 좋은 사례를 접하기도 전에 GUI 자동화 테스트의 가장 큰 벽인 "유지보수"라는 큰 장애물에 지쳐 적당히 타협하거나 포기하게 되는 일이 많습니다.
"잘" 구성된 자동화 테스트는 개인, 제품, 팀, 회사에 많은 이점을 가져다 줍니다. 비록 저도 원티드랩에서 GUI 자동화 테스트로 자동화 테스트 구성을 시작했지만, 더욱 탄탄한 기반을 가진 자동화 테스트 셋을 구성하기 위해 잠시 접어두고 API 자동화 테스트를 구성하기 시작하게 되었습니다.


목표 정하기

무계획으로 달려나가기보다 몇가지 세부적인 목적을 식별하고 그 목적을 달성하기 위한 목표를 수립해야 중간에 길을 잃지 않고 무사히 자동화 테스트를 구성할 수 있을거라고 생각했어요. 가장 큰 목적은 API 자동화 테스트 셋을 성공적으로 구성하는 것이겠죠. 그 외에도 유지보수에 필요한 시간을 줄이고 가능하다면 각각의 API로 많은 케이스를 테스트 하고 싶었어요. 특히 비정상적인 입력값이나 예외적인 사항에 대해서요.
사실 위에서 말씀드린 것은 개발 단계에서 검증이 완료되어야 하겠지만 많은 공수가 들지 않는다면 제가 만드는 API 자동화 테스트 셋에서도 구현이 되면 좋겠다는 욕심이 있었습니다.
그래서 첫번째 목표는 대상 제품의 주요 기능들에 대한 API별 테스트를 먼저 구성하는 것이 되었습니다. 그리고 두번째 목표는 첫번째 목표를 달성한 코드를 재사용해서 유저 시나리오 테스트를 구성하는 것이었어요.


자동화 테스트 구현하기

유지보수에 필요한 시간을 줄이자
각각의 API로 많은 케이스를 테스트하자
첫번째 목표에서 구현한 코드를 재활용하자

라는 세가지 목표를 달성하기 위해서는 테스트를 구성하는 파일을 역할에 따라 나누는 것이 필요하다고 생각했습니다. API의 URL을 관리하는 파일, 파라미터를 관리하는 파일, 테스트 데이터를 관리하는 파일, 실제로 테스트를 수행하는 파일과 같이요. 그래서 몇가지 디자인 패턴을 찾아보게 되었습니다.
API 자동화 테스트에서 주로 사용되는 디자인 패턴들은 POM이나 Factory 등이 있다는 사실을 알게되어 샘플 코드를 작성해 보았습니다.
POM 패턴의 경우 API 테스트를 페이지 단위로 구성하지 않을 것이라 제외했습니다. 그리고 UI 자동화 테스트에 이미 활용하고 있는 패턴이라 새로운 패턴을 경험해 보고 싶었어요. Factory 패턴은 파일과 코드의 구조화로 유지보수에 필요한 시간을 줄여줄 수 있었습니다. 구현한 코드를 재활용 할 수도 있었구요. 하지만 많은 케이스를 테스트 하기 위해서는 파라미터 셋을 반복해서 구성해야 한다고 보여졌습니다.
최종적으로는 Builder 패턴을 사용하게 되었습니다.API의 구조와 파라미터를 명시하는 "빌더"와 빌더를 호출해 필요한 파라미터에 다양한 값들을 체이닝 해 테스트 할 수 있어 제 요구사항을 모두 만족하는 패턴이었습니다.(라고 느꼈습니다.)
API 자동화 테스트에 Builder 패턴을 사용하는 것은 일반적이지는 않다고 합니다. 하지만 제 목표중 특히 수많은 케이스를 가능한 적은 양의 코드로 구현하기에는 아직까지 제가 찾은 방법 중에는 이것이 제일 좋아 보여요.
혹시 더 좋은 방법을 알고 계신다면 부디 알려주시면 감사하겠습니다. 😊
빌더의 구조는 대략 이렇습니다.

Class APIBuilder:
	def __init__(self):
        self.builder = {
            "parameter1": “parameter1”,
            "parameter2": “parameter2”,
            "parameter3": “parameter3”,
        }
    
    def with_parameter1(self, parameter1):
    	self.builder["parameter1"] = parameter1
        return self
    
    def with_parameter2(self, parameter2):
    	self.builder["parameter2"] = parameter2
        return self
        
    ...
    
    def build(self):
    	return self.builder

 
이것을 pytest와 httpx를 이용해 테스트 함수를 만들어 호출하였고, 각각의 parameter에는 pytest에서 제공하는 paramterize를 이용한다면 수많은 테스트 케이스를 수행할 수 있었습니다. 다음과 같이 paramtrize를 사용한다면 다음의 예시에서는 30개의 케이스를 테스트 할 수 있는 것이죠.

@pytest.mark. parametrize(
	"parametrize1, parametrize2, parametrize3",
    [
    	("케이스1", "케이스1", "케이스1"),
        ("케이스2", "케이스2", "케이스2"),
        ...
        ("케이스30", "케이스30", "케이스30")
    ]
)

그래서

현재는 약 2개월에 걸쳐 API 자동화 테스트 작업 환경 세팅, 운영 환경 세팅 등을 포함해 1차 목표였던 대시보드 주요 기능의 API들의 모든 빌더와 기능 별 테스트를 모두 구현해 512개의 케이스가 운영되고 있습니다. 만들어둔 API 빌더들을 활용하면 아주 손쉽게 유저 시나리오 또한 테스트로 구현이 가능해요. 빌더를 만드는게 오래걸리지 만든 빌더를 가져다 쓰는건 쉽게 할 수 있거든요.
이렇게 API 자동화 테스트의 1차 목표를 완료하고 나서 ROI를 점검해 보았을 때도 어렵지 않게 손익분기점에 도달할 것으로 확인되었고, 앞으로 테스트 결과를 단순히 보고만 하는데 그치지 않고 더 많은 가치를 창출할 수 있는 수단으로 이용하기 위한 고민도 원활하게 이어지면 좋겠습니다!