작년부터 회사에서 제품의 뼈대부터 다시 설계하는 재개발 작업이 활발하게(?) 이루어지고 있다.

덕분에 자연스럽게 UI 자동화 테스트 프로젝트는 중단됐고,

그래도 덕분에 (물론 기존 제품을 리뉴얼한 거지만, 거의 새로운 앱이라고 할 수 있는) 신규 앱 QA를 주도해보는 경험을 얻었다.

APPIUM을 사용하지 않은지도 어느덧 1년이 다 되어가는 중이다.

 

그리고 잠시 다음 QA가 착수 되기 전까지 여유가 생긴 요즘, 다시 테스트 자동화로 눈독을 들이고 있다.

그 사이 APPIUM은 v2.0 Major Update와 함께 v1.x 지원을 중단했고,

내가 익숙하게 사용하던 Desktop APP은 v2.0 릴리즈와 함께 지원을 중단했다.

APPIUM Github ReadME

그래서 이왕 다시 APPIUM을 공부하는 마음으로 설치부터 다시해보기로.


Node.js & npm 설치하기

APPIUM은 Node.js 기반으로 동작하기 때문에 Node.js를 먼저 설치해야 한다.

 

방법 1. Node.js 공식 홈페이지에서 패키지 파일을 다운로드하고, 설치한다.

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

Node.js 설치하기

방법 2. brew 명령어로 설치한다.

brew install node

다음은 APPIUM을 다운로드하기 위한 npm을 설치한다.

  • npm 설치하니까 node도 함께 설치되는 듯 ?
brew install npm

 

APPIUM 설치

이제 진짜 목적인 APPIUM을 설치한다.

npm install -g appium@next
  • 여기서 주의해야 할 점은 appium@next 를 appium 으로 입력하면 v1.22.3 버전이 설치된다. (...)
  • 그럼 얌전히 다시 uninstall 해주면 된다.
npm uninstall -g appium

설치가 완료되면 제대로 된 버전을 설치했는지 확인한다.

appium -v

v2.x.x로 나오면 성공

APPIUM 서버 실행 
appium

아무 옵션없이 실행하면 디폴트값으로 실행된다.

  • HOST: http://0.0.0.0
  • PORT: 4723

매우 간단

 

'Test Automation > APPIUM' 카테고리의 다른 글

APPIUM 스크롤  (0) 2022.01.11
APPIUM logcat 가져오기 : get_log 활용법  (0) 2020.12.08
APPIUM TimeoutException 예외처리  (0) 2020.12.08
APPIUM Desired Capabilities 설정 방법  (0) 2020.12.06
APPIUM Selenium with Python  (0) 2020.12.06
from appium.webdriver.common.touch_action import TouchAction	

actions = TouchAction(self.driver)
actions.press(x=500, y=1809).wait(200) #wait 필수
actions.move_to(x=500, y=567)
actions.release()
actions.perform()

 
UI 테스트를 진행하다 보면 Timeout Exception 오류로 테스트가 중단되는 경우가 많은데,
APPIUM Log만으로는 단순하게 UI 오류인지, 심각한 Crash 오류인지 식별하기가 어렵다.

개발자에게 전송할 로그를 포착하기 위해 로그캣창을 보고 있다가 로그 추출의 자동화가 굉장히 시급하다는 생각이 들었다.
역시 사람은 눈 앞에 고생이 닥쳐오면, 뇌가 활성화되는 것 같다.


get_log 매소드

 

똑똑한 우리의 APPIUM은 로그를 불러오는 get_log 매소드를 지원한다.

 

하지만, 역시 아예 떠먹여주지는 않는 APPIUM은 나를 또 공부시킨다.

 

get_log 매소드는 log type 파라미터를 요구한다.

이 log type은 플랫폼마다 제공되는 로그가 다르기 때문에 아주 다양한 값들이 들어갈 수 있다.

 

그 중에서 내가 필요한 부분은 logcat이기 때문에 다음과 같이 적어준다.

logs = driver.get_log('logcat') # Only Android platform

 

'여기서 print(logs)를 하면 logcat이 출력되겠지?'

친절하게 공부를 요구하는 APPIUM인데, 당연히 안된다.

 

리스트를 문자열로 변환

get_log는 리스트 형식의 output을 내는데,
이를 가독성 좋은 문자열 형태로 변환하기 위해선 다음과 같은 변환이 필요하다.

logs = driver.get_log('logcat')
logs_message = '\n'.join(list(map(lambda log: log['message'], logs)))

