企业微信通讯录_显示等待提问


如图在初始化时,我们需要添加一个显示等待直到 导出这个元素能够被定位到。这样我们才能够在add_element函数里面找到 self.find_ele((By.LINK_TEXT,'添加成员')).click()

我的疑惑:按照我的逻辑,我封装好了一个find_ele函数。这会使我在接下来10秒的时间一直寻找 添加成员,所以init函数里面的显示等待就可以不要了。但是实际操作却不能这样。这也是为什么呀?

代码部分

ContactPage代码

class ContactPage(BasePage):
   def __init__(self, driver: WebDriver):
       # 接受外部传入的driver,用于当前的自动化测试
       super().__init__(driver)
       WebDriverWait(self.driver, 10).until(expected_conditions.visibility_of_element_located((By.LINK_TEXT, '导出')))

   def add_member(self, member: Member):

       self.find_ele((By.LINK_TEXT,'添加成员')).click()

       self.find_ele((By.NAME, 'username')).send_keys(member.name)

       self.find_ele((By.NAME, 'acctid')).send_keys(member.account)


       email_ele = self.find_ele((By.ID, 'memberAdd_biz_mail'))
       email_ele.clear()
       email_ele.send_keys(member.mail)


       self.find_ele((By.NAME, 'mobile')).send_keys(member.phone)

       self.find_ele((By.LINK_TEXT, '保存')).click()

       WebDriverWait(self.driver, 10) \
           .until(expected_conditions.visibility_of_element_located(
           (By.LINK_TEXT, '立即邀请')
       )
       )
       # self.find_ele((By.LINK_TEXT, '立即邀请'))

       return self

BasePage代码

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait


class BasePage:
    def __init__(self,driver:WebDriver):
        if driver is not None:
            self.driver=driver
        else:
            options = Options()
            options.debugger_address = '127.0.0.1:9222'
            self.driver = webdriver.Chrome(options=options)

    def find_ele(self,element):
        WebDriverWait(self.driver,10).until(expected_conditions.visibility_of_element_located(element))
        return self.driver.find_element(*element)

    def click_ele(self,element):
        # WebDriverWait(self.driver, 10).until(expected_conditions.visibility_of_element_located(element))
        return self.find_ele(element).click()

    def send_ele(self,element,keyword):
        return self.find_ele(element).send_keys(keyword)

test代码

class TestMemberAdd:

    def setup_class(self):
        self.wework = WeWorkPage()
        self.contact_page = self.wework.contack()

    def setup(self):
        self.contact_page = self.wework.portal().contack()

    @pytest.mark.parametrize('memeber_data', [

        {'name': 'zzz'},
        {'name': 'xxx'},
        {'name': 'ccc'},
    ])
    def test_add_member(self, memeber_data):
        random = str(datetime.now().timestamp()).split('.')[0]
        member = Member(**memeber_data)
        member.name = member.name
        member.account = member.name + random
        member.mail = member.name + random
        member.phone = random + '0'
        self.contact_page.add_member(member)  # 添加

        self.member_edit_page = self.contact_page.search_member(member.account)  # 搜索
        get_member = self.member_edit_page.get_member()  # 获取
        assert get_member.account == member.account  # 断言

实际操作是什么样子?

实际操作就是,我如果把如图init里面的等待语句删除了就会报错。


我如果不删除就可以跑成功整个用例。但如果删除了就会报错,告诉我这句话超时;我想知道为什么,因为老师教过我们封装过BasePage,他的功能不就是让我们在规定的时间找到指定元素吗,我认为既然继承了BasePage的功能就可以去掉init里的显示等待。但实际是不能够去掉的
image

你去掉的是哪一句?你把超时报错的错误也贴下吧


画线的部分注释掉了会报错,我也知道他不能注释,但是想不通为什么

test setup failed
self = <class 'wework.tests.test_contact_page.TestMemberAdd'>

    def setup_class(self):
        self.wework = WeWorkPage()
>       self.contact_page = self.wework.contack()

