web自动化-selenium 入门篇

selenium安装介绍

selenium是web浏览器的自动化工具

官网:https://www.selenium.dev

  • 构成:

    • WebDriver: 浏览器提供的浏览器api来控制浏览器(模拟用户操作)
    • IDE: 可以录制用户的操作(录制工具)
    • Grd:分布式,可以在多个浏览器进行操作
  • selenium架构图

    web自动化-selenium 入门篇

原理:在客户端(client)用不同的语言对selenium脚本进行编写-->将脚本传送给selenium服务器(driver)-->服务器调用相应的浏览器驱动来启动对应的浏览器并执行相应的脚本操作

在python的使用
from selenium import webdriver

def test_selenium():
driver = webdriver.Chrome(r'D:\Google\Chrome\chromedriver.exe') # 如果没有配置浏览器driver环境变量,可传入driver的路径
driver.get('https://www.baidu.com/')
time.sleep(10) driver.quit()

seleniumIDE用例录制

  • 适用于开始入门ui自动化测试
  • 团队代码基础差
  • 技术成长之后学习价值不高,所以了解即可,这里不在记录

selenium用例编写

  • 1 - 导入依赖: from selenium import webdriver
  • 2 - 创建driver:

    - 如果是谷歌浏览器:driver = webdriver.Chrome()

    - 如果是火狐浏览器:driver = webdriver.Firefox()

    ...
  • 3 - 执行自动化步骤:

    1 - 打开百度:driver.get('https://www.baidu.com/')

    2 - 在搜索框中输入需要搜索的关键字:driver.find_element(By.ID, "kw").send_keys('稀饭配菜根')

    3 - 点击搜索按钮:self.driver.find_element(By.ID, "su").click()
  • 4 - 断言
示例代码
from selenium.webdriver.common.by import By
from selenium import webdriver
from time import sleep class TestDemo:
def setup(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5) # 隐式等待 def teardown(self):
self.driver.quit() def test_baidu(self):
self.driver.get('https://www.baidu.com/')
self.driver.find_element(By.ID, "kw").send_keys('稀饭配菜根')
self.driver.find_element(By.ID, "su").click()
sleep(5)

selenium三种等待方式

一、直接等待

  • python自带语法:time.sleep() -->强制待线程休眠,网络、硬件原因 不灵活
  • 用法:在测试步骤前后添加:time.sleep(3)
    # 直接等待:
    def test_sleep_wait(self):
    sleep(3)
    print('等待3秒结束')

二、隐式等待

  • self.driver.implictly_wait(5):

    设置一个等待时间,轮询查找元素是否出现,如果没有就抛出异常,每隔0.5秒去轮询查找,直到设置的 秒数除以0.5 次,如果设置为3秒,当元素过早显示就不需要等待3秒 或者 超过3秒没有显示就抛出异常
  • 缺点:

    属于全局等待,作用于所有的find_element,就造成有的find_element都需要等待那么长的时间,因为有些加载需要很长时间,如果设置成很长时间而这个元素刚好出现问题,就造成测试效率等问题发生,如果设置时间过短,而有些元素需要更长时间才能加载,也会发生报错
  • 用法

    可以在初始化的时候加入:self.driver.implictly_wait(5)
    def setup(self):
    self.driver = webdriver.Chrome()
    self.driver.implicitly_wait(5) # 隐式等待

三、显示等待

  • WebDriverWait 配合until()和unyil_not()

    针对某一个元素或者find_element进行的等待,指定了具体的一个操作,根据判断条件进行等待,默认每隔0.5秒进行条件判断,如果条件成立则执行下一步 否则继续等待,直到超过设定的最长时间
  • 用法1:
    • 使用lambda函数自定义等待方法:WebDriverWait(self.driver, 3, 1).until(lambda x: x.find_element_by_xpath('//*[@title="所有分类"]/a')).click()
    • 需要导入依赖:from selenium.webdriver.support.wait import WebDriverWait
    def test_web_driver_wait_1(self):
    # until()需要传入一个函数
    # def wait(x):
    # return len(self.driver.find_elements(By.XPATH, '//*[@class=""]')) >= 1
    # WebDriverWait(self.driver, 10).until(wait)
    WebDriverWait(self.driver, 3, 1).until(lambda x: x.find_element_by_xpath('//*[@title="所有分类"]/a')).click()
    self.driver.find_element_by_class_name("所有项目").click()
  • 用法2:
    • 使用selenium自带的方法,expected_conditions提供很多等待方法:
      • 需要导入依赖:from selenium.webdriver.support import expected_conditions
    • title_is: 判断当前页面的title是否完全等于(==)预期字符串,返回是布尔值
    • title_contains: 判断当前页面的title是否包含预期字符串,返回布尔值
    • presence_of_element_located: 判断某个元素是否被加到了dom树里,并不代表该元素一定可见
    • visibility_of_element_located: 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
    • visibility_of: 跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
    • presence_of_all_elements_located: 判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
    • text_to_be_present_in_element: 判断某个元素中的text是否 包含 了预期的字符串
    • text_to_be_present_in_element_value: 判断某个元素中的value属性是否 包含 了预期的字符串
    • frame_to_be_available_and_switch_to_it: 判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
    • invisibility_of_element_located: 判断某个元素中是否不存在于dom树或不可见
    • element_to_be_clickable: 判断某个元素中是否可见并且是enable的,这样的话才叫clickable
    • staleness_of: 等某个元素从dom树中移除,注意,这个方法也是返回True或False
    • element_to_be_selected: 判断某个元素是否被选中了,一般用在下拉列表
    • element_selection_state_to_be: 判断某个元素的选中状态是否符合预期
    • element_located_selection_state_to_be: 跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
    • alert_is_present: 判断页面上是否存在alert
    # selenium自带方法
    def test_web_driver_wait_2(self):
    # 使用expected_conditions.element_to_be_clickable,在点击“所有分类”之前,回先判断元素是否可见并且可以点击
    WebDriverWait(self.driver, 3, 1).until(expected_conditions.element_to_be_clickable
    ((By.XPATH, '//*[@title="所有分类"]/a'))).click()

