Selenium介绍

官方文档:https://www.seleniumhq.org

简单来说就是web自动化测试框架,可以在不同类型的浏览器上测试.

a4b73b470b274ef41134a87f66670c2c.png

webdriver系统架构

3beb4135a4fb3a3d4d34908f40784715.png

环境搭建

  • python2.7或者3.6

  • pycharm编辑器

  • chrome浏览器

  • chrome webdriver

安装selenium

https://pypi.org/project/selenium/

pip install selenium

chrome webdriver选择版本

查看chrom浏览器的版本,需要下载其对应版本的chrome webdriver.

860ac67f85a0a22a4591375ed6f14e6c.png

下载对照表
https://sites.google.com/a/chromium.org/chromedriver/downloads

e0da361c257ac8bfc96c0039d56610e6.png

不同浏览器的driver

  • browser = webdriver.Chrom()

  • browser = webdriver.Firefox()

  • browser = webdriver.Safari()

  • browser = webdriver.Ie()

第一个demo

使用chrome浏览器打开百度

from selenium import webdriverbrowser = webdriver.Chrome()browser.get('http://www.baidu.com/')

2a808cbdfbc81422708289e05494ed92.png

报错提示需要指定"chromedriver"路径.

解决方案下载对应版本的chromedriver,代码改动如下:

from selenium import webdriverbrowser = webdriver.Chrome(executable_path="/Users/xinxi/PycharmProjects/selenium_demo/webdriver/chromedriver_mac")# executable_path来指定chromedirver路径browser.get('https://www.baidu.com')

指定代码,会启动一个chrome浏览器并且打开百度首页.

chromeOptions

  • chromeOptions 是一个配置 chrome 启动是属性的类。通过这个类,我们可以为chrome配置如下参数(这个部分可以通过selenium源码看到):

  • 设置 chrome 二进制文件位置 (binary_location)

  • 添加启动参数 (add_argument)

  • 添加扩展应用 (addextension, addencoded_extension)

  • 添加实验性质的设置参数 (addexperimentaloption)

  • 设置调试器地址 (debugger_address)

设置不弹出自动化提示

49486ab3539c18d963547371a3e2eb73.png

chrome_options = webdriver.ChromeOptions()chrome_options.add_argument('disable-infobars')

后台运行

option = webdriver.ChromeOptions()option.add_argument('headless')

伪装移动设置

options = webdriver.ChromeOptions()options.add_argument('user-agent="Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20"')

设置开发者模式

options = webdriver.ChromeOptions()options.add_experimental_option('excludeSwitches', ['enable-automation'])self.browser = webdriver.Chrome(executable_path=chromedriver_path, options=options)

禁止加载图片

chrome_options = webdriver.ChromeOptions()prefs = {"profile.managed_default_content_settings.images": 2}chrome_options.add_experimental_option("prefs", prefs)

元素定位

web页面所有的元素最终都是以html格式展示.

使用chrome浏览器,右键查看页面元素.把鼠标定位到元素上,页面会自动定位到页面上.

9a03bd6fe728c1f5da7b9a00c82cd570.png

所以做web自动化的关键点是如何操作这些元素,模拟点击、滑动、长按等操作.

selenium提供了八种元素定位方式.

name定位

9573654bcc783b7949bac39b7fb6838c.png

browser.find_element_by_name("tj_trnews").click()

id定位

804f48ab218c46803870b0b3960bab80.png

browser.find_element_by_id("result_logo").click()

class定位

cccc2e63421917d08920c372707f8e11.png

browser.find_element_by_class_name("mnav").click()

link text定位

1c2831141742385bc17a557cc370e0f2.png

browser.find_element_by_link_text("地图").click()

xpath定位

browser.find_element_by_xpath('//*[@id="result_logo"]').click()

css定位

browser.find_element_by_css_selector('#form').click()

partial link text定位

通过链接文本的部分匹配来标识元素