test_contact_page.py:13: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\page\wework_page.py:24: in contack
    WebDriverWait(self.driver, 10).until(loop_click)  # 循环调用,可以使浏览器点击一次不生效的时候在以后的10秒内多次点击直到生效
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.support.wait.WebDriverWait (session="033b8e50c06fe16032d0a0eb8e6499fc")>
method = <function WeWorkPage.contack.<locals>.loop_click at 0x000002ACFA0B7640>
message = ''

    def until(self, method, message: str = ""):
        """Calls the method provided with the driver as an argument until the \
        return value does not evaluate to ``False``.
    
        :param method: callable(WebDriver)
        :param message: optional message for :exc:`TimeoutException`
        :returns: the result of the last call to `method`
        :raises: :exc:`selenium.common.exceptions.TimeoutException` if timeout occurs
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.monotonic() > end_time:
                break
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message:

..\..\venv\lib\site-packages\selenium\webdriver\support\wait.py:90: TimeoutException

报错来自于这里,感觉跟你的封装是没关系的。这个代码在你执行的时候被执行了,他本身的逻辑没满足导致超时了。你得看看这块的代码



报错内容


test_contact_page.py::TestMemberAdd::test_add_member[memeber_data0] 
test_contact_page.py::TestMemberAdd::test_add_member[memeber_data1] PASSED [ 33%]FAILED [ 66%]
test_contact_page.py:17 (TestMemberAdd.test_add_member[memeber_data1])
self = <wework.tests.test_contact_page.TestMemberAdd object at 0x000001E8ACFAC610>
memeber_data = {'name': 'xxx'}

    @pytest.mark.parametrize('memeber_data', [
    
        {'name': 'zzz'},
        {'name': 'xxx'},
        {'name': 'ccc'},
    ])
    def test_add_member(self, memeber_data):
        random = str(datetime.now().timestamp()).split('.')[0]
        member = Member(**memeber_data)
        member.name = member.name
        member.account = member.name + random
        member.mail = member.name + random
        member.phone = random + '0'
>       self.contact_page.add_member(member)  # 添加

test_contact_page.py:31: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\page\contact_page.py:25: in add_member
    self.find_ele((By.NAME, 'username')).send_keys(member.name)
..\framework\base_page.py:18: in find_ele
    WebDriverWait(self.driver,10).until(expected_conditions.visibility_of_element_located(element))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.support.wait.WebDriverWait (session="ac120d4f7f8fd10adabf303dc69eabc7")>
method = <function visibility_of_element_located.<locals>._predicate at 0x000001E8ACFAAEF0>
message = ''

    def until(self, method, message: str = ""):
        """Calls the method provided with the driver as an argument until the \
        return value does not evaluate to ``False``.
    
        :param method: callable(WebDriver)
        :param message: optional message for :exc:`TimeoutException`
        :returns: the result of the last call to `method`
        :raises: :exc:`selenium.common.exceptions.TimeoutException` if timeout occurs
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.monotonic() > end_time:
                break
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message: 
E       Stacktrace:
E       Backtrace:
E       	Ordinal0 [0x008278B3+2193587]
E       	Ordinal0 [0x007C0681+1771137]
E       	Ordinal0 [0x006D41A8+803240]
E       	Ordinal0 [0x007024A0+992416]
E       	Ordinal0 [0x0070273B+993083]
E       	Ordinal0 [0x0072F7C2+1177538]
E       	Ordinal0 [0x0071D7F4+1103860]
E       	Ordinal0 [0x0072DAE2+1170146]
E       	Ordinal0 [0x0071D5C6+1103302]
E       	Ordinal0 [0x006F77E0+948192]
E       	Ordinal0 [0x006F86E6+952038]
E       	GetHandleVerifier [0x00AD0CB2+2738370]
E       	GetHandleVerifier [0x00AC21B8+2678216]
E       	GetHandleVerifier [0x008B17AA+512954]
E       	GetHandleVerifier [0x008B0856+509030]
E       	Ordinal0 [0x007C743B+1799227]
E       	Ordinal0 [0x007CBB68+1817448]
E       	Ordinal0 [0x007CBC55+1817685]
E       	Ordinal0 [0x007D5230+1856048]
E       	BaseThreadInitThunk [0x7711FA29+25]
E       	RtlGetAppContainerNamedObjectPath [0x77947A9E+286]
E       	RtlGetAppContainerNamedObjectPath [0x77947A6E+238]