selenium控件定位与常见操作

一、id定位(id在整个页面是唯一的)
    - find_element(By.ID, 'kw').send_keys('测试开发')
- find_element(By.ID, 'su').click()
二、css selector
  • 使用样式进行定位,比xpath快
  • 作用域:appium selenium css selector

    注意:appium元素控件不支持css selector定位,应用嵌套webview才可以使用
  • 常用css selector
    • .class .intro 选择class=”intro的所有元素“
    • #id #firstname 选择id="firstname"的所有元素
    • * * 选择所有元素
    • p 选择所有<p>的元素
    • div p 选择所有<div>元素和所有<p>元素
    • div>p 选择父元素为<div>元素的所有<p>元素 注意 父元素为<div>元素
    • div+p 选择紧接在<div>元素之后的所有<p>元素
    • 重点:[attribute] [target] 选择带有targetr属性的所有元素
    • [attribute=value] [target=_blank] 选择带有target=_blank属性的所有元素
    • :nth-child(n) p:nth-child(n) 选择属于其父元素的第二子元素的每隔<p>元素
    • p~ul 选择前面有<p>元素的每隔<ul>元素
使用
  • 在google控制台Console使用 $('') 进行css selector语法定位:(baidu)
    • 理解$('#s_tab a:nth-child(2)')和$('#s_tab>a:nth-child(2)')区别在于使用大于号和空格,大于号表示子孙,空格表示子子孙孙
    • $('#kw') 定位id='kw'的元素
    • $('#s_tab b') 定位id='s_tab'下的子孙元素b
    • 理解点:$('#s_tab a:nth-child(2)') 先找到a的父元素 在看所需的元素在父元素的第几个位置 此语句表示定位a元素的父元素的第二个元素
  • 在selenium的应用
    self.driver.find_element(By.CSS_SELECTOR, '#kw').send_keys("测试开发")

xpath

  • 层级定位(从头到尾遍历),比css selector慢很多,比较万能
  • 作用域XML Path Language
  • 用于解析html和xml
  • 可用于:appium seleium xpath
表达式
  • /bookstore/book[1] 选取属于bookstore子元素的的一个book元素
  • /bookstore/book[last()] 选取属于bookstore子元素的的ui后一个book元素
  • /bookstore/book[last()-1] 选取属于bookstore子元素的的倒数第二个book元素
  • /bookstore/book[position()<4]选取最前面3个属于bookstore元素的子元素的book元素
  • //title[@lang='eng'] 选取所有title元素,且这些元素拥有属性值为eng的lang属性
  • /bookstore/book[price>35.00] 选取bookstore元素的所有book元素,且price元素值大于35.00
  • /bookstore/book[price>35.00]/title 选取bookstore元素中的book元素的所有title元素,且price元素值大于35.00
xpath重点讲解(属性定位)

在google(F12)控制台Console使用 $x('') 进行xpath语法定位:(baidu)

  • //*[id="s_tab”]是父元素 /或//后代表子元素或子孙元素 一个/只能定位到子元素,要定位到子孙元素(往下更多层级)需要用到//
  • $x('//*[id="s_tab”]//b') //代表选取所有元素 *代表选取任意元素 [id="s_tab“]再选取id="s_tab“的元素 //b选取获取到的元素下面的b元素
  • $x('//*[id="s_tab”]/a[1]') 选取定位多个相同元素中的第一个
  • $x('//*[id="from"]//a[1]//ul') 多层嵌套,需要用到//定位 因为单个/只能定位到元素的下一层
上一篇:LSTM的“前生今世”


下一篇:Python爬虫小白入门(五)PhatomJS+Selenium第二篇