from selenium import webdriver
from selenium.common.exceptions import (
InvalidArgumentException,
SessionNotCreatedException,
UnknownMethodException,
WebDriverException,
)
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.command import Command as RemoteCommand
from selenium.webdriver.remote.remote_connection import RemoteConnection
from appium.common.logger import logger
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
def find_element(self, by: str = AppiumBy.ID, value: Union[str, Dict, None] = None) -> MobileWebElement:
from .webelement import WebElement as MobileWebElement
Web
네이버 경제 뉴스 탭 눌러보고, 애플 검색도 해보자 (test_selenium.py)
터미널로 크롬 개발자 도구 켜서 차근차근 해보자
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
# 네이버 열기
driver.get("https://www.naver.com/")
time.sleep(3)
# "경제" 찾아보기
el = driver.find_element(By.LINK_TEXT, "경제")
# "경제" 속성 살펴보기
el.get_attribute("class")
# "경제" 클릭
el.click()
time.sleep(3)
# 애플 검색하기
el = driver.find_element(By.CLASS_NAME, "search_input")
el.send_keys("AAPL")
el.send_keys(Keys.ENTER)
time.sleep(3)
App
“TestFlutter” 앱에서 Todo list 터치 후 스크롤해보자 (test_appium.py)
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
from appium.options.android import UiAutomator2Options
# 테스트 앱 열기
capabilities = UiAutomator2Options().load_capabilities({
"platformName": "Android",
"appium:deviceName": "aos_galaxy_note_10_plus",
"appium:udid": "R3CMA0F73PL",
"appium:automationName": "UiAutomator2",
"appium:appPackage": "com.example.test_flutter",
"appium:appActivity": ".MainActivity",
"appium:autoGrantPermissions": "true",
"appium:noReset": "true",
"appium:newCommandTimeout": "3000"
})
driver = webdriver.Remote(command_executor="http://localhost:4723", options=capabilities)
time.sleep(3)
# "Todo list" 클릭
el = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="Todo list")
el.click()
time.sleep(2)
# 스크롤
driver.swipe(700, 800, 0, 0, 1000)
driver.swipe(200, 500, 900, 1800, 1000)
time.sleep(3)
테스트 전에 “TestFlutter” 앱 테스트 스크립트 잠깐 살펴보자 (test_todo_list_for_pt.py)
Appium inspector 사용해서 “TestFlutter” 앱 테스트 녹화해보자 (test_todo_list_for_pt.py)
POM?
POM 적용해보자 (test_todo_list_for_pt.py)
class TodoListTest(BaseTest):
def test_todo_list(self) -> None:
main_page = MainPage(self.driver)
main_page.click_todo_list()
todo_list_page = TodoListPage(self.driver)
time.sleep(2)
todo_list_page.scroll_down()
todo_list_page.scroll_up()
todo_list_page.send_keys_filter_text()
todo_list_page.check_todo_item()
todo_list_page.click_todo_item()
time.sleep(0.5)
반복되는 코드 줄이기
init, setUp, tearDown → BaseTest
class BaseTest(unittest.TestCase):
def __init__(self, methodName='runTest', device=None):
print(f"__init__")
super().__init__(methodName)
self.device = device
def setUp(self) -> None:
# 디바이스 셋팅
if self.device:
config.device = self.device
# 드라이버 셋팅
appium_server_url = f"{config.appium_server_host}:{util.get_port()}"
capabilities_options = util.get_capabilities_options()
print(f"setUp / device : {config.device} / appium_server_url : {appium_server_url}")
self.driver = webdriver.Remote(command_executor=appium_server_url, options=capabilities_options)
def tearDown(self) -> None:
print("tearDown")
if self.driver:
print("tearDown / quit")
# noReset true 하면 테스트 끝나도 앱 종료안되서 강제 종료
self.driver.terminate_app(util.get_app_package())
self.driver.quit()
class Temp01Test(BaseTest):
def test_temp_01(self) -> None:
time.sleep(0.5)
def test_error(self):
raise ValueError("에러 테스트 :)")
@unittest.skip("스킵 테스트 :)")
def test_skip(self):
pass
def test_fail(self):
self.assertEqual(1, 2)
class TodoListTest(BaseTest):
def test_todo_list(self) -> None:
main_page = MainPage(self.driver)
main_page.click_todo_list()
todo_list_page = TodoListPage(self.driver)
time.sleep(2)
todo_list_page.scroll_down()
todo_list_page.scroll_up()
todo_list_page.send_keys_filter_text()
todo_list_page.check_todo_item()
todo_list_page.click_todo_item()
time.sleep(0.5)
테스트 코드 최초 실행되는 로직 (if name == 'main' 부분)
# 스크립트 파라미터 파싱
def get_args(argv) -> argparse.Namespace:
# help
parser = argparse.ArgumentParser(description="Test Appium", add_help=True) # python3 test.py -h
# 파싱
devices = " / ".join(config.capabilities.keys())
parser.add_argument("--device", "-d", dest="device", help=f"Available devices >>>>>>> {devices}")
# 1번째는 스크립트 이름. 실제 파라미터는 2번째부터
args = parser.parse_args(argv[1:])
return args
# 테스트 슈트 로드
def load_tests(args: argparse.Namespace, test_class) -> unittest.TestSuite:
# 파라미터 전달
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
for test_case in suite:
test_case.device = args.device
return suite
args = util.get_args(sys.argv)
suite = util.load_tests(args, TodoListTest)
suite2 = util.load_tests(args, Temp01Test)
suites = unittest.TestSuite([suite, suite2])
pip3 install html-testRunner
# 테스트 실행 및 report 생성
HtmlTestRunner.HTMLTestRunner(
output = "reports", # report 넣을 폴더명
report_name = f"report_{args.device}", # report html 파일명
report_title = "Test Results", # report 제목
combine_reports = True # report 합치기
).run(suites)
capabilities MyData 셋팅 필요
// SmartM MyData
"appium:appPackage": "kr.co.koreastock.mts.android",
"appium:appActivity": ".mydata.MyDataActivity",
// SmartM Intro
"appium:appPackage": "kr.co.koreastock.mts.android",
"appium:appActivity": ".AppIntro",
// STEPS Intro
"appium:appPackage": "plus.steps.sapp.dev",
"appium:appActivity": "plus.steps.sapp.intro.IntroActivity",
// STEPS Apk
"appium:app": "/Users/kwon0koang/Downloads/steps.apk",
Jenkins 연동
ELK 연동
Telegram 혹은 Slack 연동
adb shell dumpsys window windows | grep "popupcalculator”
adb uninstall io.appium.uiautomator2.server.test
npm install -g appium
appium driver install uiautomator2
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
appium driver list --installed
--log-timestamp
: Show timestamps in console output--log
: Also send log output to this fileappium --base-path /wd/hub --port 4723
pip3 install selenium
pip3 install appium-python-client
self.driver.update_settings({"waitForIdleTimeout": 0})
# 수정 전
if exctype is test.failureException:
# Skip assert*() traceback levels
length = self._count_relevant_tb_levels(tb)
msg_lines = traceback.format_exception(exctype, value, tb, length)
else:
msg_lines = traceback.format_exception(exctype, value, tb)
# 수정 후
msg_lines = traceback.format_exception(exctype, value, tb)
Appium Documentation - Appium Documentation
Chapter 4.8 - Run First Test on iOS Real Device
Parallel execution in Appium 1.7
Docker 기반의 Elasticsearch 설치 및 실행
ELK Stack Tutorial: What is Kibana, Logstash & Elasticsearch?
[ELK] ELK(Elasticsearch, Logstash, Kibana)에 대한 간단한 소개 및 구성 예시