Python加Selenium自动化测试知乎网站(二)操作页面元素
做自动化测试得能模拟用户的操作步骤和行为,比如点击、勾选等,在模拟操作前,需要能识别页面的元素。
先定义一个检查点吧:未登录用户打开别人分享的Python话题的链接,能看到5个相关回答,并能看到关注话题的按钮,点击关注话题,会弹出登录框。然后搜索文章,能搜索到对应的内容,且不会弹出登录框。
于是需要识别到关注话题的按钮和话题的标题,当判断是否弹出了登录框,可以通过获取登录的控件元素来检查。
找一个元素需要用find_element,写的定位应该能唯一对应该元素,这样才能操作到正确的元素;
找多个元素需要用find_elements,写的定位能概况某一类元素,比如检查当前页面展示了多少篇文章;
定义元素的方式可以有:id, name, class name, xpath, css selector, link text, partial link text, tag name; 当然能用id就用id,这样最方便,另外用得最多的是xpath。
例如我们去获取该页面的文章区域时可以用:
driver.find_element_by_id("TopicMain")
获取该页面的'精华'链接时可以用:
driver.find_element_by_xpath("//div[@id='TopicMain']//ul[@role='tablist']/li[@aria-controls='Topic-top']/a")
也可以不用每次调用不同的方法去找元素,一会by_id,一会by_xpath之类的,可以统一用find_element,指定By的类型即可,比如:
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, "//div[@class='SignContainer-content']//input[@name='username']")
元素的类型可以是:按钮、输入框、下拉框、复选、单选、文本、超链接等等。不同的元素也有对应的操作方法,比如按钮和单选都可以用click,下拉框可以用select_by_value或select_by_index,输入框可以用send_keys,等。
在上面定义的检查点会用到的是按钮、文本、输入框,让我们先写一个可以运行的脚本:
# 这是一个未完善有缺点的样例,但可以看到效果。在后面的文章中逐步完善
from selenium import webdriver
topic_url = "https://www.zhihu.com/topic/19552832/hot"
keyword = "用Django做一个简单的记账网站"
driver = webdriver.Chrome()
driver.get(topic_url)
focus_topic_button = driver.find_element_by_xpath("//div[@class='TopicActions TopicMetaCard-actions']/button[contains(@class, 'TopicActions-followButton')]") # 获得'关注话题'按钮
topics = driver.find_elements_by_xpath("//div[@class='List-item TopicFeedItem']/div[@class='ContentItem ArticleItem']") # 获得当前页面展示的话题
assert len(topics) >= 5 # 检查话题数是不是大于5个
focus_topic_button.click() # 点击'关注话题'按钮
login_username_field = driver.find_element_by_xpath("//div[@class='SignContainer-content']//input[@name='username']") # 获得登录的用户名输入框
login_username_field.send_keys("123456") # 向用户名输入框输入内容
driver.find_element_by_xpath("//button[@class='Button Modal-closeButton Button--plain']").click() #关闭弹窗
search_field = driver.find_element_by_xpath("//div[contains(@class, 'AppHeader-SearchBar')]//input")
search_field.send_keys(keyword) # 输入搜索关键词
search_button = driver.find_element_by_xpath("//div[contains(@class, 'AppHeader-SearchBar')]//button[contains(@class, 'SearchBar-searchButton')]")
search_button.click() # 搜索
first_search_result_title = driver.find_element_by_xpath("//div[@id='SearchMain']//div[@class='Card SearchResult-Card'][1]//h2[@class='ContentItem-title']/a")
assert first_search_result_title.text == keyword # 检查第一个搜索结果是不是匹配搜索词
driver.close()
driver.quit()
当然上面这小段代码是不够好的,有一些问题:
- 当网络不稳定时容易找不到元素而报错;无等待机制;
- 无异常退出的处理;
- 元素未统一管理,在页面变动时会增加维护成本;
- 无封装无复用;
- 无测试统计等。
这些问题会在后面的章节中给解决掉。