본문 바로가기

끄적끄적

[끄적끄적] E2E(API) 테스트 자동화 도입기

(운영환경과 비슷한 환경에서 API 사용자 입장에서 종단까지 테스트 한다는 의미로 E2E 테스트와 API 테스트를 혼용해서 사용하고 있습니다.)

 

최근, 테스트의 중요성을 깨닫게된후 TDD나 ATDD 방법론에 따라 개발을 진행하고 테스트 커버리지를 도입하는등 더 안정적인 서비스를 구축하기 위해서 노력을 기울이고 있습니다. 실제로, 이러한 방법론을 적용하니, 목표 커버리지 70%를 훨씬 넘는 수치를 달성하고 꼼꼼한 테스트를 작성했다는 생각을 하기도 했었습니다.

 

그렇다면, 이러한 노력이 (QA 단계에서) 적은 버그로 이어졌을까요? 창피하게도 여전히 버그는 발생했고, 심지어 꼼꼼히 테스트를 하고 버그가 발생하지 않을것 이라 예상한 API에서도 버그가 발생했었습니다. 

😂😂😂😂😂

문제의 원인은 다음과 같은 예측하지 못한 여러가지 변인에 있었습니다.

 

1. 캐시될 것 이라 예상한 API가 캐시 되지 않았고, 테스트하지 못해서 QA단계에서 버그 발생
2. jpql을 사용하지 않은채 native query를 사용한 몇몇 로직 때문에 sql이 달라 QA단계에서 버그 발생
3. 기타 여러가지 모킹 처리한 인프라에서 버그 발생

 

이런곳은 테스트하기 어렵죠 :) 

문제의 원인은 테스트 환경과 운영환경이 일치하지 않았기 때문이었습니다. 이를 계기로 "운영환경과 일치하는 환경" (성능은 다르더라도) 에서 테스트를 진행할 필요성을 느끼게 되었고, API 테스트 도입을 결심하게 되었습니다.

 

API 테스트 도입

API 테스트툴로 유명한것은 Karate가 있습니다. 저희 프로젝트는 자바로 작성되었기 때문에, 같은 자바 기반의 테스트 툴인 Karate가 매력적으로 느껴지기도 했습니다. 하지만, 다음과 같은 이유 때문에 팀에 완전히 딱 맞는다고 생각되지는 않아서 다른 테스트 툴을 찾기로 결심했습니다.

 

GitHub - karatelabs/karate: Test Automation Made Simple

Test Automation Made Simple. Contribute to karatelabs/karate development by creating an account on GitHub.

github.com

 

1. 높은 러닝커브와 쌓여있는 백로그

해야할것은 많은데, 테스트를 위해서 또 무엇인가를 배워야 한다면, 빠르게 배우고 빠르게 적용 가능해야했습니다. 인수테스트와 단위테스트가 촘촘한 상황에서, 테스트에 더 시간을 쏟는거보다 당장 출시를 위해 빠르게 개발하는게 중요했거든요. 또한, 앞서 말했듯 이미 인수테스트와 단위테스트가 촘촘했기 때문에 API 테스트에서 꼼꼼히 테스트 하기보단 정말 중요한 부분(Golden path)만 테스트 하기로 회의를 했었습니다.

 

아래 코드블록은 Karate로 작성된 테스트의 예시입니다. 한번에 슉슉 읽히기는 하지만 결국 karate만의 dsl을 익혀야하고 문서가 굉장히 방대합니다.

Scenario: create and retrieve a cat

Given url 'http://myhost.com/v1/cats'
And request { name: 'Billie' }
When method post
Then status 201
And match response == { id: '#notnull', name: 'Billie }

Given path response.id
When method get
Then status 200

 

2. 빠른 속도

테스트 환경이 github action free plan 인 만큼 빠르게 수행되어야 했습니다.

 

이러한 이유 때문에, karate의 적용은 보류하고 다른 테스트 툴을 찾던중, HURL 을 발견하게 되었습니다.

 

GitHub - Orange-OpenSource/hurl: Hurl, run and test HTTP requests with plain text.

Hurl, run and test HTTP requests with plain text. Contribute to Orange-OpenSource/hurl development by creating an account on GitHub.

github.com

아래 코드블록은 위의 karate로 작성된 코드를 HURL로 똑같이 작성한것 입니다. HURL은 익숙한 HTTP 용어도 많이 보여서 배우기 쉬워 보였습니다.

# Scenario: create and retrieve a cat

POST http://myhost.com/v1/cats
{ "name": "Billie" }
HTTP 201
[Captures]
cat_id: jsonpath "$.id"
[Asserts]
jsonpath "$.name" == "Billie"

GET http://myshost.com/v1/cats/{{cat_id}}
HTTP 200

실제로, 영어를 잘 못하는데도 문서를 다 읽고 적용하는데 약 2시간 정도밖에 걸리지 않았을 만큼 러닝커브가 낮았던거 같아습니다. 또한, HURL은 별도의 runtime이 필요없어서 설치도 편하고 실행도 빨랐습니다.

 

최종적으로 개발부터 배포까지 아래와 같은 CI/CD 환경을 구축하게 되었습니다.

 

CI/CD pipeline

 

후기

API 테스트를 도입한 후 바로 다음 QA에서는 버그가 발견되지 않았을 만큼 API 테스트는 효과가 좋았고, 투자 대비 이득이 컷다고 생각합니다. 😀

 

아래는 E2E 테스트 도입을 결심하며, 고민했던 내용입니다. 혹시나, 팀에 이런 테스트 툴 도입을 고민하시는 분이 있다면 도움이 되면 좋겠습니다.

 

1. E2E 테스트를 하는데, 인수테스트를 작성해야 할까?

E2E 테스트는 인프라 환경 구축부터, 실제 서버를 띄워야해서 인수테스트보다 시간이 더 오래 걸립니다. 즉, 인수테스트보다 자주 수행하기 힘들며, 이 때문에 저희팀은 인수테스트와 E2E 모두 작성하기로 결정했고 E2E(중요한 로직), 인수테스트(중요한 로직, 덜 중요한 로직) 과 같이 테스트 했습니다.

 

2. HURL 에는 Import가 없습니다.

E2E 테스트를 작성할때, 로그인과 같이 중복되는 로직이 많이 생겼는데, HURL에서는 이 로직을 매번 작성해줘야 했습니다. 약간 불편하긴 했는데 감수할정도라고 생각합니다. 

아래는 Import를 추가해달라는 관련 PR입니다. 검토해보겠다는 말은 있는데 실제로 적용되지는 않았습니다.

다만, 3-4개월전에 마지막으로 확인한거라 지금은 적용되었을지 모르겠네요 🥸 (아직 Issue가 open인걸 보면 아직 진행중인것 같습니다.)

https://github.com/Orange-OpenSource/hurl/issues/115

 

Feature Requests: Imports · Issue #115 · Orange-OpenSource/hurl

First of all: thanks for building this! I really like the general idea. A great feature would be imports to reuse requests (e.g. login flows) and to be able to scale larger test suites.

github.com