Android Client UI automation tips

  • Defines the fixture in conftest.py, say,
    • @pytest.fixture(scope="function")
      def driver(request):
          desired_caps = {
              'platformName': 'Android',
              'platformVersion': PLATFORM_VERSION,
              'app': APP_PATH,
              'unicodeKeyboard': True,
              'resetKeyboard': True,
              'deviceName': 'T21718CJ40232',
              # 'dontStopAppOnReset': True
              # 'autoGrantPermissions': True,
          }
          driver = webdriver.Remote(APPIUM_URL, desired_caps)
          driver.implicitly_wait(5)
      
          def fin():
              driver.quit()
      
          request.addfinalizer(fin)
          return driver  # provide the fixture value
  • Define how pytest should run in pytest.ini, say, rerun failed cases,
    • addopts = -v --reruns 3 --html=report.html --self-contained-html
  • Define pytest.mark in pytest.ini,
    • markers =
        tier1: smoke testing, test core function
        tier2: sanity testing, test main function (core + high-frequency operations)
        qa: run the test case on QA server only
        dev: run the test case on Dev server only
  • If you wanted to pass env. into the python, use,
    • os.getenv('APPIUM_URL') if os.getenv('APPIUM_URL') else 'http://localhost:4723/wd/hub'
    • @pytest.mark.skipif(os.getenv('OLD_CART_UI'), reason='skip it because it is old cart UI')
  • If you want to scroll your window to find out element ‘xyz’, you can use,
    • driver.find_element_by_android_uiautomator(PATH.COMMON_SCROLL_LEFT_PANEL.format(name))
      
      
      COMMON_SCROLL_LEFT_PANEL = "new UiScrollable(new UiSelector().scrollable(true).instance(0))." \
                                 "scrollIntoView(new UiSelector()." \
                                 "textContains(\"" + '{!s}' + "\").instance(0))"
      # If you wanted to scroll the second scrollable="true" element, use instance(1)
      # If you want to know how scrollable element in the page, print it via driver.page_source and search 'scrollable="true"'
  • http://www.xpathtester.com/xpath is a nice xpath tool.
  • xpath relative example, say,
    • INPUT_PRICE = "//android.widget.RelativeLayout[" \
                    "@resource-id='com.xxx.yyy:id/oc_item_default_price']" \
                    "//android.widget.EditText[@resource-id='com.xxx.yyy:id/oc_text_row_edit']"
    • COMMON_FIND_BY_TEXT = 'new UiSelector().text("{!s}")'
      COMMON_FIND_BY_TEXT_CONTAINS = 'new UiSelector().textContains("{!s}")'
  • Find element using uiautomator,
    • COMMON_FIND_BY_TEXT = ‘new UiSelector().text(“{!s}”)’
      COMMON_FIND_BY_TEXT_CONTAINS = ‘new UiSelector().textContains(“{!s}”)’
    • find_element_by_android_uiautomator
  • Sometimes appium is unable to refresh the page_source, try to bring it background then appium will refresh
    • driver.background_app(1)
      # sometimes you may need to try to seelp(seconds) after the background command to await it completes
  • A typical android client UI automation project directory structure.
    • Screen Shot 2019-02-24 at 9.16.16 PM
      • test_suite: it defines the test cases, it is like your test spec
        actions: it contains all of the ACTIONS, like find an element, scroll and click it.
      • labels: it contains the TEXTS in XXX App, say, ‘Tax rates will be autoxxx’
      • configs: it defines the test configurations, say, which apk you wanted to test
      • paths: it defines the PATHS how can you find the elements, say, ‘com.xxx.yyy:id/oc_switch_active’
      • conftest.py: it defines python fixtures for the test run
      • pytest.ini: it configures how pytest runs
  • Hide soft keyboard:
    • ‘unicodeKeyboard’: True,
    • ‘resetKeyboard’: True,
    • or
      driver.hide_keyboard() # case by case