企业微信实战2---报错信息---InvalidSelectorException--selenium.common.exceptions.InvalidSelectorException: Message: Locator Strategy 'xpath,//android.widget.TextView[@text='通讯录']' is not supported for this session

代码如下:
app.py:

#存放app应用常用的一些方法 启动 关闭 停止 进入首页
from appium import webdriver
from testing.appium.page.base_page import BasePage
from testing.appium.page.mainpage import MainPage

class App(BasePage):
def start(self):
“”"
启动APP
:return:
“”"
if self.driver == None:
# 基类定义第一次调用时候driver是null
caps = {}
caps[“platformName”] = “android”
caps[“deviceName”] = “127.0.0.1:7555”
caps[“appPackage”] = “com.tencent.wework”
caps[“appActivity”] = “.launch.LaunchSplashActivity”
caps[“noReset”] = “true”
caps[‘skipServerInstallation’] = ‘true’ # 跳过 uiautomator2 server的安装
caps[‘skipDeviceInitialization’] = ‘true’ # 跳过设备初始化
# caps[‘dontStopAppOnReset’] = ‘true’ # 启动之前不停止app
caps[‘settings[waitForIdleTimeout]’] = 0
# 与sever建立连接,初始化一个driver 创建session,返回一个session
self.driver = webdriver.Remote(‘http://localhost:4723/wd/hub’, caps)
self.driver.implicitly_wait(20)
else:
self.driver.launch_app()
return self
def restart(self):
self.driver.close()
self.driver.lanch_app()
return self

def stop(self):
    pass

def goto_main(self):
    return MainPage(self.driver)

mainpage.py
#主页面
from appium.webdriver.common.mobileby import MobileBy
from appium import webdriver
from testing.appium.page.ContactListPage import ContactListPage
from testing.appium.page.base_page import BasePage

class MainPage(BasePage):
# def init(self,driver):
# self.driver = driver
contactlist = (MobileBy.XPATH, “//android.widget.TextView[@text=‘通讯录’]”)

def goto_contactlist(self):
    #进入到通讯录
    #self.driver.find_element(MobileBy.XPATH, "//android.widget.TextView[@text='通讯录']").click()
    self.find_and_click(self.contactlist)
    return ContactListPage(self.driver)

def goto_workbench(self):
    pass

AddMember.py
#添加成员页
#from testing.appium.page.ContactAddPage import ContactAddPage
import time

from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support.wait import WebDriverWait

from testing.appium.page.base_page import BasePage

class AddMemberPage(BasePage):
# def init(self,driver):
# self.driver = driver

add_manual_element = (MobileBy.XPATH,
                             "//android.widget.TextView[@text='手动输入添加']")
toast_ele = (MobileBy.XPATH, "//*[@class='android.widget.Toast']")
def add_menual(self):
    #手动输入添加
    from testing.appium.page.ContactAddPage import ContactAddPage
    # self.driver.find_element(MobileBy.XPATH,
    #                          "//android.widget.TextView[@text='手动输入添加']").click()
    self.find_and_click(self.add_manual_element)
    return ContactAddPage(self.driver)

def get_toast(self):
    #text = '成功'
    # element = WebDriverWait(self.driver, 10).until(
    #         lambda x: x.find_element(MobileBy.XPATH, "//*[@class='android.widget.Toast']"))
    element = self.webdriver_wait(self.toast_ele)
    result = element.text
    time.sleep(5)
    return result

ContactAddPage.py
#from testing.appium.page.AddMemberPage import AddMemberPage
import time

from appium.webdriver.common.mobileby import MobileBy

from testing.appium.page.base_page import BasePage

class ContactAddPage(BasePage):
# def init(self,driver):
# self.driver = driver
# 设置姓名
name_element = (MobileBy.XPATH,
“//[contains(@text,‘姓名’)]/…/[@class=‘android.widget.EditText’]”)
gender_element = (MobileBy.XPATH,“//[contains(@text,‘性别’)]/…//[@text=‘男’]”)
male_ele = (MobileBy.XPATH, “//[@text=‘男’]“)
female_ele = (MobileBy.XPATH,”//
[@text=‘女’]”)
phonenum_ele = (MobileBy.XPATH, “//*[@text=‘手机号’]”)
save_ele = (MobileBy.ID, “com.tencent.wework:id/hvk”)

def set_name(self,name):
 # self.driver.find_element(MobileBy.XPATH,
 #                             "//*[contains(@text,'姓名')]/../*[@class='android.widget.EditText']").send_keys(name)
 self.find_and_sendkeys(self.name_element,name)
 return self

def set_gender(self,gender):
    # 设置性别
    # self.driver.find_element(MobileBy.XPATH,
    #                          "//*[contains(@text,'性别')]/..//*[@text='男']").click()
    self.find_and_click(self.gender_element)
    if gender == '男':
        time.sleep(2)
        #self.driver.find_element(MobileBy.XPATH, "//*[@text='男']").click()
        self.find_and_click(self.male_ele)
    else:
        time.sleep(2)
        # self.driver.find_element(MobileBy.XPATH, "//*[@text='女']").click()
        self.find_and_click(self.female_ele)
    return self

def set_phonum(self,phonenum):
    # self.driver.find_element(MobileBy.XPATH, "//*[@text='手机号']").send_keys(phonenum)
    self.find_and_sendkeys(self.phonenum_ele,phonenum)
    return self
def click_save(self):
    from testing.appium.page.AddMemberPage import AddMemberPage
    # self.driver.find_element(MobileBy.ID, "com.tencent.wework:id/hvk").click()
    self.find_and_click(self.save_ele)
    return AddMemberPage(self.driver)

ContactListPage.py
#通讯录列表页
from appium.webdriver.common.mobileby import MobileBy

from testing.appium.page.AddMemberPage import AddMemberPage
from testing.appium.page.base_page import BasePage

class ContactListPage(BasePage):
# def init(self, driver):
# self.driver = driver
addmember_text = “添加成员”
def addcontact(self):
# self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
# ‘new UiScrollable’
# ‘(new UiSelector().’
# ‘scrollable(true).’
# ‘instance(0)).’
# ‘scrollIntoView(’
# ‘new UiSelector().’
# ‘text(“添加成员”).instance(0));’).click()
self.find_by_scroll(self.addmember_text).click()
return AddMemberPage(self.driver)

  # def search_contact(self):
  #   pass

base_page.py
‘’’
BasePge:存放一些基本的方法,比如初始化driver,find查找元素
‘’’
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from appium import webdriver

class BasePage:

def __init__(self, driver:WebDriver = None):
    self.driver = driver

def find(self,locator):
    return self.driver.find_element(*locator)

def find_and_click(self,*locator):
    self.find(locator).click()

def find_and_sendkeys(self,locator,text):
    self.find(locator).send_keys(text)

def find_by_scroll(self,text):
    return self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                             'new UiScrollable'
                             '(new UiSelector().'
                             'scrollable(true).'
                             'instance(0)).'
                             'scrollIntoView('
                             'new UiSelector().'
                             f'text("text").instance(0));')

def webdriver_wait(self,locator,timeout=10):
    element = WebDriverWait(self.driver, timeout).until(
        lambda x: x.find_element(*locator)
    )
    return element

test_contact.py
from testing.appium.page.app import App
import pytest

class TestContact:

def setup_class(self):
    self.app = App()
    self.main = self.app.start().goto_main()

def test_contact(self):

    name = "霍格name2"
    gender = "女"
    phonenum = "13715280003"
    mypage = self.main.goto_contactlist().\
        addcontact().add_menual().\
        set_name(name).set_gender(gender).set_phonum(phonenum).click_save()
    text = mypage.get_toast()
    mypage.add_menual()
    assert '成功' in text

报错信息如下:
FAILED
testing\appium\testcases\test_contact.py:9 (TestContact.test_contact)
self = <testcases.test_contact.TestContact object at 0x000001F5D9590BB0>

def test_contact(self):

    name = "霍格name2"
    gender = "女"
    phonenum = "13715280003"
  mypage = self.main.goto_contactlist().\
        addcontact().add_menual().\
        set_name(name).set_gender(gender).set_phonum(phonenum).click_save()

test_contact.py:15:


…\page\mainpage.py:17: in goto_contactlist
self.find_and_click(self.contactlist)
…\page\base_page.py:20: in find_and_click
self.find(locator).click()
…\page\base_page.py:17: in find
return self.driver.find_element(*locator)
C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages\appium\webdriver\webdriver.py:279: in find_element
return self.execute(RemoteCommand.FIND_ELEMENT, {
C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages\selenium\webdriver\remote\webdriver.py:321: in execute
self.error_handler.check_response(response)
C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages\appium\webdriver\errorhandler.py:31: in check_response
raise wde
C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages\appium\webdriver\errorhandler.py:26: in check_response
super().check_response(response)


self = <appium.webdriver.errorhandler.MobileErrorHandler object at 0x000001F5D9920820>
response = {‘status’: 400, ‘value’: ‘{“value”:{“error”:“invalid selector”,“message”:“Locator Strategy 'xpath,//android.widget.Te…s\\app\\node_modules\\appium\\node_modules\\appium-base-driver\\lib\\protocol\\protocol.js:297:21)”}}’}

def check_response(self, response):
    """
    Checks that a JSON response from the WebDriver does not have an error.

    :Args:
     - response - The JSON response from the WebDriver server as a dictionary
       object.

    :Raises: If the response contains an error message.
    """
    status = response.get('status', None)
    if status is None or status == ErrorCode.SUCCESS:
        return
    value = None
    message = response.get("message", "")
    screen = response.get("screen", "")
    stacktrace = None
    if isinstance(status, int):
        value_json = response.get('value', None)
        if value_json and isinstance(value_json, basestring):
            import json
            try:
                value = json.loads(value_json)
                if len(value.keys()) == 1:
                    value = value['value']
                status = value.get('error', None)
                if status is None:
                    status = value["status"]
                    message = value["value"]
                    if not isinstance(message, basestring):
                        value = message
                        message = message.get('message')
                else:
                    message = value.get('message', None)
            except ValueError:
                pass

    exception_class = ErrorInResponseException
    if status in ErrorCode.NO_SUCH_ELEMENT:
        exception_class = NoSuchElementException
    elif status in ErrorCode.NO_SUCH_FRAME:
        exception_class = NoSuchFrameException
    elif status in ErrorCode.NO_SUCH_WINDOW:
        exception_class = NoSuchWindowException
    elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
        exception_class = StaleElementReferenceException
    elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
        exception_class = ElementNotVisibleException
    elif status in ErrorCode.INVALID_ELEMENT_STATE:
        exception_class = InvalidElementStateException
    elif status in ErrorCode.INVALID_SELECTOR \
            or status in ErrorCode.INVALID_XPATH_SELECTOR \
            or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
        exception_class = InvalidSelectorException
    elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
        exception_class = ElementNotSelectableException
    elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
        exception_class = ElementNotInteractableException
    elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
        exception_class = InvalidCookieDomainException
    elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
        exception_class = UnableToSetCookieException
    elif status in ErrorCode.TIMEOUT:
        exception_class = TimeoutException
    elif status in ErrorCode.SCRIPT_TIMEOUT:
        exception_class = TimeoutException
    elif status in ErrorCode.UNKNOWN_ERROR:
        exception_class = WebDriverException
    elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
        exception_class = UnexpectedAlertPresentException
    elif status in ErrorCode.NO_ALERT_OPEN:
        exception_class = NoAlertPresentException
    elif status in ErrorCode.IME_NOT_AVAILABLE:
        exception_class = ImeNotAvailableException
    elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
        exception_class = ImeActivationFailedException
    elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
        exception_class = MoveTargetOutOfBoundsException
    elif status in ErrorCode.JAVASCRIPT_ERROR:
        exception_class = JavascriptException
    elif status in ErrorCode.SESSION_NOT_CREATED:
        exception_class = SessionNotCreatedException
    elif status in ErrorCode.INVALID_ARGUMENT:
        exception_class = InvalidArgumentException
    elif status in ErrorCode.NO_SUCH_COOKIE:
        exception_class = NoSuchCookieException
    elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
        exception_class = ScreenshotException
    elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
        exception_class = ElementClickInterceptedException
    elif status in ErrorCode.INSECURE_CERTIFICATE:
        exception_class = InsecureCertificateException
    elif status in ErrorCode.INVALID_COORDINATES:
        exception_class = InvalidCoordinatesException
    elif status in ErrorCode.INVALID_SESSION_ID:
        exception_class = InvalidSessionIdException
    elif status in ErrorCode.UNKNOWN_METHOD:
        exception_class = UnknownMethodException
    else:
        exception_class = WebDriverException
    if value == '' or value is None:
        value = response['value']
    if isinstance(value, basestring):
        if exception_class == ErrorInResponseException:
            raise exception_class(response, value)
        raise exception_class(value)
    if message == "" and 'message' in value:
        message = value['message']

    screen = None
    if 'screen' in value:
        screen = value['screen']

    stacktrace = None
    if 'stackTrace' in value and value['stackTrace']:
        stacktrace = []
        try:
            for frame in value['stackTrace']:
                line = self._value_or_default(frame, 'lineNumber', '')
                file = self._value_or_default(frame, 'fileName', '<anonymous>')
                if line:
                    file = "%s:%s" % (file, line)
                meth = self._value_or_default(frame, 'methodName', '<anonymous>')
                if 'className' in frame:
                    meth = "%s.%s" % (frame['className'], meth)
                msg = "    at %s (%s)"
                msg = msg % (meth, file)
                stacktrace.append(msg)
        except TypeError:
            pass
    if exception_class == ErrorInResponseException:
        raise exception_class(response, message)
    elif exception_class == UnexpectedAlertPresentException:
        alert_text = None
        if 'data' in value:
            alert_text = value['data'].get('text')
        elif 'alert' in value:
            alert_text = value['alert'].get('text')
        raise exception_class(message, screen, stacktrace, alert_text)
  raise exception_class(message, screen, stacktrace)

E selenium.common.exceptions.InvalidSelectorException: Message: Locator Strategy ‘xpath,//android.widget.TextView[@text=‘通讯录’]’ is not supported for this session

C:\Users\Administrator\AppData\Roaming\Python\Python38\site-packages\selenium\webdriver\remote\errorhandler.py:242: InvalidSelectorException

观看性实在太差了 :rofl: 从报错来看,换一种定位方式试试吧

应该是传参设置错了,find element应该传入两个参数,现在是把整个表达式当成了定位符。

你断点调试下find函数的传参就知道了

OK

其实是base_page find_by_scroll这里写的跟老师写的不一致;
老师的:
def find_by_scroll(self, text):
logging.info(‘find_by_scroll’)
return self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
‘new UiScrollable(new UiSelector()’
‘.scrollable(true).instance(0))’
‘.scrollIntoView(new UiSelector()’
f’.text("{text}").instance(0));’)

我写的
self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
‘new UiScrollable’
‘(new UiSelector().’
‘scrollable(true).’
‘instance(0)).’
‘scrollIntoView(’
‘new UiSelector().’
‘text(“添加成员”).instance(0));’).click()