browser.find_element_by_partial_link_text("地").click()

tag name定位

使用h1、a、span这种标签定位.

bcd5b3e9649fb9c0682e7a848e871c20.png

browser.find_element_by_tag_name("span").click()

定位选择顺序

id > class > name > link_text > xpath > css

frame切换

是HTML元素,它定义了一个特定区域,另一个HTML文档可以在里面展示.

<html><frameset cols="25%,50%,25%"><frame src="/example/html/frame_a.html"> <frame src="/example/html/frame_b.html"> <frame src="/example/html/frame_c.html">frameset> html> 

ead846f8955085ac26970018758d7158.png

由此可见不同的frame包含不用的元素在里边. douban⽹⾸⻚为例,通过元素检查登录区域是一个frame区域

0b25728c3ace63e7450fcbcfc4d3ba80.png

用⾃动化脚本点击"密码登录"按钮,代码如下:

from selenium import webdriverbrowser = webdriver.Chrome(executable_path="/Users/xinxi/PycharmProjects/selenium_demo/webdriver/chromedriver_mac") # executable_path来指定chromedirver路路径browser.get("https://www.douban.com")print("登录douban")browser.find_element_by_class_name('account-tab-account').click()print("点击密码登录")

错误提示如下:

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:{"method":"class name","selector":"account-tab-account"}

修改代码如下:

browser.switch_to.frame(browser.find_elements_by_tag_name("iframe")[0]) print("切换frame") browser.find_element_by_class_name('account-tab-account').click() print("点击密码登录")

此时代码运行正常,说明点击"元素"之前说明需要切换到该frame上. selenium提供了了switch_to.frame方法 用法如下:

driver.switch_to.frame('frame_name') # 使⽤用名字driver.switch_to.frame(0) # 使⽤用名字 # 使⽤用位置序号 driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0]) # 使⽤用标签序号

windows切换

在web⻚页⾯面上经常有点击一个页⾯后,另外打开一个新窗口.是因为html中target参数是"_bank"控制.

26be283335cbee53d830f5726394049c.png

所以在做⾃动化测试过程中,点击跳转以后.页⾯句柄还在当⻚面,所以不能点击跳转以后的页面元素. 所以此时需要切换windows,selenium提供了了switch_to.frame⽅法 

⽤法如下:

driver.switch_to.window('main') window的名字

代码如下:

from selenium import webdriverbrowser = webdriver.Chrome(executable_path="/Users/xinxi/PycharmProjects/selenium_demo/webdriver/chromedriver_mac") # executable_path来指定chromedirver路路径browser.get("https://www.douban.com")print("登录douban")browser.find_element_by_class_name("lnk-book").click() print("点击读书")handles_list = browser.window_handles print(handles_list) browser.switch_to.window(str(handles_list[-1])) print("切换窗⼝口")if browser.current_window_handle == str(handles_list[-1]): print("切换窗⼝口成功...")

等待

等待的⽬目的主要是为了页面加载完成才点击元素,避免找不到元素的现象. 一共有三种等待:

硬编码等待

time.sleep(1) 不推荐

全局隐示等待

browser.get("https://www.douban.com") print("登录douban")browser.implicitly_wait(10) # 会等待每个元素最⼤大时间10s browser.find_element_by_class_name("lnk-book").click() print("点击读书")

显示等待

WebDriverWait(browser, 5).until(EC.presence_of_element_located((By.CLASS_NAME, "lnk-book"))).click() # 显示等待lnk-book 5s

使⽤方式:显示等待 > 全局隐示等待 > 硬编码等待

常用方法

获取窗口大小

print browser.get_window_size() # 获取窗⼝口⻚页⾯面当前⾼高和宽

获取cookies

print(browser.get_cookies())

设置网络

