python自动化web自动化:2.web自动化工具selenium讲解

Posted new nm个对象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python自动化web自动化:2.web自动化工具selenium讲解相关的知识,希望对你有一定的参考价值。

一.selenium简介

1.什么是selenium

Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera,Edge等。

2.selenium三大组件

  • WebDriver:是selenium提供的一个API,用于操作浏览器。

  • IDE:是selenium提供的一个插件,可以录制用户的操作

  • Grid:是selenium分布式的工具,实现在多个浏览器操作。使用Grid可以轻松实现用例的分布式执行。

  • 我们编写自动化主要使用WebDriver来实现,我们后面所指的selenium默认也是WebDriver

3.selenium的工作原理

在这里插入图片描述

4.selenium环境准备

  • 在python中安装selenium
pip install selenium
  • 配置浏览器驱动

下载driver:https://npm.taobao.org/mirrors/,选择对应的浏览器driver已经对应的版本,下载zip包。

将浏览器driver配置待环境变量,或者使用driver时指定路径。

5.selenium编写测试用例的步骤

(1)导入依赖

(2)生成driver

(3)执行测试步骤

(4)断言

import time
from selenium import webdriver # 导入selenium

# 使用webdriver,生成一个对应浏览器的driver。该driver提供了许多操作浏览器的API。
# 使用executable_path来指定chromedriver路径,如果将chromedriver.exe配置在了环境变量中,则不需要指定。
driver = webdriver.Chrome(executable_path='./etc/chromedriver.exe')

# 使用driver的api执行测试步骤
driver.get('https://www.baidu.com/') # 打开浏览器
driver.find_element_by_id('kw').send_keys('selenium') # 定位元素,并输入内容
driver.find_element_by_id('su').click() # 定位并点击元素
time.sleep(3)

# 断言
assert 'selenium' in driver.title

二.selenium的webdriver的常用API

1.webdriver访问网站API

from selenium import webdriver # 导入selenium

driver = webdriver.Chrome(executable_path='./etc/chromedriver.exe')
driver.get('https://www.baidu.com/') # 访问网站

2.元素定位API

selenium中提供了八种元素定位的方式。

(1)id定位

通过id属性来定位元素,定位唯一.

格式:
# 找到界面上id为'kw'的元素,以下两种方式效果一样.
1.driver.find_element_by_id('kw') 
2.driver.find_element(By.ID,'kw')

(2)name定位

通过 name 属性来定位元素,定位唯一

# 找到界面上name为'sss'的单个元素,以下两种方式效果一样.
driver.find_element_by_name('sss')
driver.find_element(By.NAME,'sss')
# 找到界面上name为'sss'的所有元素,以下两种方式效果一样.
driver.find_elements_by_name('sss')
driver.find_elements(By.NAME,'sss')

(3)class name 定位

通过元素的 class 属性来定位元素,name和id在所有元素中是唯一的

# 找到界面上class为'sss'的单个元素,以下两种方式效果一样.
driver.find_element_by_class_name('sss')
driver.find_element(By.CLASS_NAME,'sss')
# 找到界面上class为'sss'的所有元素,以下两种方式效果一样.
driver.find_elements_by_class_name('sss')
driver.find_elements(By.CLASS_NAME,'sss')

(4)link_text定位

通过链接文本信息来定位,只能用于a标签

driver.find_element_by_link_text('内容')
driver.find_element(By.LINK_TEXT,'内容')

(5)partial link text 定位

对 link text 定位的补充,有些文本链接比较长,或者这些文本链接其中有一部分文本信息是动态生成的,这个时候,可以选择文本链接的一部分进行定位,只要这部分信息可以唯一的标识这个链接。

driver.find_element_by_partial_link_text('内容')
driver.find_element(By.PARTIAL_LINK_TEXT,'内容')

(6)tag 定位

通过元素的标签名来定位元素

driver.find_element_by_tag_name('内容')
driver.find_element(By.TAG_NAME,'内容')

(7)xpath定位

格式:
1.driver.find_element_by_xpath('xpath路径')
2.driver.find_elements(By.XPATH,'xpath路径')

