selenium+Page Objects(第二话)
前面介绍了什么是po模式,并且简单分析了一下使用po模式编写脚本的思路,接下来开始正式编写
1.先编写一个页面基类BasePage.py,里面封装每个页面常用的一些方法
# coding: utf-8 # author: hmk from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException class BasePage(object): # 如果没有明确要继承的类,默认继承object,当然这里留空也行 """基类封装其他页面都会用到的方法""" base_url = 'http://localhost/UnifiedReporting/bid/caption?' def __init__(self, driver): self.driver = driver # 构造器中定义一个driver驱动,后续所有操作都引用这个driver,保持前后driver一致性 def open(self, url): """定义打开url方法""" url = self.base_url + url self.driver.get(url) self.driver.maximize_window() def find_element(self, *locator): """定位页面元素位置的方法""" try: # element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element(*locator)) # 这个方法我没有成功,总是定位不到元素 element = WebDriverWait(self.driver, 30).until(EC.presence_of_element_located(locator)) return element # 返回页面元素的位置对象 # 类型是<class 'selenium.webdriver.remote.webelement.WebElement'> except NoSuchElementException: print("%s 页面中未能找到 %s 元素" % (self, locator)) def switch_frame(self, loctor): """切换iframe表单""" return self.driver.switch_to_frame(loctor) def script(self, src): """执行js脚本""" self.driver.execute_script(src) def send_keys(self, locator, value, clear_first=True): """封装send_keys()方法""" try: # locator = getattr(self, "_%s"% locator) if clear_first: self.find_element(*locator).clear() # 判断是否需要清除输入框信息 self.find_element(*locator).send_keys(value) except AttributeError: print("%s 页面中未找到 %s 元素" % (self, locator)) def click(self, locator): """封装click()方法""" self.find_element(*locator).click() def get_current_url(self): """获取当前页面url""" return self.driver.current_url def get_url_title(self): """获取当前页面title""" return self.driver.title
注释写得也比较详细,不过多赘述了,后续需要其他操作的话,也可以继续添加进来
2.编写locators文件,把每个页面中的元素位置都事先定义好
# coding: utf-8 # author: hmk from selenium.webdriver.common.by import By class Locators(object): """元素定位器""" first_page_locators = { "agree_button": (By.ID, "btn_argee"), "disagree_button": (By.XPATH, "//a[@aria-label='不同意']") } second_page_locators = { "handle": (By.ID, "start_handle"), "back": (By.XPATH, "//a[text()='上一步']") } third_page_locators = { "custName": (By.NAME, "custName"), # 企业名称 "custAddr": (By.NAME, "custAddr"), # 企业地址 "custLegalMan": (By.NAME, "custLegalMan"), # 法定代表人 "custCerId": (By.NAME, "custCerId"), # 法定代表人证件 "custContactPerson": (By.NAME, "custContactPerson"), # 经办人姓名 "custCardId": (By.NAME, "custCardId"), # 经办人证件 "nextstep": (By.ID, "basicinfo_next_btn"), # 下一步 "backstep": (By.XPATH, "//a[text()='上一步']") # 上一步 } fourth_page_locators = { "upload_button1": (By.XPATH, ".//*[@id='uploadAttachList_body']/tr[1]/td[5]/a"), # 材料列表第一个材料的上传按钮 "upload_true": (By.CSS_SELECTOR, "#i_select_files>input"), # 去掉上传隐藏属性后的真实上传按钮 "upload_t": (By.XPATH, "//div[@class='layui-layer-content']//a[@aria-label='本地上传']"), # 必须双斜杠 "confirm": (By.XPATH, "//div[@class='layui-layer-content']//a[text()='确定']"), # 上传弹窗的确定按钮 "nextstep": (By.ID, "upload_next_btn"), # 下一步按钮 "backstep": (By.CLASS_NAME, "btn") # 上一步按钮 } if __name__ == "__main__": t = Locators() print(t.first_page_locators["agree_button"])
这里简单地把所有页面中用到的元素都写在了这里面,每个页面各自以字典形式存放元素,当然也可以拆分为几个文件分别存放,后面元素位置发生变化,可以在这里修改
2018-05-11 11:54:42