Appium 의 코드 인 스 턴 스 및 로그 분석

본문 내용:
  • Android 및 IOS 는 TestNG 를 기반 으로 한 코드 구조 예시
  • 자주 사용 하 는 요소 포 지 셔 닝 방식 에 대한 소개
  • 일부 항목 에서 사용 하 는 기능 코드 예시
  • Appium 로그 의 구체 적 인 분석
  • 부분 이해 해 야 할 개념
  • Android 예제 코드 (TestNG):
    public class AndroidTest {
        protected AndroidDriver driver;
        URL url = new URL("http://127.0.0.1:4723/wd/hub");
        
        @BeforeSuite
        public void setUp() throws Exception {
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "AndroidPhone");
            capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.example.dev");
            capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".MainActivity");
            capabilities.setCapability(MobileCapabilityType.NO_RESET, true);
            ......
            driver = new AndroidDriver<>(url, capabilities);
        }
        
        @AfterSuite
        public void tearDown() throws Exception {
            if (driver != null) {
                driver.quit();
            }
        }
        
        @Test
        public void test_001(){}//Test Case One
        @Test
        public void test_002(){}//Test Case Two
    }

    IOS 예제 코드 (TestNG):
    public abstract class IOSTest {
        protected IOSDriver driver;
        URL url = new URL("http://127.0.0.1:4723/wd/hub");
        
        @BeforeSuite
        public void setUp() throws Exception {
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "10.3");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "My iPhone 6");
            capabilities.setCapability(MobileCapabilityType.UDID, "c4ef2cbc8a1b39123838a8ad9fdea45547e44c20");
            capabilities.setCapability(IOSMobileCapabilityType.BUNDLE_ID, "com.example.dev");
            ......
            driver = new IOSDriver<>(url, capabilities);
        }
    }

    자주 사용 하 는 요소 포 지 셔 닝 방식:
    Android:
    By.id
    View id
    com.hello.uat:id/et_reg_mobileandroid:id/button1button1
    By.classname
    View 의 형식 명
    android.widget.TextViewandroid.widget.Button
    By.xpath
    element 의 속성 및 DOM 등급 에 따라 찾기 가 불안정 합 니 다.
    By. xpath (". / / * [@ text = 'title']") 는 text 속성 에 따라 찾 습 니 다. 일반적으로 색인 이 불확실 한 요 소 를 사용 합 니 다.
    MobileBy.AndroidUIAutomator
    Android 자체 UIAutomator 프레임 워 크 의 포 지 셔 닝 방식
    IOS:
    MobileBy.AccessibilityId
    구성 요소 의 AccessibilityId, 가장 좋 은
    일반적으로 같은 구성 요소 의 name 속성, Inspector 를 사용 하여 획득
    By.classname
    구성 요소 의 형식 이름
    XCUIElementTypeStaticTextXCUIElementTypeButton
    By.xpath
    element 의 속성 과 DOM 등급 에 따라 검색 하면 비교적 불안정 합 니 다.
    By. xpath (". / * [@ name = 'title']") 는 name 속성 에 따라 찾 을 수 있 으 며, 일반적으로 AccessibilityId 로 대체 할 수 있 습 니 다. name 과 AccessibilityId 는 일반적으로 같 고 정확 하기 때문에 classname: / / XCuielement TypeStaticText [@ name = "Hello"] 는 색인 이 정확 하지 않 고 AccessibilityId 가 없 는 요 소 를 사용 합 니 다.
    MobileBy.IosUIAutomation
    IOS 자체 프레임 워 크 UIAutomation 의 포 지 셔 닝 방식
    AccessibilityId
    appium 은 Selenium 에서 자주 사용 하 는 name 과 tagname 포 지 셔 닝 방식 을 제거 합 니 다.
    IOS 에 Accessibility Identifier 를 표시 합 니 다. 보통 Name, Label 속성 과 같 습 니 다.
    Android 에 content description 표시
    대화 식 조작
    MobileElement: 상호작용 대상, Android 의 View 대상 에 대응
    클릭: element. click ();
    입력: element. sendKeys ("text");
    미끄럼: driver. swipe ()
    클릭: driver. tap ();
    대기 모드:
    / / 암시 적 대기
    / / 전역 에서 요 소 를 찾 을 때 대기 시간 을 설정 합 니 다. 10 초 동안 검색 을 시도 할 것 을 찾 을 수 없습니다. 계속 찾 을 것 을 찾 았 습 니 다.
    / / 여기 서 설정 한 값 은 driver 의 전체 수명 주기 에 작용 합 니 다. 지금부터 다음 수정 까지 매번 찾 을 때마다 10 초 입 니 다.
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    / / 명시 적 대기
    / / 이번 만 최대 5 초 대기, 종료 조건 은 원소 찾기 id = btnext。시간 초과 로 TimeoutException 을 던지다.
    WebElement e = new WebDriverWait(driver, 5).until(
    ExpectedConditions.presenceOfElementLocated(By.id("bt_next")));
    / / 기다 림 을 강행 하 다
    / / 스 레 드 가 직접 중단 되 어 단순 한 기다 림 에 적합 합 니 다.원소 찾기
    Thread.sleep(3000)
    DesiredCapabilities
    이것 은 키 - value 의 집합 으로 서버 에 연 결 된 장치 정 보 를 알려 주 는 데 사용 되 며 플랫폼 에 따라 다 릅 니 다.appium 은 많은 속성 설정 을 지원 하여 홈 페이지 에 가서 전면적 인 이 해 를 할 수 있 습 니 다.
    MobileCapability Type: 서로 다른 플랫폼 공용
    Android Mobile Capability Type: Android 전용
    IOSMobileCapability Type: IOS 전용
    Android 는 일반적으로 적어도:
    1、platformName
    2、platformVersion
    3、deviceName
    4、appPackage
    5、appActivity
    IOS 는 일반적으로 적어도:
    1、platformName
    2、platformVersion
    3、deviceName
    4、udid
    5、bundleId
    부분 코드 예시
    //          ,    Allow       Allow。
    protected void grantPermissionIfPrompt() {
        int count = 0;//at most five times grant
        MobileElement allowBtn = findElement(By.id(ConstConfig.ALLOW_BUTTON));
        while (allowBtn != null && count++  
      


    //      ,        
    static public MobileElement scrollDownUnitFound(AndroidDriver driver, String content) throws Exception {
        int width = driver.manage().window().getSize().getWidth();
        int height = driver.manage().window().getSize().getHeight();
        int count = 0;
        String xpathStr = createXpathDesc(content);
        do {
            if (driver.findElementsByXPath(xpathStr).size() > 0) {
                //in case of the element is still hiding, or the element is showing only a little part of it.
                driver.swipe(width / 2, height / 2, width / 2, height / 3, 600);
                Thread.sleep(1000);//sleep 1 second to avoid getting the element in the wrong position.
                return driver.findElementsByXPath(xpathStr).get(0);
            }
            driver.swipe(width / 2, height / 2, width / 2, height / 4, 600);
            count++;
        } while (count  
      


    //  xpath   
    static public String createXpathDesc(String content) {
        return ".//*[@text='" + content + "']";
    }
    //      ,       CheckBox。CheckBox  id,     classname,         ,            。
    MobileElement el = AndroidHelper.scrollDownUnitFound(driver, voteTarget);
    if (el != null) {//find the checkbox to the left of the founded target.
        int targetX = el.getLocation().getX() - 20;
        int targetY = el.getLocation().getY() + 1;//event +0 is working
        System.out.println("coordinates:x = " + targetX + "    y = " + targetY);
        driver.tap(1, targetX, targetY, 300);
    }

    로그 분석 (AWS 장치 팜 의 Appium):
    Appium 은 Client / server 구조 이기 때문에 모든 작업 은 Client 가 Server 에 http 요청 을 보 내 는 것 으로 시작 하여 Server 가 Client 에 http 응답 을 보 내 는 것 으로 끝 납 니 다.로 그 를 찾 아 보면 이 규칙 에 따라 불필요 한 정 보 를 걸 러 낼 수 있다.
    Android 로그 분석:
    driver.findElement(By.id("compose_button")).click();
    (Adnroid) findElement 작업 로그:
    2017-09-19 04:06:27:278 - [HTTP] --> POST /wd/hub/session/acfa31ae-321f-4ee1-a34b-294667393f8f/element {"using":"id","value":"compose_button"}
    2017-09-19 04:06:27:278 - [debug] [MJSONWP] Calling AppiumDriver.findElement() with args: ["id","compose_button","acfa31ae-321f-4ee1-a34b-294667393f8f"]
    2017-09-19 04:06:27:279 - [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
    2017-09-19 04:06:27:279 - [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
    2017-09-19 04:06:27:279 - [debug] [BaseDriver] Waiting up to 3000 ms for condition
    2017-09-19 04:06:27:280 - [debug] [AndroidBootstrap] Sending command to android: {"cmd":"action","action":"find","params":{"strategy":"id","selector":"compose_button","context":"","multiple":false}}
    2017-09-19 04:06:27:310 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"action","action":"find","params":{"strategy":"id","selector":"compose_button","context":"","multiple":false}}
    2017-09-19 04:06:27:310 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type ACTION
    2017-09-19 04:06:27:310 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command action: find
    2017-09-19 04:06:27:311 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Finding 'compose_button' using 'ID' with the contextId: '' multiple: false
    2017-09-19 04:06:27:311 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Using: UiSelector[INSTANCE=0, RESOURCE_ID=com.example.hello:id/compose_button]
    2017-09-19 04:06:27:329 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Returning result: {"status":0,"value":{"ELEMENT":"9"}}
    2017-09-19 04:06:27:330 - [debug] [AndroidBootstrap] Received command result from bootstrap
    2017-09-19 04:06:27:330 - [debug] [MJSONWP] Responding to client with driver.findElement() result: {"ELEMENT":"9"}
    2017-09-19 04:06:27:344 - [HTTP]  
      

    (Android)click :

    2017-09-19 04:06:27:348 - [HTTP] --> POST /wd/hub/session/acfa31ae-321f-4ee1-a34b-294667393f8f/element/9/click {"id":"9"}
    2017-09-19 04:06:27:348 - [debug] [MJSONWP] Calling AppiumDriver.click() with args: ["9","acfa31ae-321f-4ee1-a34b-294667393f8f"]
    2017-09-19 04:06:27:359 - [debug] [AndroidBootstrap] Sending command to android: {"cmd":"action","action":"element:click","params":{"elementId":"9"}}
    2017-09-19 04:06:27:375 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"action","action":"element:click","params":{"elementId":"9"}}
    2017-09-19 04:06:27:391 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type ACTION
    2017-09-19 04:06:27:391 - [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command action: click
    2017-09-19 04:06:27:876 - [debug] [AndroidBootstrap] Received command result from bootstrap
    2017-09-19 04:06:27:876 - [debug] [MJSONWP] Responding to client with driver.click() result: true
    2017-09-19 04:06:27:880 - [HTTP]  
      



    IOS :

    driver.findByAccessibilityId("Compose").click();

    (IOS)findElement :

    2017-09-19 07:19:36:259 - [HTTP] --> POST /wd/hub/session/bbb16560-a4c7-43fc-a5d0-dea9057dff93/element {"using":"accessibility id","value":"Compose"}
    2017-09-19 07:19:36:259 - [debug] [MJSONWP] Calling AppiumDriver.findElement() with args: ["accessibility id","Compose","bbb16560-a4c7-43fc-a5d0-dea9057dff93"]
    2017-09-19 07:19:36:260 - [debug] [XCUITest] Executing command 'findElement'
    2017-09-19 07:19:36:260 - [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, name, class name, -ios predicate string, -ios class chain, accessibility id
    2017-09-19 07:19:36:260 - [debug] [BaseDriver] Waiting up to 3000 ms for condition
    2017-09-19 07:19:36:261 - [debug] [JSONWP Proxy] Proxying [POST /element] to [POST http://127.0.0.1:8100/session/3FAA9ECD-8EE9-49BC-B1F9-010B03B9821B/element] with body: {"using":"accessibility id","value":"Compose"}
    2017-09-19 07:19:37:826 - [debug] [JSONWP Proxy] Got response with status 200: {"value":{"ELEMENT":"E56F3927-08E6-4ECD-B3E4-05F30198FA6A","type":"XCUIElementTypeButton","label":"Compose"},"sessionId":"3FAA9ECD-8EE9-49BC-B1F9-010B03B9821B","status":0}
    2017-09-19 07:19:37:829 - [debug] [MJSONWP] Responding to client with driver.findElement() result: {"ELEMENT":"E56F3927-08E6-4ECD-B3E4-05F30198FA6A","type":"XCUIElementTypeButton","label":"Compose"}
    2017-09-19 07:19:37:843 - [HTTP]  
      

    (IOS)click :

    2017-09-19 07:19:37:869 - [HTTP] --> POST /wd/hub/session/bbb16560-a4c7-43fc-a5d0-dea9057dff93/element/E56F3927-08E6-4ECD-B3E4-05F30198FA6A/click {"id":"E56F3927-08E6-4ECD-B3E4-05F30198FA6A"}
    2017-09-19 07:19:37:870 - [MJSONWP] Driver proxy active, passing request on via HTTP proxy
    2017-09-19 07:19:37:870 - [debug] [XCUITest] Executing command 'proxyReqRes'
    2017-09-19 07:19:37:870 - [debug] [JSONWP Proxy] Proxying [POST /wd/hub/session/bbb16560-a4c7-43fc-a5d0-dea9057dff93/element/E56F3927-08E6-4ECD-B3E4-05F30198FA6A/click] to [POST http://127.0.0.1:8100/session/3FAA9ECD-8EE9-49BC-B1F9-010B03B9821B/element/E56F3927-08E6-4ECD-B3E4-05F30198FA6A/click] with body: {"id":"E56F3927-08E6-4ECD-B3E4-05F30198FA6A"}
    2017-09-19 07:19:39:829 - [debug] [JSONWP Proxy] Got response with status 200: {"status":0,"id":"E56F3927-08E6-4ECD-B3E4-05F30198FA6A","value":"","sessionId":"3FAA9ECD-8EE9-49BC-B1F9-010B03B9821B"}
    2017-09-19 07:19:39:829 - [JSONWP Proxy] Replacing sessionId 3FAA9ECD-8EE9-49BC-B1F9-010B03B9821B with bbb16560-a4c7-43fc-a5d0-dea9057dff93
    2017-09-19 07:19:39:834 - [HTTP]  
      


    좋은 웹페이지 즐겨찾기