xpath详解:
在这里插入图片描述
在这里插入图片描述

练习:

//div[@id="wraf"] #定位到id=wraf的div元素
//*[@id="wraf"] #定位到id=wraf的元素,*表示类型不限
//*[@id="wraf"]/* #定位到id=wraf的元素的所有子集元素,*表示类型不限
//*[@id="wraf"]/div #定位到id=wraf的元素的所有子集div元素
//*[@id="wraf"]//a #定位到id=wraf的元素的所有子集以及子集的子集(无论差几级)中的所有的a元素
//*[contains(@id,"kw")] #定位到id包含wraf的元素
//*[text()="wraf"] # 定位到文本内容为wraf的元素
//*[contains(text(),"wraf")] # 定位到文本内容包含wraf的元素
//*[@id="wraf" and @class="asdff"] # 定位id为wraf且class为asdff的元素

(8)css_selector定位

格式:
1.driver.find_element_by_css_selector('css路径')
2.driver.find_element(By.CSS_SELECTOR,'css路径')

css详解:
在这里插入图片描述
在这里插入图片描述

练习:

#wraf #定位id为wraf的元素
#wraf>div #定位id为wraf的元素的子集中的所有div元素
#wraf a #定位id为wraf的元素的子子孙孙集中的所有a元素
#wraf a:nth-child(2) #定位id为wraf的元素的子子孙孙集中的所有a元素,且这些a元素属于它父级的第二个子元素。

3.鼠标点击:定位元素后.click()

driver.find_element_by_id('su').click()

4.输入内容:定位元素后.send_keys(“内容”)

driver.find_element_by_id('kw').send_keys('自动化测试')

5.清空内容:定位元素后.clear()

element = driver.find_element(By.ID,'kw')
element.send_keys('自动化测试')
sleep(2)
element.clear()

6.退出浏览器

driver.quit()

7.获取页面title

s = driver.title

8.最大化浏览器窗口

driver.maximize_window()

9.等待方式

9.1 页面元素加载顺序

在这里插入图片描述

9.2 直接等待

from time import sleep
sleep(3) # 线程休眠3秒

9.3 隐式等待

driver.implicitly_wait(5)
# 在5秒内不断检测元素是否出现,出现就结束等待,执行下一步。如果5秒内没有出现就抛出异常
# 隐式等待是作用在全局的,一般放在setup中
# 隐式等待有一个缺点:因为隐式等待是针对全局的元素而言的,而每个元素的加载时间是不一样的。所以隐式等待的等待时间是不能很好的兼容所有元素。
# 使用隐式等待会有这个bug,就是元素已经出现,但不能被点击。所以导致用例失败。这是因为浏览器加载时,会先加载DOM节点,然后再加载js等静态文件,所以会出现元素已经出现,但无法点击的问题。

9.4 显示等待

格式:
# 在规定的时间内不断的调用方法1,直到方法1返回True,结束等待。超时抛出异常
WebDriverWait(driver驱动,等待时间).until(方法1)

# 在规定的时间内不断的调用方法1,直到方法1返回False,结束等待。超时抛出异常
WebDriverWait(driver驱动,等待时间).until_not(方法1)

until后的方法,selenium中有许多。我们介绍几种常用的:

  • expected_conditions.presence_of_element_located----判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见
from selenium import webdriver # 导入依赖
from time import sleep

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')

element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'kw')))
# 显式等待:直到对应的元素出现,就结束等待。并且定位到该元素

element.send_keys('selenium')
  • expected_conditions.visibility_of_element_located-----判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于 0

  • expected_conditions.presence_of_all_elements_located—判断是否至少有 1 个元素存在于 dom 树中。举个例子,如果页面上有 n 个元素的 class 都是’column-md-3’,那么只要有 1 个元素存在,这个方法就返回 True

  • expected_conditions.text_to_be_present_in_element—判断某个元素中的 text 是否 包含 了预期的字符串

  • expected_conditions.text_to_be_present_in_element_value----判断某个元素中的 value 属性是否包含 了预期的字符串

  • expected_conditions.invisibility_of_element_located----判断某个元素中是否不存在于dom树或不可见

  • expected_conditions.element_to_be_clickable—判断某个元素中是否可见并且是 enable 的,这样的话才叫 clickable

  • expected_conditions.element_to_be_selected—判断某个元素是否被选中了,一般用在下拉列表