print(browser.set_network_conditions(                offline=False,                latency=5,  # additional latency (ms)                download_throughput=500 * 1024,  # maximal throughput                upload_throughput=500 * 1024)  # maximal throughput)            )

获取title

print(browser.title)

获取页面元素

print(browser.page_source)

获取页面url

print(browser.current_url)

窗口放大

browser.maximize_window()

窗口缩小

browser.minimize_window()

设置窗口大小

browser.set_window_size(300,300)

向前

browser.forward()

后退

browser.back()

滑动

#滑到底部 js="window.scrollTo(0,document.body.scrollHeight)" browser.execute_script(js)

滑动解锁

演示网站:https://www.helloweba.net/demo/2017/unlock/

f41b275d25e81e15886acd1a4c49b306.png

#获取拖动条dragger = browser.find_elements_by_class_name("slide-to-unlock-handle")[0]#获取拖动条进度条长度dragger_text = browser.find_elements_by_class_name("slide-to-unlock-bg")[0]x = dragger_text.location["x"]action = ActionChains(browser) #鼠标左键按下不放action.click_and_hold(dragger).perform()#平行移动大于解锁的长度的距离try:    action.drag_and_drop_by_offset(dragger,x, 0).perform()    print("滑动...")except Exception as e:    print("faild")

4e73ef33786fb520aebe3d0acf93b6ca.png

关闭弹框

c9ded39131924ef3847f6f4a28acfb45.png

time.sleep(10)try:    tt = browser.switch_to_alert()    print("打印警告框提示...")except Exception as e:    print("faild")success_text = tt.textprint(success_text)tt.accept()

截图

保存截图

browser.save_screenshot("/Users/xinxi/PycharmProjects/selenium_demo/screen_folder/截图.png")

图片流截图

sc_str = browser.get_screenshot_as_png()sc_path = "/Users/xinxi/PycharmProjects/selenium_demo/screen_folder/截图.png"with open(sc_path,"w") as f:    f.write(sc_str)

base64截图

sc_str = browser.get_screenshot_as_base64()html_tmp = """

这是一个截图

""".format(sc_str)html_path = "/Users/xinxi/PycharmProjects/selenium_demo/screen_folder/截图.html"with open(html_path,"w") as f: f.write(html_tmp)

2bc85e2b655fec6151069e4593f84f35.png

参数化

参数化的目的是解决不同输入参数,测试同一条测试用例,检验预期结果的差异性

安装:pip install parameterized

文档地址:https://github.com/wolever/parameterized

实例:搜索不同名称的书籍

 @allure.story("读书-搜索")    @parameterized.expand([["java"], ["python"], ["php"], ])    def test_book_serach(self, arg1):        '''        首页参数化搜索        :param arg1:        :param arg2:        :return:        '''        print("test_book_serach")        self.home_page.home_serach()        self.book_page.serach_book(arg1)
安装: pip install ddt

文档地址:https://ddt.readthedocs.io/en/latest/example.html

实例:搜索不同名称的书籍

import unittestfrom ddt import ddt,data,unpack@ddtclass MyTesting(unittest.TestCase):    @data(["java"], ["python"], ["php"])    @unpack    def test_serach(self,value):        print(value)

单元测试框架

unittest

官方教程地址: https://docs.python.org/3/library/unittest.html

pytest

官方教程地址: https://pytest.org/latest/contents.html

nose2

nose框架使用没有unittest和pytest多,用法也比较类似.

详见文档:https://docs.nose2.io/en/latest/getting_started.html

断言

unitest

unitest的断言,需要类继承unittest.TestCase

pytest

pytest的断言,使用assert关键字,assert可以使用直接使用“==”、“!=”、“”、“>=”、"<=" 等符号来比较相等、不相等、小于、大于、大于等于和小于等于.

import pytestclass Testpytest():    def test_assert_eq(self):        assert 1 == 1    def test_assert_ne(self):        assert 1 != 1    def test_assert_less(self):        assert 1 >=1

Page Objects

使用页面对象模式的好处:

  • 创建可在多个测试用例之间共享的可重用代码

  • 减少重复代码的数量

  • 如果用户界面发生更改,则修复程序只需要在一个位置进行更改

PO原则

https://github.com/SeleniumHQ/selenium/wiki/PageObjects
  • 公共方法表示页面提供的服务

  • 尽量不要暴露页面的内部

  • 页面一般不做断言

  • 方法返回其他PageObjects

  • 无需代表整个页面都建模

  • 针对相同动作的不同结果被建模为不同方法

selenium的po

https://selenium-python.readthedocs.io/page-objects.html

page-objects

安装:pip install page_objects

相关介绍

https://github.com/eeaston/page-objectshttps://page-objects.readthedocs.io/en/latest/tutorial.html#a-simple-page-obje

实例:

#!/usr/bin/env python# -*- coding: utf-8 -*-import time,sys,unittest,osfrom page_objects import PageObject, PageElementfrom selenium import webdriverclass LoginPage(PageObject):        '''        登录页面        '''        logintab = PageElement(class_name='account-tab-account')        username = PageElement(id_='username')        password = PageElement(name='password')        login = PageElement(link_text='登录豆瓣')class TestLogin(unittest.TestCase):     def setUp(self):             PATH = lambda p: os.path.abspath(                     os.path.join(os.path.dirname(__file__), p)             )             chromedriver = PATH("../webdriver/chromedriver_mac")             print(chromedriver)             driver = webdriver.Chrome(                     executable_path=chromedriver)             page = LoginPage(driver)             page.get("https://www.douban.com")             driver.implicitly_wait(5)             global driver,page     def test_login(self):             driver.switch_to.frame(0)             print("切换frame")             page.logintab.click()             page.username.send_keys("11111")             page.password.send_keys("11111")              page.login.click()             assert page.username.text == 'secret'if __name__ == '__main__':    unittest.main()

报告

报告主要目的记录成功、失败数量,错误日志,失败截图.

html-testRunner

pip install html-testRunner

报告展示:

4fb034cfc183a2be0ea271792df0a767.png

带错误截图的报告:

73831e07fd4c4f1bc75565179be0fccd.png

allure报告

 当下比较流行的自动化测试报告,官方地址: http://allure.qatools.ru

2ee89eee2b69d79020970cdbba822c65.png

自定义报告

d5750882bce98eff7795aa3e4debcdfb.png

jenkins持续集成

使用Allure作为报告展示

安装插件allure-jenkins-plugin

f0c5150afa7cc669f0c4105e691a450c.png

进入系统管理-全局工具配置-Allure Commandline

4739c6224a661a72309379c480ce9e55.png

创建自动化job

设置allure报告地址

43b22eab48d420939d141d934472afcc.png

构建shell

0b93aa3bb9c2053ba09c89b20742900f.png

构建历史

6f2ff352c4bba394d5c1fbe746c21328.png

selenium分布式

官方文档:https://github.com/SeleniumHQ/selenium/wiki/Grid2

下载selenium-server-standalone-3.141.59.jar

启动hub

java -jar selenium-server-standalone-3.141.59.jar -role hub -port 4455

93b6c915f72096f3162f02c9a8bbdcaa.png

启动node

java -Dwebdriver.chrome.driver="/Users/xinxi/PycharmProjects/selenium_demo/webdriver/chromedriver_mac" -jar selenium-server-standalone-3.3.1.jar -role node -port 5555 -hub http://192.168.56.1:4455/grid/registe

55945ebb78e8853ff4c2e5a373b98314.png

查看节点log日志

http://localhost:4455/grid/console

7ae5bcb180f87c9fd301586dde085b4c.png

多node测试

ef3b84e628dfd928848c59c4c940f502.png

小结

本文主要介绍了Selenium环境搭建、元素定位、截图、切换frame、po、集成框架、报告、持续集成.

demo代码地址: https://github.com/xinxi1990/Selenium_Demo
Logo

开源、云原生的融合云平台

更多推荐