# Tip ! 로그 파일로 저장하기
file = open(filepath + filename + '.log', 'w')
file.write(logs_message)

 

그렇다면,

 

Q. 내가 원하던 Crash 로그가 발생 했을 때 로그를 추출하려면 어떻게 해야 될까 ?

A. 리스트 형식인 로그를 차례로 대입하여 Crash 로그가 있는지 확인한다.

logs = driver.get_log('logcat')
logs_message = list(map(lambda log: log['message'], logs))

for message in logs_message:
    if 'Crash' in message:
        break

file = open(filepath + filename + '.log', 'w')
file.write('/n'.join(logs_message))

 

그리하여, 테스트를 열심히 하다가 Crash Log가 나면

똑똑하게 해당 세션의 로그 파일을 저장해주는 자동화 프로그램 구축에 성공했다.

 

'Test Automation > APPIUM' 카테고리의 다른 글

APPIUM 설치부터 실행까지  (0) 2023.05.12
APPIUM 스크롤  (0) 2022.01.11
APPIUM TimeoutException 예외처리  (0) 2020.12.08
APPIUM Desired Capabilities 설정 방법  (0) 2020.12.06
APPIUM Selenium with Python  (0) 2020.12.06

 

UI 기반의 테스트를 진행하다보면 예상치 못한 부분에서 Timeout Exception 에러로 허무하게 테스트가 중단될 때가 있다.
Timeout Exception은 이름에서 유추할 수 있듯이 설정한 대기시간이 넘도록 조건을 만족하지 못해 더이상 테스트를 진행할 수 없을 때 나타나는 오류다.

예를 들면 다음과 같은 소스코드가 있을 때,

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

# Driver의 기본 대기 시간은 20초
wait = WebDriverWait(driver, 20)