10.action接口

10.1 简介

selenium给我们提供了两种操作浏览器控件的actions接口:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

10.2 ActionChains

(1).鼠标单击,双击,左键操作

from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest

class TestSelenium:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.get("http://sahitest.com/demo/clicks.htm")
        self.driver.implicitly_wait(5)

    def teardown(self):
        self.driver.close()

    def test_selenium(self):
        # 定位元素
        element_click = self.driver.find_element_by_xpath("//*[@value='click me']")
        element_double_click = self.driver.find_element_by_xpath("//*[@value='dbl click me']")
        element_right_click = self.driver.find_element_by_xpath("//*[@value='right click me']")

        # 创建一个action
        action = ActionChains(self.driver)

        # 给action添加需要执行的方法
        action.click(element_click) # 鼠标左键单击
        action.double_click(element_double_click) # 鼠标左键双击
        action.context_click(element_right_click) #鼠标右键点击

        # 执行action
        action.perform()

(2).鼠标移动到某个元素上

from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep

class TestSelenium:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window() #最大化窗口
    def teardown(self):
        self.driver.close()
    def test_move(self):
        self.driver.get("https://www.baidu.com/")
        # 定位元素
        ele = self.driver.find_element_by_id("s-usersetting-top")
        # 创建action
        action = ActionChains(self.driver)
        # 给action添加操作方法
        action.move_to_element(ele) # 移动到元素上,但不点击
        # 执行action
        action.perform()

(3).拖拽一个元素到另一个元素上

方法一:

from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep

class TestSelenium:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window() #最大化窗口

    def teardown(self):
        self.driver.close()

    def test_drag_drop(self):
        self.driver.get("http://sahitest.com/demo/dragDropMooTools.htm")
        # 定位元素
        drag_ele = self.driver.find_element_by_id("dragger")
        drop_ele = self.driver.find_element_by_xpath("/html/body/div[2]")
        # 创建action
        action = ActionChains(self.driver)
        # 给action添加操作方法
        action.drag_and_drop(drag_ele,drop_ele) # 拖拽并移动,传入两个参数,第一个为需要退拽的元素,第二个为释放位置的元素
        # 执行action
        action.perform()

方法二:

from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
class TestSelenium:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window() #最大化窗口
    def teardown(self):
        self.driver.close()
    def test_drag_drop(self):
        self.driver.get("http://sahitest.com/demo/dragDropMooTools.htm")
        # 定位元素
        drag_ele = self.driver.find_element_by_id("dragger")
        drop_ele = self.driver.find_element_by_xpath("/html/body/div[2]")
        # 创建action
        action = ActionChains(self.driver)
        # 给action添加操作方法
        action.click_and_hold(drag_ele) # 按下不放手
        action.release(drop_ele) # 释放鼠标
        # 执行action
        action.perform()

(4).模拟键盘操作

from selenium import webdriver
from selenium.webdriver import ActionChains
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
class TestSelenium:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window() #最大化窗口
    def teardown(self):
        self.driver.close()
    def test_keys(self):
        self.driver.get("http://sahitest.com/demo/label.htm")
        # 定位元素
        ele1 = self.driver.find_element_by_xpath("/html/body/label[1]/input")
        ele2 = self.driver.find_element_by_xpath("/html/body/label[2]/table/tbody/tr/td[2]/input")
        # 创建action
        action = ActionChains(self.driver)
        # 给action添加操作方法
        ele1.click()
        action.send_keys("ouyi1") # 输入内容
        action.send_keys(Keys.SPACE) #输入空格
        action.send_keys("ouyi2") # 输入内容
        action.send_keys(Keys.CONTROL,'a') #全选
        action.send_keys(Keys.CONTROL, 'c')  # 复制
        ele2.click()
        action.send_keys(Keys.CONTROL, 'v')  # 粘贴
        # 执行action
        action.perform()