..\..\venv\lib\site-packages\selenium\webdriver\support\wait.py:90: TimeoutException
FAILED [100%]
test_contact_page.py:17 (TestMemberAdd.test_add_member[memeber_data2])
self = <wework.tests.test_contact_page.TestMemberAdd object at 0x000001E8ACFAC520>
memeber_data = {'name': 'ccc'}

    @pytest.mark.parametrize('memeber_data', [
    
        {'name': 'zzz'},
        {'name': 'xxx'},
        {'name': 'ccc'},
    ])
    def test_add_member(self, memeber_data):
        random = str(datetime.now().timestamp()).split('.')[0]
        member = Member(**memeber_data)
        member.name = member.name
        member.account = member.name + random
        member.mail = member.name + random
        member.phone = random + '0'
>       self.contact_page.add_member(member)  # 添加

test_contact_page.py:31: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\page\contact_page.py:25: in add_member
    self.find_ele((By.NAME, 'username')).send_keys(member.name)
..\framework\base_page.py:18: in find_ele
    WebDriverWait(self.driver,10).until(expected_conditions.visibility_of_element_located(element))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.support.wait.WebDriverWait (session="ac120d4f7f8fd10adabf303dc69eabc7")>
method = <function visibility_of_element_located.<locals>._predicate at 0x000001E8ACFAB5B0>
message = ''

    def until(self, method, message: str = ""):
        """Calls the method provided with the driver as an argument until the \
        return value does not evaluate to ``False``.
    
        :param method: callable(WebDriver)
        :param message: optional message for :exc:`TimeoutException`
        :returns: the result of the last call to `method`
        :raises: :exc:`selenium.common.exceptions.TimeoutException` if timeout occurs
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, 'screen', None)
                stacktrace = getattr(exc, 'stacktrace', None)
            time.sleep(self._poll)
            if time.monotonic() > end_time:
                break
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message: 
E       Stacktrace:
E       Backtrace:
E       	Ordinal0 [0x008278B3+2193587]
E       	Ordinal0 [0x007C0681+1771137]
E       	Ordinal0 [0x006D41A8+803240]
E       	Ordinal0 [0x007024A0+992416]
E       	Ordinal0 [0x0070273B+993083]
E       	Ordinal0 [0x0072F7C2+1177538]
E       	Ordinal0 [0x0071D7F4+1103860]
E       	Ordinal0 [0x0072DAE2+1170146]
E       	Ordinal0 [0x0071D5C6+1103302]
E       	Ordinal0 [0x006F77E0+948192]
E       	Ordinal0 [0x006F86E6+952038]
E       	GetHandleVerifier [0x00AD0CB2+2738370]
E       	GetHandleVerifier [0x00AC21B8+2678216]
E       	GetHandleVerifier [0x008B17AA+512954]
E       	GetHandleVerifier [0x008B0856+509030]
E       	Ordinal0 [0x007C743B+1799227]
E       	Ordinal0 [0x007CBB68+1817448]
E       	Ordinal0 [0x007CBC55+1817685]
E       	Ordinal0 [0x007D5230+1856048]
E       	BaseThreadInitThunk [0x7711FA29+25]
E       	RtlGetAppContainerNamedObjectPath [0x77947A9E+286]
E       	RtlGetAppContainerNamedObjectPath [0x77947A6E+238]

..\..\venv\lib\site-packages\selenium\webdriver\support\wait.py:90: TimeoutException


**提问:**都是等待同一个界面的元素,为什么一个会报错,一个就能通过这个case

@seveniruby 老师,在帮我看看呗

因为“添加成员“在没进入通讯录页面之前就存在了。是个巧合,在企业微信后台的默认首页里,也存在一个”添加成员“按钮,我上课的时候讲过这个,你可能没注意。