浅谈Selenium之WebUI自动化

一、自动化测试

自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常,在设计了测试用例并通过评审之后,由测试人员根据测试用例中描述的规程一步步执行测试,得到实际结果与期望结果的比较。在此过程中,为了节省人力、时间或硬件资源,提高测试效率,便引入了自动化测试的概念。

二、分层自动化

在这里插入图片描述

2.1、单元测试(unit)

它可以通过junit或者unittest框架,模拟各种异常场景,外部依赖最少,且可以做到测试粒度到最小的一种测试方法。也因为依赖少,可方便随时随地执行,也让问题排查很简单。这是一切测试的地基。

2.2、接口测试(service)

这里要求测试人员对系统的结构和系统间的调度非常清楚,同时要了解接口逻辑关系,否则接口测试代码很容易遗漏一些异常场景。 这一层由于含有一些业务逻辑和多接口的一个集成,所以相对单元测试来说,多了一些外界依赖,导致问题定位不会有单元测试层那么准确。因此投入会比单元测试 多一些。

2.3、页面测试(ui)

是常见的黑盒自动化测试场景。它最接近用户真实场景,也容易发现问题,但它的实现成本最高且太容易受外部依赖,影响脚本成功率,所以处在金字塔的顶端,但它不是金字塔的全部。自动化测试的劣势,其中80%都是因为ui自动化。

三、自动化测试框架

3.1、Robot FrameWork

Robot FrameWork是一款基于Python语言编写的自动化测试框架,具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试。

3.2、Selenium

Selenium是一个用于Web应用程序测试的工具,支持多平台,多浏览器,多语言去实现自动化测试,支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等;目前在Web自动化领域应用越来越广泛。

3.2.1、Selenium简介

在这里插入图片描述

3.2.1.1、主要功能

测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。

3.2.1.2、主要特点
  • 提供更加简单API编写自动化测试
  • 提供脚手架,快速生成自动化测试项目
  • 自动生成HTML测试报告生成
  • 自带断言方法,断言title、URL 和 text
  • 支持用例参数化
  • 支持用例失败重跑
  • 用例失败/错误截图
3.2.1.3、测试系统功能

创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。

3.2.1.4、Selenium也是一款同样使用Apache License 2.0协议发布的开源框架
  1. 支持平台:
    WebDriver支持Android和BlackBerry两个移动平台的浏览器测试。Android目前为市场占有率第一的移动平台,对于在其上面进行自动化测试,推荐Appium,Appium扩展了WebDriver的协议,支持ios平台和Android平台上的原生应用、Web应用和混合应用等。
  2. 支持浏览器:
    WebDriver 目前所支持的浏览器包括:Firefox、Chrome、IE、Edge、Opera、Safari. 为什么会选择上面几款浏览器进行支持呢?主要与浏览器的内核有关。
  3. 支持模式:
    HtmlUnit和PhantomJS是两个比较特殊的模式,我们可以把它们看作是伪浏览器,在这种模式下支持html、Java Saript等的解析,但不会真正地渲染出页面。由于不进行CSS及GUI渲染,所以运行效率上要比真实的浏览器快很多,主要用在功能性测试上面。

3.3、Selenium脚本环境配置

3.3.1、下载selenium驱动包

● 在pyhcarm中安装selenium库文件
○ file–>setting–>project…–>project intercepter–>右上角点击+号–>搜索selenium关键词–>左下角install package
● 如果安装失败报错,使用packaging_tool.py文件复制替换pycharm安装目录里面helpers文件夹文件
○ 重新搜索安装
在这里插入图片描述

3.3.2、安装chrome浏览器驱动

● 下载对应的chromedriver
http://chromedriver.storage.googleapis.com/index.html
● 与chrome浏览器版本对应
https://blog.csdn.net/huilan_same/article/details/51896672
● chromedriver.exe驱动文件发到python的根目录下
在这里插入图片描述

3.4、Selenium查找页面元素及元素操作

3.4.1、Id

find_element_by_id('id')

3.4.2、Name

find_element_by_name('name')

3.4.3、Class

find_element_by_class_name('class')

3.4.4、tagName

