原理
Chrome 提供了一个接口,Selenium 之所以可以操作Chrome,是因为Chrome 在启动的时候开放 Debug 端口,ChromeDriver 借助于 Debug 开放的端口,与 Chrome 之间的自动化,各种调用 Chrome接口 ,本质上是使用一种调试协议来进行自动化测试的
参考
https://selenium-python.readthedocs.io/navigating.html selenium官方文档
https://www.w3school.com.cn/cssref/css_selectors.asp CSS选择器
实例:百度搜索selenium
导入webdriver类
from selenium import Webdriver
# 调用selenium浏览器驱动,获取浏览器句柄
driver = webdriver.Firefox()
# 通过句柄访问URL
first_url = 'http://www.baidu.com'
driver.get(first_url)
# 通过句柄控制页面元素
driver.find_element_by_id("kw").send_keys("selenium") # 在搜索框输入selenium
driver.find_element_by_id("su").click() # 单击百度一下
selenium安装环境
- 安装python3
- 安装selenium: pip install selenium
- 安装浏览器驱动,将驱动放置python目录下
元素定位
1.id定位
find_element_by_id(“id名称”)
2.name定位
find_element_by_name(“name名称”)
3.class定位
find_ement_by_class_name(“class名称”)
4.tag定位
每个元素本质上也是一个tag,例如:<input>、<div>、<a>
find_element_by_tag_name(“input”)
5.link定位
它专门用来定位文本链接:
find_element_by_link_text(“链接名”)
6.partial_link定位
parial link定位是对link定位的一种补充,有些文本链接会比较长,这个时候我们可以取文本链接的一部分定位,只要这一部分信息可以唯一地标识这个链接。
find_element_by_partial_link_text(“一个很长的文本链接”)
7.xpath定位
- 绝对路径定位
find_element_by_xpath("/html/body/div/div[2]/div/div/div/from/span/input")
div[2]表示当前层级下的第二个div标签
- 元素属性定位
find_element_by_xpath("//input[@id=‘id名称’]")
find_element_by_xpath("//input[@name=‘name名称’]")
find_element_by_xpath("//input[@class=‘class名称’]")
find_element_by_xpath("//*[@id=‘id名称’]")
find_element_by_xpath("//input[@type=‘submit’]")
find_element_by_xpath(’//p[contains(text(), “问卷”)]/a’)
显示等待和隐式等待
driver.implicitly_wait(3) 比sleep()更智能
后者只能固定等待时间,前者可以在一个范围内智能等待
sleep() #是以秒为单位
- 显示等待
显示等待是针对于某个特定的元素设置的等待时间,如果在规定的时间范围内,没有找到元素,则会抛出异常,如果在规定的时间内找到了元素,则直接执行,即找到元素就执行相关操作element=WebDriverWait(driver,5,0.5),until(EC.presence_of_element_located((By.ID,'su')))
解释:WebDriverWait(driver,5,0.5)5表示等待的最大时长秒单位,0.5位间隔秒
EC.presence_of_element_located((By.ID,‘su’))方法本身调用时有括号,所以调用时会有双括号填入参数
- 隐式等待
隐式等待是设置的全局等待,分为1、页面加载超时等待 ;2、页面元素加载超时;3、异步脚本超时
如果是页面元素超时,设置等待时间,是对页面中的所有元素设置加载时间。隐式等待是其实可以理解成在规定的时间范围内,浏览器在不停的刷新页面,直到找到相关元素或者时间结束。
driver.implicitly_wait(5)
隐式等待,设置等待时长5秒
小练习
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import allure
class TestAfter:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.get('https://testerhome.com')
self.driver.maximize_window()
self.driver.implicitly_wait(10)
def teardown(self):
self.driver.quit()
def test_scan(self):
self.driver.find_element(By.XPATH, '//*[@id="main"]/div/div[1]/div[2]/div[1]/div/a').click()
self.driver.find_element(By.XPATH, '//*[@id="main"]/div/div[1]/div[1]/div[1]/div[1]/div[2]/div[1]/a').click()
def test_nologin(self):
self.driver.find_element(By.XPATH, '//*[@id="main-nav-menu"]/ul/li[4]/a').click()
sleep(3)
self.driver.find_element(By.CLASS_NAME, 'team-name').click()
sleep(6)
self.driver.find_element(By.CSS_SELECTOR, '[title="第十期_Selenium 第二周_20190801"]').click()
sleep(5)
assert "访问被拒绝,你可能没有权限或未登录。" in self.driver.page_source
def test_errorlogin(self):
self.driver.find_element(By.XPATH, '//*[@id="main-page"]/div[1]/nav/div/ul[1]/li[2]/a').click()
sleep(3)
self.driver.find_element_by_id('user_login').send_keys('zhanglu')
sleep(3)
self.driver.find_element_by_name('user[password]').send_keys('123456')
self.driver.find_element_by_name('commit').click()
sleep(4)
assert "帐号或密码错误" in self.driver.page_source
def test_girl(self):
search = self.driver.find_element_by_name('q')
search.send_keys('测试媛')
search.send_keys(Keys.ENTER)
sleep(3)
self.driver.find_element(By.XPATH, '//*[@id="main"]/div/div[2]/div[4]/div[1]/a').click()
sleep(3)
assert "测试媛" in self.driver.page_source
测试报告
pytest 路径/…py --alluredir=任一路径
allure serve 任一路径
打开浏览器debug模式
- windows(进入chrome的路径下)
chrome.exe --remote-debugging-port=9222 - mac
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome -remote-debugging-port=9222
注意:一定要整个退出chrome浏览器再执行该命令,否则不生效。
在打开的浏览器中输入网址即可默认是debug模式,登录一次即可
比如:
chrome浏览器打开百度网址,在另一窗口输入127.0.0.1:9222,将会进入调试模式点击元素,某些网站可能会click不生效,如下
这时就要使用js注入
# 验证:浏览器的控制台中会输出“hello world!”
print(self.driver.execute_script("console.log('hello world!')"))
# 验证:给python返回一个值,当前页的title
print(self.driver.execute_script("return document.title;"))
# js方式点击一个已赋值的元素
self.driver.execute_script("arguments[0].click();", element_add)
# js方式点击元素的另一种方式,没有先赋值
self.driver.execute_script("arguments[0].click();",self.driver.find_element(By.CSS_SELECTOR, "#js_upload_input"))
self.driver.find_element_by_id("js_upload_input").click()
# js方式上传图片,直接输入图片的路径,就自动上传成功
self.driver.find_element(By.ID, "js_upload_input").send_keys("/Users/apple/Documents/photos/2.png")