WebDriver+Selenium实现浏览器自动化

前言

Selenium是一款可以自动化操作浏览器的开源项目,最初的目的是浏览器功能的自动化测试,但是随着项目的发展,人们根据它的特性也用来做一些更多的有意思的功能而不仅仅是UI的自动化测试工具。就像Selenium官方网站上描述的那样,Selenium可以自动化操纵浏览器。完了!你想用它的能力做什么事情完全取决于你。

使用场景

针对浏览器的自动化测试有三个场景:

  • Selenium WebDriver:如果您想创建健壮的、基于浏览器的回归自动化套件和测试、在许多环境中扩展和分发脚本,那么您需要使用 Selenium WebDriver,它是一组特定于语言的绑定来驱动浏览器——这就是它的本意驱动的
  • Selenium IDE:如果您想创建快速的错误重现脚本,创建脚本以帮助自动化辅助探索性测试,那么您想使用 Selenium IDE; Chrome、Firefox 和 Edge 插件,可以对与浏览器的交互进行简单的记录和回放
  • Selenium Grid:如果您想通过在多台机器上分发和运行测试来扩展并从一个中心点管理多个环境,从而可以轻松地针对大量浏览器/操作系统组合运行测试,那么您需要使用 Selenium Grid

原理

早期的Selenium目的是实现web应用的UI自动化测试,实现方式是通过三方的服务器注入js达到控制浏览器行为的目的,核心的组件叫Selenium-RC(Remote Control)
包含两个部分:

  • 客户端侧的编写控制浏览器逻辑的库
  • 实现控制浏览器启动和关闭的服务器

架构如下

image.png

这种架构被证明是复杂的,而且有诸多限制,比如:

  • 复杂的架构
  • 执行测试脚本非常耗时,因为 Selenium RC 使用 JavaScript 命令作为浏览器的指令。这会导致性能下降
  • API不太面向对象
  • 不支持 Headless HTMLUnit 浏览器(不可见的浏览器)

Selenium RC 的局限性导致了新的自动化框架 Selenium WebDriver 的开发。在 2006 年引入 WebDriver 后,RC 中出现的复杂问题可以得到解决和解决
Selenium 结合WebDriver简化了浏览器的控制行为,将中间环节的服务器去掉,直接在系统层级本地化控制浏览器,优化后的架构如下:


image.png

环境准备

如果你不想在编码层实现你的功能,可以下载Selenium IDE插件,支持录制回放,过程脚本导出。

image.png

如果需要通过代码实现更多灵活自定义功能,建议使用python,环境准备
python3、pip3

brew install python3

selenium

pip3 install selenium

install browser drivers
设置您的系统以允许浏览器自动化。
通过 WebDriver,Selenium 支持市场上所有主流浏览器,例如 Chrome/Chromium、Firefox、Internet Explorer、Edge、Opera 和 Safari。在可能的情况下,WebDriver 使用浏览器的内置自动化支持来驱动浏览器


image.png

开发

First Script

通过webdriver实现控制浏览器自动访问功能


def test_eight_components():
    driver = webdriver.Chrome()
    
    driver.get("https://google.com")
    
    title = driver.title
    assert title == "Google"
    
    driver.implicitly_wait(0.5)
    
    search_box = driver.find_element(by=By.NAME, value="q")
    search_button = driver.find_element(by=By.NAME, value="btnK")
    
    search_box.send_keys("Selenium")
    search_button.click()
    
    search_box = driver.find_element(by=By.NAME, value="q")
    value = search_box.get_attribute("value")
    assert value == "Selenium"
    
    driver.quit()

WebDriver API

webDriver操纵浏览器的API大致可以分为两个部分,控制浏览器行为的比如,打开、关闭、前进、后退、刷新等和控制页面元素的如,点击、输入、获取元素内容等

浏览器

获取浏览器信息

// title
driver.getTitle(); 
// url
driver.getCurrentUrl();

导航

//打开
driver.get("https://selenium.dev");

//跳转
driver.navigate().to("https://selenium.dev");

// 后退
driver.navigate().back();

// 前进
driver.navigate().forward();

// 刷新
driver.navigate().refresh();