self.driver.find_elements_by_tag_name('tagName')[0]
#找到所有标签为input的元素,放在列表里面

3.4.5、Link

find_element_by_link_text('百度一下').click()

3.4.6、partialLink

find_element_by_partial_link_text('百度').click()
#_partial部分超链接  #百度 度一 一下

3.4.7、Css

cssSelector这种元素定位方式跟xpath比较类似,但执行速度较快,而且各种浏览器对它的支持都相当到位
css选择器常见语法:
浏览器-开发者模式-Elements选中元素-右键-copy-Copy selector

find_element_by_css_selector('Copy selector')#Copy seletor

3.4.8、Xpath

XPath是一种在XML文档中定位元素的语言,因为HTML可以看做XML的一种实现,所以Selenium用户可以使用这种强大的语言在WEB应用中定位元素

find_element_by_xpath('Copy Xpath')
#find_element_by_xpath('//标签名[@属性名1 = "属性值1" and @属性名2 = "属性值2"]')

3.4.9、元素定位选择

  1. 当页面元素有id属性时,最好尽量用id来定位。但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法。
  2. xpath很强悍,但定位性能不是很好,所以还是尽量少用。如果确实少数元素不好定位,可以选择xpath或cssSelector。
  3. 当要定位一组元素相同元素时,可以考虑用tagName或name。
  4. 当有链接需要定位时,可以考虑linkText或partialLinkText方式。

3.4.10、document.getElementsByClassName(‘class’) []

#定位充满div class页面元素的方法,id、xpath都没用的抓狂情况

js = "document.getElementsByClassName('title')[2].click();"
driver.execute_script(js)

以搜狐网(定位右上角“搜狐邮箱”)为例:
● 打开Chrome开发者工具,点击Console(控制台)标签,输入一条JavaScript语句:
○ document.getElementsByClassName(‘title’).length
● 回车查看结果,结果是4,说明整个HTML文档,有4个地方用了class=“title”。那怎么办呢?
○ 直接输入document.getElementsByClassName(‘title’),回车
○ 有四个用到class="title"的地方,把鼠标指针浮在每个元素上,并同时关注页面上的蓝色定位标志。
● 找到了!是下标为2的div.title
○ 那么结果就是document.getElementsByClassName(‘title’)[2]
● 不是要做点击操作吗?那么直接就是(python语言为例):
○ js = “document.getElementsByClassName(‘title’)[2].click();”
● JavaScript语句规定,下标一律从0开始算起;而Xpath是从1开始算起,千万别搞混淆了!

3.4.11、简单元素操作

3.4.11.1、清除文本
clear()
3.4.11.2、模拟按键输入
send_keys()
3.4.11.3、获取元素属性值
get_attribute()

3.5、浏览器事件

3.5.1、选择浏览器

#driver = webdriver.Firefox()
driver = webdriver.Chrome()

3.5.2、浏览器前进后退

driver.back()#浏览器后退
driver.forward()#浏览器前进

3.5.3、打开URL

driver.get("http://www.baidu.com")

3.5.4、刷新

driver.refresh()

3.5.5、最大化

browser.maximize_window()

3.5.6、截取当前页面

driver.get_screenshot_as_file('screenshot/shots.jpg')

3.5.7、滑动页面

#滚动页面
driver.execute_script('window.scrollBy(0,200)')
self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

#window.scrollBy(0,500)     向下滚动500个像素
#window.scrollBy(0,-500)    向上滚动500个像素
#window.scrollBy(500,0)     向右滚动500个像素
#window.scrollBy(-500,0)    向左滚动500个像素

3.5.8、关闭浏览器

driver.quit()

3.6、鼠标事件

在WebDriver中,将关于鼠标的操作封装在ActionChains类中;
perform() :执行所有的ActionChains中存储的所有行为:

move_to_element() 悬浮
context_clict() 右击
double_clict() 双击
click_and_hold() 长按
drag_and_drop() 拖拽
aLink = self.driver.find_element_by_partial_link_text('百度一下')
ActionChains(self.driver).move_to_element(aLink).perform()#鼠标hover

3.7、键盘事件

