前端自动化测试漫长路之——Selenium初探
引言
最近想解决前端开发或测试中的两个问题:一是界面UI的布局适配,能否在测试的过程中,通过命令操作真机打开相应页面然后截屏,通过对图片识别分类,发现有问题的图片,然后及时修复;二是页面性能分析,很多时候页面只能在指定的Webview中使用,能否直接通过命令打开指定的页面,分析页面在真实APP中的性能,并生成报告。这两个问题的前提就是通过命令直接操作手机App,带着问题找线索,于是我就结识了Selenium
,下面将结合实例和大家分享一下。
Selenium是什么?
先看一下官网的解释:
Selenium automates browsers. That's it! What you do with that power is entirely up to you. Primarily, it is for automating web applications for testing purposes, but is certainly not limited to just that. Boring web-based administration tasks can (and should!) be automated as well.
Selenium has the support of some of the largest browser vendors who have taken (or are taking) steps to make Selenium a native part of their browser. It is also the core technology in countless other browser automation tools, APIs and frameworks.
从上面的话我们可以知道3个点:
- 利用Selenium可以自动化操作浏览器,来实现web程序的自动化测试;
- Selenium是一个综合性的项目,提供了提供了不同语言版本的类库和工具,来支持浏览器的自动化;
- 主流浏览器基于W3C规定的的Web Driver规范,提供了相应的Web Driver,而标准的主要技术支持来源于Selenium项目。
一图胜千言,Selenium在自动化测试中扮演的角色如下图所示:
Selenium如何用?
我们的诉求是通过脚本控制本地和手机上的浏览器,甚至APP中的Webview,Selenuim正好提供了WebDriver API供我们使用。从上面可以知道Selenium支持多种语言,如python、go、javascript等,对于前端而言,首选当然是javascript。以下是相关的操作步骤:
环境准备
该环节主要是两步:
- 在项目中下载selenium-webdriver
npm install selenium-webdriver --save
- 下载浏览器提供的WebDriver,并将该命令文件放置在系统变量PATH下
我使用的是chrome的WebDriver,针对不同的chrome版本,需要下载不同版本的WebDriver,否则程序会报错。网上有好心人已经整理出了chrome的WebDriver与chrome的版本映射表,可以点击查看。
代码编写
selenium-webdriver的说明文档相当的赞,在selenium-webdriver包的目录下有几个文件:chrome.js、edge.js、ie.js、phantom.js等,这些都是selenium-webdriver针对不同的浏览器的webdriver的调用做了封装,打开chrome.js,在文件的开头有详细的文档说明。
chrome.js中提到了3种使用场景:分别是Headless Chrome、Customizing the ChromeDriver Server、Working with Android。而我需要的场景就是Working with Android。
实例代码如下:
let chrome = require('selenium-webdriver/chrome');
let {Builder} = require('selenium-webdriver');
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.androidPackage('com.example')
.androidActivity('com.example.Activity'))
.build();
其中需要要点就是指定要操作的浏览器类型、APP包的名字、android程序的Activity名字。一般webview的内核都是基于webkit的,指定浏览器类型为chrome即可,APP的包名和Activity名字可以通过命令工具aapt获取,关于aapt的详细介绍可以参考这篇博客。
通过以上两步,就可以通过node执行相应的js文件,实现通过命令来控制APP了,这里是几个我测试的demo,供大家下载。
selenium-webdriver运行原理
上面的操作涉及到了两个核心,即浏览器提供的webdriver和浏览器(chrome/chromium)。selenium-webdriver的作用就是利用webdriver将浏览器启动起来,并实现一系列自动操作。但究竟webdriver和浏览器是怎样一个协同关系呢,从chrome.js文件的注释中可以找到一些线索。
By default, every Chrome session will use a single driver service, which is started the first time a Driver instance is created and terminated when this process exits. The default service will inherit its environment from the current process and direct all output to /dev/null. You may obtain a handle to this default service using getDefaultService getDefaultService() and change its configuration with setDefaultService setDefaultService().
从上面可以知道,selenium-webdriver先通过webdriver启动了一个driver service,该service又启动chrome,分别起在不同的端口。
通过查阅资料,可以知道driver service在开启chrome的同时,为chrome安装了一个Chrome Automation Extension
扩展程序,该扩展程序的描述是:Exposes extension APIs for automating Chrome
,通过查看其源码,可以看到launchApp、getWindowInfo等函数,主要是提供了一些操作chrome的相关方法。
一图胜千言,selenium-webdriver的工作原理如下图所示,该图来源于网络:
Tips:
上面知道了driver service与chrome之间的关系,知道默认情况下driver service的生命周期和测试的Chrome session是同步的,意味着每次测试都需要开启一个driver service,如果频繁的开启和关闭service,势必会造成资源浪费。
针对这个情况,官方的描述是这样的:
The ChromeDriver class starts the ChromeDriver server process at creation and terminates it when quit is called. This can waste a significant amount of time for large test suites where a ChromeDriver instance is created per test.
官方针对该情况提出了两个解决办法:
- Start the ChromeDriver server separately before running your tests, and connect to it using the Remote WebDriver.
即测试之前先单独启动driver server,然后使用Remote WebDriver连接上driver server所在的端口。官方提供了一个python的示例:
import time
from selenium import webdriver
import selenium.webdriver.chrome.service as service
service = service.Service('/path/to/chromedriver')
service.start()
capabilities = {'chrome.binary': '/path/to/custom/chrome'}
driver = webdriver.Remote(service.service_url, capabilities)
driver.get('http://www.google.com/xhtml');
time.sleep(5) # Let the user actually see something!
driver.quit()
- Use the ChromeDriverService. This is available for most languages and allows you to start/stop the ChromeDriver server yourself.
可自己创建一个driver,同时为这个driver指定相应的service。这样不仅可以为driver提供个性化的服务(如log日志),还可以控制service的生命周期。
代码如下:
let chrome = require('selenium-webdriver/chrome');
let service = new chrome.ServiceBuilder()
.loggingTo('/my/log/file.txt')
.enableVerboseLogging()
.build();
let options = new chrome.Options();
// configure browser options ...
let driver = chrome.Driver.createSession(options, service);
小结
前端自动化测试的道路是漫长的,对selenium的挖掘才刚刚开始。本文并没有解决引言中提到的两个问题,selenium-webdriver只是解决了第一步,即通过命令行来操作app,后面将继续学习,继续总结分享。
前端自动化测试漫长路之——Selenium初探的更多相关文章
- 前端自动化测试工具doh学习总结(二)
一.robot简介 robot是dojo框架中用来进行前端自动化测试的工具,doh主要目的在于单元测试,而robot可以用来模仿用户操作来测试UI.总所周知,Selenium也是一款比较流行的前端自动 ...
- 前端自动化测试工具doh学习总结(一)
前言 项目中需要用到前端自动化测试,自己被当作一个探针研究了下目前用的比较多的web自动化测试工具.一开始研究的是的selenium,但由于项目使用了大量的dijit控件,写起testCase来很费劲 ...
- web前端自动化测试/爬虫利器puppeteer介绍
web前端自动化测试/爬虫利器puppeteer介绍 Intro Chrome59(linux.macos). Chrome60(windows)之后,Chrome自带headless(无界面)模式很 ...
- 自动化测试Java一:Selenium入门
From: https://blog.csdn.net/u013258415/article/details/77750214 Selenium入门 欢迎阅读Selenium入门讲义,本讲义将会重点介 ...
- Selenium自动化测试Python一:Selenium入门
Selenium入门 欢迎阅读Selenium入门讲义,本讲义将会重点介绍Selenium的入门知识以及Selenium的前置知识. 自动化测试的基础 在Selenium的课程以前,我们先回顾一下软件 ...
- 自动化测试 python2.7 与 selenium 2 学习
windows环境搭建 # 下载 python[python 开发环境] http://python.org/getit/ # 下载 setuptools [python 的基础包工具]setupto ...
- 我的web前端自学之路-心得篇:我为什么要学习web前端?
时光如流水,转眼间,自己已经是大三的学长了,看着一个个学弟学妹,心中有种莫名的感觉,很怀念大学的前两年时光,但也很憧憬着自己的未来,自己将要去经历很多从未经历的事.我是我们学校信科院的一名学生,在编程 ...
- Web前端自动化测试Cypress实践总结
本文主要首先主要介绍了什么是自动化测试,接着对常用的自动化测试框架进行了对比分析,最后,介绍了如果将自动化测试框架Cypress运用在项目中. 一.自动化测试概述 为了保障软件质量,并减少重复性的测试 ...
- 菜鸟学自动化测试(八)----selenium 2.0环境搭建(基于maven)
菜鸟学自动化测试(八)----selenium 2.0环境搭建(基于maven) 2012-02-04 13:11 by 虫师, 11419 阅读, 5 评论, 收藏, 编辑 之前我就讲过一种方试来搭 ...
随机推荐
- Asp.net MVC4高级编程学习笔记-模型学习第四课基架与模型绑定20171027
MVC模型 一.构建基架. MVC中的基架可以为应用程序提供CURD各种功能生成所需要的样板代码.在添加控制器的时候可以选择相应的模板以及实体对象来生成相应的模板代码. 首先定义一个模型类如下所示: ...
- Android插件化-RePlugin项目集成与使用
前言:前一段时间新开源了一种全面插件化的方案-- RePlugin,之前一种都在关注 DroidPlugin 并且很早也在项目中试用了,但最终没有投入到真正的生产环节,一方面是项目中没有特别需要插件化 ...
- 2016-2017 ACM-ICPC, Asia Tsukuba Regional Contest D Hidden Anagrams
题目链接:http://codeforces.com/gym/101158/attachments /* * @Author: lyucheng * @Date: 2017-10-21 12:20:0 ...
- HDU 6069 Counting Divisors
Counting Divisors Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Oth ...
- Day1作业-模拟登录
# /usr/bin/env python# -*- coding: utf-8 -*-# Author:jenvid.yangimport getpassimport shutiluserspwd ...
- .Net高级进阶,在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码?
本文将通过场景例子演示,来通俗易懂的讲解在复杂的业务逻辑下,如何以最简练的代码,最直观的编写事务代码. 通过一系列优化最终达到两个效果,1.通过代码块来控制事务(分布式事务),2.通过委托优化Tran ...
- 阿里云RDS for SQL Server使用的一些最佳实践
了解RDS的概念 这也是第一条,也是最重要的一条,在使用某项产品和服务之前,首先要了解该产品或服务的功能与限制,就像你买一个冰箱或洗衣机,通常也只有在阅读完说明书之后才能利用起来它们的所以功能,以及使 ...
- javascript 二维(多维)数组的复制问题
最近在项目中遇到一个动画暂停的效果,需要在动画停止的时候检测当前坐标和已经运行的时间,从而调节时间轴为再次运行时加速. 但是在数组保存方面折腾了半天. var orbitArray = [], lin ...
- JavaScript核心参考
Array 方法 concat() 把元素衔接到数组中. every() 测试断言函数是否对每个数组元素都为真. filter() 返回满足断言函数的数组元素. forEach() 为数组的每一个元素 ...
- Lucene全文检索学习笔记
全文索引 介绍Lucene的作者:Lucene的贡献者Doug Cutting是 一位资深全文索引/检索专家,曾经是V-Twin搜索引擎(Apple的Copland操作系统的成就之一)的主要开发者,后 ...