弹框

//根据条件找到页面中的弹框并点击
driver.findElement(By.linkText("See an example alert")).click();

//等待弹框展示并保存到变量中
Alert alert = wait.until(ExpectedConditions.alertIsPresent());

//获得弹框内容文本
String text = alert.getText();

//点击确定按钮
alert.accept();
  

Alert、Confirm、Prompt功能类似
Cookies
可以支持cookies的添加删除操作

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class addCookie {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("http://www.example.com");

            // Adds the cookie into current browser context
            driver.manage().addCookie(new Cookie("key", "value"));
        } finally {
            driver.quit();
        }
    }
}

Frames
支持针对Frames内元素的获取及操作
Windows
WebDriver 不区分窗口和选项卡。如果您的站点打开一个新选项卡或窗口,Selenium 将允许您使用窗口句柄来处理它。每个窗口都有一个唯一标识符,该标识符在单个会话中保持不变。您可以使用以下方法获取当前窗口的窗口句柄:

driver.getWindowHandle();

元素

识别和使用DOM中的元素
大多数人的 Selenium 代码大部分都涉及使用 Web 元素。这部分功能和写前端代码的document.getElementById作用差不多,思想比较简单,就是找到页面中的元素然后执行模拟用户行为的操作
支持绝对定位和相对定位的策略,针对复杂页面ID,Tag,Class不好定位的情况可以使用xPath方式,非常灵活,其实也不用死记硬背,当某元素不好定位时,可以去官网查API的方式去实现
相对定位

image.png

def relative():
    # Above
    email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
    # Below
    password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
    # Left of
    cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
    # Right of
    submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
    # Near
    email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
    # Chaining relative locators
    submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})

传统定位

<ol id="vegetables" style="margin-top: 20px">
      <li class="potatoes">potatoes</li>
      <li class="onions">onions</li>
      <li class="tomatoes"><span>Tomato is a Vegetable</span></li>
    </ol>
    <ul id="fruits">
      <li class="bananas"></li>
      <li class="apples"></li>
      <li class="tomatoes"><span>Tomato is a Fruit</span></li>
     </ul>

def finders():
    # Evaluating entire DOM
    vegetable = driver.find_element(By.CLASS_NAME, "tomatoes")
    print(vegetable)
    # Evaluating a subset of the DOM
    fruits = driver.find_element(By.ID, "fruits")
    fruit = fruits.find_elements(By.CLASS_NAME, "tomatoes")
    print(fruit)
    # Optimized locator
    fruit = driver.find_element(By.CSS_SELECTOR, "#fruits .tomatoes")
    fruit2 = driver.find_element(By.CSS_SELECTOR, "ul .tomatoes")
    print(fruit == fruit2) # True
    # All matching elements
    plants = driver.find_elements(By.TAG_NAME, "li")
    print(plants)
    # Get all the elements available with tag name 'p'
    elements = driver.find_elements(By.TAG_NAME, 'span')
    for e in elements:
        print(e.text)


def xPath():
    ol = driver.find_element(By.XPATH, "/html/body/div/div/ol[1]")
    ol2 = driver.find_element(By.XPATH, "//ol[1]")
    ol3 = driver.find_element(By.XPATH, "//ol[@id='vegetables']")
    print(ol == ol2) # True
    print(ol == ol3) # True
    onions = driver.find_element(By.XPATH, "//ol[1]/li[2]")
    print(onions.text)

交互
5种基本命令:

  • click(任意元素)
  • send keys(仅用于文本块和内容可编辑元素)
  • clear(同上)
  • submit (form 元素)
  • select (选择列表元素)

获取元素信息

image.png

总结

本次分享介绍了Selenium使用场景,简单原理和一些的基础用法。并列举了一个小例子。掌握以上内容,你已经可以实现基本的UI自动化测试了。另外可以做一些爬虫和自动化操纵浏览器的工具需求就需要根据个人场景化定制了,只要你有“懒”的天性,相信一定会找到挺多有意思场景使用去使用它。

参考

https://www.selenium.dev/
https://www.browserstack.com/guide/selenium-rc-tutorial

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容