send_keys()模拟键盘输入:

from selenium.webdriver.common.keys import Keys

send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
send_keys(Keys.ESCAPE) 回退键(Esc)
send_keys(Keys.ENTER) 回车键(Enter)
send_keys(Keys.CONTROL,'a') 全选(Ctrl+A)
send_keys(Keys.CONTROL,'c') 复制(Ctrl+C)
send_keys(Keys.CONTROL,'x') 剪切(Ctrl+X)
send_keys(Keys.CONTROL,'v') 粘贴(Ctrl+V)
send_keys(Keys.F1) 键盘 F1
#……
send_keys(Keys.F12) 键盘 F12

3.8、设置元素等待

3.8.1、Selenium的隐式等待

原理:针对全局,无指定元素,是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步
隐性等待对整个driver的周期都起作用,所以只要设置一次即可

#设置隐式等待为 10 秒
driver.implicitly_wait(10)

3.8.2、sleep休眠

休眠:指定等待时间,不管元素是否存在
使当前线程进入等待,time.sleep();这种等待属于死等,很容易让线程挂掉,使程序抛异常,所以要慎用此方法

sleep(2)
time.sleep(2)

3.9、Cookie操作

有时候我们需要验证浏览器中cookie是否正确,WebDriver提供了操作Cookie的相关方法,可以读取,添加和删除cookie信息;也可通过cookie操作绕过登陆进行测试

3.9.1、WebDriver操作Cookie

get_cookies() #获得所有cookie信息。
get_cookies(name) #返回字典的key为name的cookie信息
add_cookie(cookie_dict) #添加cookie;cookie_dict指的是字典对象,必须要有name和value值
delete_cookie #删除cookie信息
delete_all_cookies()#删除所有的cookie信息

3.9.2、获取、遍历Cookie

#cookie基本操作
from selenium import webdriver
driver=webdriver.Chrome()
driver.get("http://www.csdn.net")
#获取cookie信息
cookies=driver.get_cookies()
print(cookies)
print("==="*50)
#遍历cookie
for cookie in cookies:
    print("%s===%s",(cookie["name"],cookie["value"]))
driver.quit()

3.9.3、添加删除Cookie

#添加cookie信息
#添加和修改用的是同一个函数add_cookie,如果cookie名字不存在,那么是增加,如果已存在,那么就是修改
cookie = {'domain': 'combine.jinx.corp.kuaishou.com', 'httpOnly': False, 'name': 'kuaishou.ad.ssp_ph', 'path': '/', 'secure': False, 'value': '6f6c86ddcb509b0a3d106467e7c91d3355ca'}, {'domain': 'combine.jinx.corp.kuaishou.com', 'httpOnly': True, 'name': 'kuaishou.ad.ssp_st', 'path': '/', 'secure': False, 'value': 'ChJrdWFpc2hvdS5hZC5zc3Auc3QScBlT57yuYHLBWWKXJsZtqHvtQb3Actjueso-Xj55JV7CaWXR5KJyd7mTL9EgrgK7gtY1h3Zk7RkEqUBX6c2MNJCylPqLHkbp1u3qjk7AFPrI3-I9Uypt-i3FX6naNbtregpgQ9XWsMCZKqfLVuFjtToaEscpAbxEZ84hbzlb29ZtRfqEwSIgrsZC77YqlHLwv1yO3OrBXCafjXZinc0tBnIGoAzFNbgoCjAB'}, {'domain': '.kuaishou.com', 'expiry': 1655625528, 'httpOnly': True, 'name': 'apdid', 'path': '/', 'secure': False, 'value': 'ecf8b1ed-913d-4a0d-871c-e32a3fb760ce97f8e5cf7f3c314c12ad32a444182bfd:1624089528:1'}, {'domain': 'combine.jinx.corp.kuaishou.com', 'httpOnly': False, 'name': 'cross-site-cookie', 'path': '/', 'sameSite': 'None', 'secure': True, 'value': 'bar'}, {'domain': '.kuaishou.com', 'httpOnly': False, 'name': 'userId', 'path': '/', 'sameSite': 'None', 'secure': True, 'value': '1416022050'}, {'domain': '.jinx.corp.kuaishou.com', 'expiry': 1624132728, 'httpOnly': True, 'name': 'accessproxy_session', 'path': '/', 'secure': False, 'value': 'b44f91d7-aa3c-4f09-97ab-9a05901908bb'}
driver.add_cookie(cookie)