# btn_login이 클릭가능할 때까지 대기 (최대 20초)
login = wait.until(EC.element_to_bo_clickable((By.ID, 'com.sample.package:id/btn_login'))
login.click()

 

임의의 오류로 20초가 지나도록 로그인 버튼이 클릭 가능한 상태가 되지 않으면 Timeout Exception 오류가 나고,

이후 스크립트는 실행되지 않고, 테스트는 자동 종료된다.

이를 방지하기 위해 필요한 것이 Timeout Exception 예외 처리다.

즉, Timeout이 생기더라도 스크립트를 중단하지 않고 그대로 다음 스크립트를 진행하기 위한 예외 처리이다.

 

try:
       # Timeout 오류가 날 수 있는 스크립트

except TimeoutException:
       # Timeout 오류가 난 경우 실행 될 스크립트

 

소프트웨어 테스트를 할 때 작성된 테스트 케이스에 맞춰 기능을 테스트하는 경우도 있지만,
정해진 패턴없이 무작위로 랜덤 데이터 입력으로 진행되는 테스트도 필요하다.

이러한 테스트를 일컫는 용어인 Fuzz Test

 

구글링을 해보면 주로 보안과 관련된 글이 많은 걸로 보아,
주로 보안 취약점을 발견하는 데 사용하는 테스트 기법인 것 같다.

 


 

Fuzz Test : AWS Devicefarm Built-in Fuzz Test

AWS Devicefarm에서 기본적으로 제공하는 Fuzz Test
랜덤 데이터 입력으로 소프트웨어/하드웨어의 취약점을 확인하는 테스트를 의미한다.

실제로 AWS Devicefarm에서 Built in Fuzz-Test 스크린 레코드를 보면 정신없이 화면이 움직이는 모습을 볼 수 있다.

 

 

AWS Devicefarm 이용 방법은 공식 홈페이지에 친절하게 나와있어서 생략한다.

 

Device Farm용 기본 제공 퍼지 테스트를 이용한 작업 - AWS Device Farm

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

이 테스트를 오프라인 단말에서 할 수 있는 방법이 없을까 찾던 중 알게 된

 

Monkey Test

Android adb에서 제공하는 Monkey Test tool

역시 친절한 안드로이드 문서에 설명이 너무 잘 되어 있다.

 

UI/Application Exerciser Monkey  |  Android 개발자  |  Android Developers

Monkey는 에뮬레이터나 기기에서 실행되는 프로그램으로 여러 시스템 레벨 이벤트뿐만 아니라 클릭, 터치, 동작과 같은 사용자 이벤트의 의사 랜덤 스트림을 생성합니다.

developer.android.com

아무것도 모르는 원숭이가 이것저것 막 눌러보듯이 테스트를 한다고 해서 Monkey Test다.

에뮬레이터와 실제 기기 모두 사용 가능하며, adb 기본 사용 설정이 되어 있어야 한다. ※ 아래 글 참고 ※

 

Android adb 환경변수 설정 (Feat. 연결된 기기 확인)

테스트 자동화 프로그램을 구축하면서 많이 쓰는 adb 명령어 ! adb 명령어를 사용하려면 환경변수 설정을 해줘야 한다. 사전준비 1. Android Studio SDK 설치 Download Android Studio and SDK tools  | Android..

summer-west.tistory.com

Monkey 를 사용하는 기본 구문은 다음과 같고, option을 설정해 나름 세세하게 랜덤 동작을 조절할 수 있다.

 

adb shell monkey [options] <event-count>

옵션에 대한 설명도 공식 홈페이지에 아주 잘 나와있지만, 주요 옵션에 대해서 참고사항을 적자면

 

동영상은 옵션이 -v 500 -s 500 이라 굉장히 빠르고 짧은 테스트지만
옵션값을 적절히 조절하면 Devicefarm 의 Fuzz Test와 유사한 테스트를 할 수 있다.

(비행기모드 / Wifi 설정 등도 드래그, 터치 랜덤 동작 중 나타나는 동작)

 

카카오엔터프라이즈 인턴을 하면서 QA 분야로, 정확하게는 자동화 엔지니어로 방향성을 잡았다.

다양한 방식으로 테스트 자동화 프로그래밍을 공부하고 있는데,

특히 AWS Devicefarm 과 APPIUM을 연동하면서 다양한 방식으로 APPIUM을 다뤄보고 있다.

그동안 아장아장 예제를 따라하며 시작했던 테스트 스크립트를 이제는 직접 필요한 부분만 작성 할 수 있게 됐다.

그 중에서 APPIUM 스크립트에서 가장 기본 설정이 되는 Desired Capabilities

스크립트 작성 방식, JSON 파일 방식, CLI 방식 중 상황에 맞춰 활용하면 꽤나 똑똑하게 테스트를 진행할 수 있다.

그래서 정리해보는 Desired Capabilities 설정 방법


 

Desired Capabilities

쉽게 말하면 테스트 환경 설정을 위한 속성값을 정의한다.

APPIUM 서버에서 Client를 연동할 때, 정의된 Desired Capabilities 값을 참조하여 테스트를 진행한다.

Desired Capabilities 작성 방식은 스크립트 작성 / JSON 이용 / CLI 방식 총 세가지 방식이 있다.

 

첫번째. 스크립트 작성 방식

제일 먼저 소개할 방식은 테스트 스크립트 작성 시 Desired Capabilities 속성을 정의하는 방식으로,

스크립트 언어에 따른 예시도 APPIUM 공식 홈페이지에 나와있어 가장 쉽게 접근할 수 있는 방식이다. (내 기준에서)

스크립트 최상단에 Desired Capabilities 속성을 먼저 정의하고, 해당 값으로 Driver를 시작한다.

아래 소개할 두 방식과 달리 유일하게 스크립트 내부에서 정의된 속성값을 호출할 수 있다는 장점이 있다.

출처 : Appium Officail Site (http://appium.io/docs/en/commands/session/create/) ​

위 속성값은 예시로 작성 된 속성일 뿐, 속성 목록을 보고 테스트 환경에 따라 필요한 속성을 추가/제거하여 작성하면 된다.

속성 목록은 APPIUM 공식 홈페이지에 어떤 역할인지, 예시 구문까지 아주 친절하게 나와있다.

 

Desired Capabilities - Appium

From here you can search these documents. Enter your search terms below.

appium.io

경험상 Android 테스트의 경우 기본적으로 platformName / platformVersion / appPackage / appActivity 가 필요하다.

(여러 단말이 연결된 경우 UDID까지)

※ apk 파일에서 패키지와 액티비티 정보를 추출하는 방법은 아래 글 참고

 

Android apk 파일에서 매니패스트 정보 추출 (패키지명, 권한 등)

apk 파일만 덩그러니 놓여있을 때, apk 파일의 매니패스트 정보를 추출할 수 있는 방법 ​ AndroidStudio 에서 제공하는 AAPT2 를 이용하는 방법으로 주로 패키지명, Activity 구조, 권한 정보 등을 추출할

summer-west.tistory.com

 

두번째. JSON 이용 방식

다음은 JSON 파일을 이용하는 방식으로, 스크립트 언어가 익숙치 않은 사람들에게 유용한 방식이라고 생각 된다.

APPIUM 서버를 실행할 때 --default-capabilities flag 옵션으로 Desired Capabilities를 정의할 수 있는데,

Desired Capabilities 속성이 정의된 JSON 파일명 입력만으로 손쉽게 정의할 수 있다.

다만 단점은 이 때 설정한 값은 처음 세션이 시작할 때만 적용되고, 이후 스크립트 내부에서는 해당 속성값을 사용할 수 없다는 것이다.

이 때 사용할 JSON 형식은 Object xpath, id 값을 찾는 Inspector Sesstion 자연스럽게 생성할 수 있다.

 

이렇게 생성된 JSON은 명령어에 직접 이용 혹은 JSON 파일로 저장하여 이용할 수 있다.

# 명령어에 직접 이용
APPIUM --default-capabilities '{"app": "myapp.app", "deviceName": "iPhone Simulator"}'

# Windows CMD 사용 시 \ 필수
APPIUM --default-capabilities "{\"app\": \"myapp.app\"}"

# JSON 파일 저장 후 이용
APPIUM --default-capabilities /path/to/file.json

 

세번째. CLI 방식

마지막은 CLI 속성을 이용하는 방식인데,
--app, --platform-version 등 속성값을 입력하면 자동으로 JSON 형식으로 변환해 Desired Capabilities를 정의하는 방식이다.
즉, JSON 이용 방식과 마찬가지로 스크립트 내부에서는 해당 속성값을 사용할 수 없다는 단점이 있다.

CLI 속성에는 Desired Capabilities 속성값 외 포트번호라든가, log 출력 형식 등 APPIUM 서버 동작을 위한 유용한 속성들도 많아서
참고해서 활용하면 훨씬 편리하게 테스트 자동화를 진행 할 수 있다.

 

CLI Arguments - Appium

From here you can search these documents. Enter your search terms below.

appium.io

 

 

Selenium을 기반으로 하는 APPIUM을 Python Client로 작성 중이라면 굉장히 유용한 사이트

 

 

Selenium with Python — Selenium Python Bindings 2 documentation

Note This is not an official documentation. If you would like to contribute to this documentation, you can fork this project in GitHub and send pull requests. You can also send your feedback to my email: baiju.m.mail AT gmail DOT com. So far 50+ community

selenium-python.readthedocs.io

 

Appium 을 이용한 테스트자동화 프로그램 구축 시
기본적으로 appium 에서는 테스트를 진행할 때마다 새롭게 앱 설치를 진행한다.

(정확히 말하면 Session이 새로 시작될 때마다)
그런데 테스트 사전 세팅이 필요한 경우 매번 앱이 초기화 상태가 되면서 진행이 굉장히 번거로워진다.

 

해결 방안은 Desired Capabilities 설정 차이 !

 


새로 apk 설치 후 테스트 진행

Desired Capabilities에 app 속성에 테스트 apk 를 설정한다.

# 테스트 apk 경로 지정
app = os.path.join(os.path.dirname(__file__), 'C://apk 디렉토리', '파일명.apk')
app = os.path.abspath(app)

desired_caps = {
  'platformName': 'Android',
  'platformVersion': '10',
  'deviceName': 'VELVET',
  'automationName': 'Appium',
  'app': app,
  'appPackage': 'com.application.test',
  'appActivity': 'com.application.test.Activity'
}
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

 

이미 설치되어 있는 앱으로 테스트 진행

Desired Capabilities에 app 속성 제거 / noReset = True , fullReset = False 속성값 추가

desired_caps = {
  'platformName': 'Android',
  'platformVersion': '10',
  'deviceName': 'VELVET',
  'automationName': 'Appium',
  'appPackage': 'com.application.test',
  'appActivity': 'com.application.test.Activity',
  'noReset': True,
  'fullReset': False
}
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

'Test Automation > APPIUM' 카테고리의 다른 글

APPIUM 스크롤  (0) 2022.01.11
APPIUM logcat 가져오기 : get_log 활용법  (0) 2020.12.08
APPIUM TimeoutException 예외처리  (0) 2020.12.08
APPIUM Desired Capabilities 설정 방법  (0) 2020.12.06
APPIUM Selenium with Python  (0) 2020.12.06

+ Recent posts