백엔드 개발자가 만들어 본 App 테스트 자동화 (feat. Appium, Jenkins, AWS DeviceFarm)
안녕하세요! QA엔지니어(?) Jay입니다 ㅋㅋㅋㅋ ~는 아니고 저는 백엔드 개발자입니다. 오늘 이렇게 시작을 한 이유는 최근 회사에서 했던 과제 중 하나가 앱로그 QA 자동화입니다.
"갑자기 왠 QA?"라고 하신다면...ㅋㅋ 해당 과제가 중요하기도 했고 저희팀이 플랫폼 전반적인 과제들을 하고 있기 때문에 저희팀에서 과제를 가져와서 진행하게 되었습니다.
게다가 단순히 앱 UI 테스트 자동화는 아니고, 앱에서 어떤 액션을 할때마다 정상적으로 로그가 남는지까지 확인하는 End-To-End 테스트라서 백엔드 영역의 핸들링도 필요하기 때문에 저희 쪽에서 진행하게 된 이유도 있습니다.
이런저런 이유로 제가 진행했던 과제에서 App 테스트 자동화를 어떤 식으로 했고 어떤 기술들을 이용했는지 정리 및 소개를 하려고 합니다!
1. 어떤 기술을 사용했나?!
저는 Appium이란 오픈소스 서비스를 사용했습니다~ 특별히 다른 서비스를 찾아보진 않았고 Appium이 가장 많이 쓰이는 것 같아 Appium을 선택했습니다.
Appium은 모바일(iOS, Android, Tizen), 브라우저(Chrome, Firefox, Safari), 데스크톱(macOS, Windows), TV를 포함한 많은 앱 플랫폼의 UI 자동화를 용이하게 하도록 설계된 오픈 소스 프로젝트이자 관련 소프트웨어의 생태계입니다. (Roku, tvOS, Android TV, Samsung)
네 그렇다고 합니다ㅋㅋ Appium을 사용하는 방법은 대략적으로 아래와 같습니다.
- Appium 설치
- Appium 드라이버 및 해당 종속성을 설치. (ios = xcuitest, android =uiautomator2)
- 선택한 언어로 Appium 클라이언트 라이브러리를 설치합니다(JavaScript, Python, Java, Ruby 및 .NET를 지원하는 Appium 라이브러리가 있습니다. 사용하시는 언어에 맞게 설치하시면 됩니다.)
- 샘플 애플리케이션을 사용하여 간단한 Appium 자동화 스크립트 작성 및 실행
이번 포스팅에서는 전체적인 설치에 대한 가이드는 이야기하지 않겠습니다. (Appium 설치 가이드는 여기를 확인해 주세요!)
2. 테스트 디바이스 실행 및 연결
일단 테스트를 실행하기 위해서는 디바이스가 있어야 합니다. 하지만 우리는 모든 디바이스를 가지고 있지 않기 때문에 가상 디바이스를 활용합니다! (다만 여기서 함정이 있습니다. 함정은 잠시 후 공개....)
일단 Android의 경우 Android Studio Emulator를 사용할 수 있습니다. ios도 마찬가지로 Xcode Simulator를 사용할 수 있는데... 여기서 함정이 있습니다. ios Simulator 같은 경우에는 ipa파일이 설치가 안되더라고요... 직접 만든 앱을 Simulator에 빌드(Build)해서 실행시키는 건 됩니다. 그래서 ios 같은 경우에는 부득이하게 실제 Device를 연결해서 테스트를 진행했습니다. (혹시 방법을 아신다면 댓글로...)
참고로 이번 포스팅에서는 Android 기준으로 설명해보려고 합니다.
3. 테스트를 위한 사전 작업
일단 테스트를 진행하려면 테스트할 apk가 있어야 합니다. 아래 블로그에서 sample apk를 제공해 주셔서 요걸 사용해 보겠습니다. 감사합니다!!
테스트할 apk도 생겼으니 이제 테스트 스크립트를 작성해 볼까요?!
그전에 먼저 테스트를 하려면 UI Element들을 제어하기 위해 어떤 값들을 가졌는지 알아야 하는데요. 이걸 가능하게 하는 게 바로 Appium inscpector라는 툴입니다. 릴리즈 파일들은 여기에서 확인할 수 있으니 os 맞게 설치해 주시면 됩니다!
Appium Inspector를 실행하면 이런 창을 확인할 수 있습니다!
Appium Inspector를 통해 앱에 접근하기 위해서는 당연히 Appium Server가 실행되어 있어야 하고 몇 가지 값들을 Capability에 정의해줘야 합니다.
- Android Emulator
{
"platformName": "Android",
"appium:automationName": "uiautomator2", // 안드로이드 전용 드라이버
"appium:deviceName": "emulator-5554", // 안드로이드 에뮬레이터는 이 이름으로 고정
"appium:app": ".../app.apk" // apk 경로
}
- ios Device
{
"platformName": "ios",
"appium:automationName": "XCUITest", // ios driver
"appium:platformVersion": "17.2",
"appium:deviceName": "iPhone12",
"appium:app": "../app.ipa", // 앱 경로
"appium:wdaBaseUrl": "http://xxx.xxx.xxx.xxx:8100", // wda 로컬 네트워크
"appium:xcodeSigningId": "iPhone Developer",
"appium:xcodeOrgId": "", // xcode org id
"appium:udid": "" // device UDID
}
- ios Simulator
{
"platformName": "ios",
"appium:automationName": "XCUITest",
"appium:platformVersion": "17.2",
"appium:udid": "",
"appium:deviceName": "simulator",
"appium:bundleId": "" # 앱 번들 ID
}
저의 경우 위에 서서도 말했지만 Simulator에 ipa 파일 설치하는 게 안 됐어서 Device로 테스트를 진행했습니다. 상황에 맞게 선택해 주시면 될 것 같아요!
참고로 ios의 경우 실 디바이스, Simulator에서 Appium을 사용하려면 WebDriverAgent라는 앱이 필요합니다. WebDriverAgent 설치 관련 내용은 아래 블로그를 참고해 주세요!
Capability에 대한 자세한 내용은 capabilites.md를 참고해 주세요!
Start Session 버튼을 클릭하면 Emulator에 앱이 설치되면서 Appium Inspector에서 앱의 화면을 캡처한 형태로 보이게 됩니다.
위 이미지처럼 UI Element를 클릭하면 속성들을 확인할 수 있고 이 속성값들을 이용해서 앱을 제어할 수 있습니다! 참고로 이 화면은 앱 화면에 따라 자동으로 변경되진 않고 상단의 돋보기 버튼 왼쪽에 있는 새로고침 버튼을 클릭해야지 현재 화면 기준으로 캡처가 됩니다.
자 이제 본격적으로 테스트 스크립트를 작성해 보겠습니다!
4. 테스트 스크립트 작성
Appium에 접근해서 앱을 제어하기 위한 라이브러리들을 Appium에서 제공을 하는데요. 다양한 언어로 된 라이브러리를 제공합니다. 저는 python이 주 언어이이기 때문에 Appium-Python-Client를 사용했습니다! 본인에게 맞는 언어로 사용하시면 될 것 같고 저는 python 기준으로 테스트 코드를 작성해 보겠습니다.
테스트 코드는 깃헙에 업로드해놨으니 참고해 주세요!
python을 사용해 보신 분들이라면 unnittest, pytest에 대해서 한 번쯤 들어 보셨을 텐데요. Appium 테스트도 똑같습니다! 일단은 Appium Driver를 연결을 위한 BaseTest 클래스를 만듭니다.
BaseTest 클래스에서는 Driver를 통해 Appium Server와 session을 맺고 끊는 역할을 제공합니다. 이 클래스를 상속해서 Test Class를 구현하면 됩니다!
테스트 코드를 짤 때 보통 page단위로 Element와 Action들을 정리를 하더라고요! 그래서 이 page들에 공통으로 기능을 제공해 주는 BasePage 클래스를 만들고 이 클래스를 상속해서 테스트할 페이지를 구현해 보겠습니다. 저희는 샘플 앱의 home page를 테스트할 예정입니다.
BasePage에서는 click, get_element, send_keys와 같은 공통 동작들을 구현해 놓았습니다.
HomePage에는 홈화면의 버튼들과 그 버튼들에 대한 액션을 정의했습니다. 각 element들의 속성은 Appium Inspector를 통해서 추출하면 됩니다.
위에서 정의한 BaseTest, BasePage, HomePage 클래스들을 사용해서 테스트 케이스를 작성해 봤습니다. 코드는 특별히 설명이 없어서 보시면 어떤 액션들을 할지 알아보실 거 같아서 따로 설명은 드리지 않고 동작이 어떻게 되는지 영상으로 공유드리겠습니다.
아주 잘 동작하는 걸 볼 수 있습니다! 여기까지가 이제 로컬에서 테스트하는 방법이었고 테스트 자동화라고 하기엔 뭔가 부족하죠?!ㅎㅎ 그래서 좀 더 자동화에 가깝게 Jenkins + DeviceFarm을 연동하는 방법에 대해 간단하게 설명드리겠습니다. (깊게 설명하자면 글이 너무 길어져서 어떤 식으로 연동했는지 정도만 말씀드릴게요)
5. Jenkins + DeviceFarm 연동 테스트 자동화
Jenkins 같은 경우 CI/CD 파이프라인으로 많이들 사용하고 있습니다. 그럼 DeviceFarm은 무엇인가?! 두둔!
AWS DeviceFarm은 테스트 인프라를 프로비저닝하고 관리하지 않아도 다양한 데스크톱 브라우저 및 실제 모바일 디바이스에서 테스트를 진행하여 웹 및 모바일 앱 품질을 향상시키는 애플리케이션 테스트 서비스입니다. 테스트를 통해 여러 데스크톱 브라우저나 실제 디바이스에서 동시에 테스트를 실행함으로써 테스트 도구 실행 속도를 높이고 비디오 및 로그를 생성하여 앱과 관련된 문제를 빠르게 식별할 수 있습니다.
말 그대로 저희가 테스트를 위해 여러 디바이스를 구비하지 않아도 AWS를 통해서 테스트할 수 있는 디바이스들을 빌려서 사용한다고 생각하시면 됩니다. 디바이스를 대여하는 것, 사용한 만큼 지불하는 것 등 여러 옵션이 있습니다. 기본적으로 1000분의 Free Trial을 제공해 주기 때문에 테스트하시는데 큰 어려움은 없으실 겁니다! (요금정책)
그리고 Jenkins에는 DeviceFarm과 연동할 수 있는 플러그인(Plugin)을 제공하기 때문에 쉽게 연동할 수 있습니다. 처음에는 요걸 몰라서 직접 DeviceFarm API를 호출해서 파이썬 스크립트로 자동화를 구현하다가 뒤늦게 해당 플러그인을 발견했네요 ㅋㅋㅋ 그래도 boto3로 DeviceFarm API호출하는 것도 나름 재밌습니다. (jenkins-aws-device-farm plugin)
AWS 공식문서에 가보시면 jenkins와 연동하는 방법에 대해 나와있으니 구현하실 때 참고 하시면 될 것 같습니다. 저 같은 경우 Jenkins를 도커로 설치한 뒤 진행했습니다.
최종적으로 제가 구현한 형태는 위 이미지처럼 동작합니다. 필요에 따라서 apk 빌드부터 업로드하는 부분까지 자동화할 수 있을 것 같습니다. 위 내용도 자세하게 설명하면 좋겠지만 이번 포스팅에서는 다루지 않고 따로 글을 쓰도록 하겠습니다🙏🏻
6. 정리
Appium을 사용해서 앱 테스트 자동화 코드를 만들고 Jenkins + DeviceFarm 연동까지 정리해 봤습니다. 마지막에 Jenkins + DeviceFarm 연동에 대해 자세히 다루지 못해서 아쉽지만... 이런 식으로 테스트 자동화를 해봤다 정도로 참고해 주시면 좋을 것 같습니다.
개인적으로 회사에서 이번 과제를 진행하면서 몇 가지 느낀 점이 있습니다.
1. 내 업무와 직접적인 관계는 아니지만 간접적인 업무였을 때 내가 할 수 있는 일이 있다면 적극적으로 해보기
2. 잠시 QA 엔지니어의 삶을 느껴봤는데 생각보다 재밌었고 어쨌든 개발과 관련된 부분이다 보니 커리어에 도움이 될 것 같다
3. 앱테스트 자동화다 보니 혼자 하는데 한계가 있다. (못하는 건 아님)
예를 들어 시나리오 작성을 하려면 UI Element를 찾아야 하는데 고유의 ID가 없거나 움직이는 배너이라던가 (속도가 빠르면 클릭 잘 못 할 수 있음) 하는 일들 때문에 앱개발자들도 함께 자동화 환경을 만들어 가야 한다.
4. 앱이 어떻게 빌드되고 설치되는지에 대한 이해도가 없어서 초반에 삽질 많이 했다.
특히 ios는 지랄맞게 추가적인 작업들 (WebDriverAgent 설치 등)과 개발자 등록이 안되면 일주일에 열 번 빌드인가? 암튼 제한이 있어서 삽질하다가 빌드를 못해서 Apple 계정을 새로 만들기도 했다.
5. 잘 만들면 QA 하기 편할 것 같다. (하지만 그 과정이 빡셀 것 같긴 하다 ㅋㅋ)
암튼 재밌었던 과제였고 아직 마무리된 건 아니지만, 마무리가 되고 잘 사용이 되면 기분이 좋을 것 같습니다. (poc까지 끝낸 상황)
긴 글 읽어주셔서 감사드리며 오늘도 좋은 하루 보내시길 바랍니다!