#删除名字为username的cookie
driver.delete_cookie("username")

#删除所有cookie信息
driver.delete_all_cookies()

3.10、Page Object设计模式

3.10.1、Page Object 设计模式的优点

● 减少代码的重复
● 提高测试用例的可读性
● 提高测试用例的可维护性,特别是针对 UI 频繁变化的项目

3.10.2、Page Object使用方法

● public方法代表Page提供的功能
● 尽量不要暴露Page的内部细节
● 不要assertion
● 方法可以返回其他Page Objects
● Page Object不用代表整个页面,可以是任意一个部分
● 一样的操作,不同的结果应该分开(正确登录,错误登录)

3.10.3、定义Page Object类

● 封装共性的查找元素的方法
● 封装打开页面的逻辑
● 封装判断页面是否正确的逻辑
● 读取数据的操作封装
● 错误截图
eg:
● 定义子类:
● LoginPage RegistPage CartPage 继承自pageObject
○ 只需要定义自己特有的操作
○ LoginPage
■ 登录
■ 验证用户名是否存在
■ 记住用户名密码
○ RegistPage
■ 验证用户名是否重复
■ 注册
■ 其他数据验证
○ CartPage
■ 添加购物车
■ 删除
■ 清空
■ 修改数量

3.10.4、封装

模块描述
config配置文件,比如log.conf
data放置数据文件,比如apiUrl(放路径)、csv文件
logs放日志文件
reports生成测试报告的目录
screen_shot放置截图
pageObject封装的父类
bussinessPage个页面的类
common公共操作的代码
test_case测试用例
run_test_case用例执行文件

在这里插入图片描述

3.10.4.1、common/getDriver.py
from selenium import webdriver


def getDriver():

    driver = webdriver.Chrome()
    driver.maximize_window()
    driver.implicitly_wait(30)
    driver.refresh()

    return driver
3.10.4.2、common/MyUnit.py
class MyUnit(unittest.TestCase):
    def setUp(self):
        self.driver = getDriver()

    def tearDown(self):
        self.driver.quit()
3.10.4.3、pageObject/pageObject.py
class PageObject:

    #初始化驱动对象
    def __init__(self,driver):
        self.driver = driver

    #查找单个元素
    def findElement(self,*args):
        return self.driver.find_element(*args)

    #查找多个元素
    def findElements(self,*args):
        return self.driver.find_elements(*args)

    #获取截图  ../screenShots/描述信息_时间.png
    def getShots(self, desc):
        times = time.strftime('%X %x')
        self.driver.get_screenshot_as_file('../screenShots'+str(desc)+'_'+str(times)+'.png')

    #读取csv文件
    def getCsvData(self,csv_file,line):
        files = open(file= csv_file,mode='r',encoding='utf—8—sig')
        reader = csv.reader(files)
        #index行下标  row行内容  传入的line和行下标index进行匹配
        for index,row in enumerate(reader,1):
            if index == line:         #line行
                return row

3.10.5、HTML测试报告

3.10.5.1、拷贝HTMLTestRunnerX.py到当前项目/run_test_case
3.10.5.2、 新建一个py类run_testcase.py
from com.tencent.common.HTMLTestRunnerX import HTMLTestRunner
from com.tencent.test_case.category_page_test import CategoryPageTest

if __name__ == '__main__':
	#创建测试套件
    suite = unittest.TestSuite()
	#将测试用例添加到测试套件中
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CategoryPageTest))
    #  定义生成测试报告的名称
    filename1="../reports/"+str(time.strftime('%Y%m%d%H%M%S'))+".html"
    fp = open(filename1, 'wb')
    # 定义测试报告的路径,标题,描述等内容
    runner=HTMLTestRunner(stream=fp,title=u'电商联盟',description=u'电商联盟')
	# 执行用例
runner.run(suite)
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值