10.3 TouchActions

注意:在web端使用TouchActions时,需要修改谷歌浏览器的启动options

(1)实现滑动

方式一:scroll_from_element----从某个元素开始滑动

from selenium import webdriver
from selenium.webdriver import ActionChains,TouchActions
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
class TestSelenium:
    def setup(self):
        # 设置谷歌的启动配置options
        option = webdriver.ChromeOptions()
        option.add_experimental_option('w3c',False) #设置谷歌启动方式不要为w3c
        self.driver = webdriver.Chrome(options=option)
        self.driver.implicitly_wait(5)
        self.driver.maximize_window() #最大化窗口
    def teardown(self):
        self.driver.quit()
    def test_touch1(self):
        self.driver.get("https://www.taobao.com/")
        # 定位元素
        ele = self.driver.find_element_by_id("J_TSearchForm")
        # 创建action
        action = TouchActions(self.driver)
        # 给action添加操作方法
        """从某个元素开始滑动。传入三个参数,第一个为开始作为滑动起点的元素,第一个为X偏移量,第三个为y偏移量"""
        action.scroll_from_element(ele,0,10000)
        # 执行action
        action.perform()

方式二:action.scroll(x偏移量,y偏移量)------从当前位置滑动指定的偏移量

action.scroll(0,1000)

11.多窗口的处理

11.1多窗口的识别

在这里插入图片描述

(1)获取当前窗口的句柄

driver.current_window_handle #返回当前的窗口句柄

(2)获取所有窗口的句柄

self.driver.window_handles # 返回一个包含所有窗口句柄的列表

11.2多窗口的切换

self.driver.switch_to_window(对应的窗口句柄) #切换到对应的窗口

12.frame处理

12.1 frame简介

在这里插入图片描述

12.2 frame的切换

在这里插入图片描述

13.selenium多浏览器的处理

我们可以将浏览器作为一个参数,传递给参数用例。来做浏览器的兼容性处理

from selenium import webdriver
from selenium.webdriver import ActionChains,TouchActions
import pytest
from time import sleep
from selenium.webdriver.common.keys import Keys
import os
class TestBroswer:
    def setup(self):
        # 获取执行测试用例时传入的broswer的值,来判断使用哪个浏览器
        broswer = os.getenv('broswer')
        if broswer == 'firefox':
            self.driver = webdriver.Firefox()
        elif broswer == 'chrome':
            self.driver = webdriver.Chrome()

        self.driver.implicitly_wait(5)
        self.driver.maximize_window()  # 最大化窗口
    def teardown(self):
        self.driver.quit()
    def test_broswer(self):
        self.driver.get("https://www.baidu.com/")
        self.driver.find_element_by_id('kw').send_keys('selenium')
        self.driver.find_element_by_id('su').click()

这样我们在执行测试用例时,只需要传入broswer对应的值,就可以使用对应的浏览器了。

broswer=chrome pytest -v test_selenium.py

14.selenium执行javascript

在自动化测试中,经常会有一些组件无法定位到。这时需要使用js来进行定位操作。因此我们可以所以selenium中提供的接口来执行JavaScript命令。

14.1 selenium执行JavaScript命令

方式一:执行js命令:driver.execute_script(‘js命令’)

from selenium import webdriver
from time import sleep
class TestJs:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window()
    def teardown(self):
        self.driver.quit()
    def test_js(self):
        self.driver.get("https://www.baidu.com/")
        # 使用selenium执行js脚本
        self.driver.execute_script('alert("selenium")')
        sleep(3)

方式二:执行js命令,并将结果返回给selenium代码:driver.execute_script(‘return js命令’)

from selenium import webdriver
from time import sleep
class TestJs:
    def setup以上是关于python自动化web自动化:2.web自动化工具selenium讲解的主要内容,如果未能解决你的问题,请参考以下文章

Django 测试客户端不会自动序列化工厂

请问python主要应用领域是啥,哪方面用的多了.

自动化测试框架总结

自动化测试框架总结

Python的主要应用领域都有哪些

自动化测试框架总结