selenium-web自动化测试
Posted 小律爷
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了selenium-web自动化测试相关的知识,希望对你有一定的参考价值。
Web应用包含超文本标记语言(html)、层叠样式表演(CSS)、javascript脚本的Web页面。
HTML表单由不同类型的元素组成的,包含<form>、<input>、<button>、<label>
1 webdriver的API与定位元素
from selenium import webdriver b = webdriver.Firefox() b.get(\'http://www.baidu.com\') #输入url print(b.title) #打印元素 print(b.current_url) #打印url
Webdriver常用方法:
1.1 8种元素定位的方法
元素名称 | webdriver API | 说明 |
id | find_element_by_id() | |
name | find_element_by_name() | |
class name | find_element_by_class_name() | |
tag name | find_element_by_tag_name() | |
link text | find_element_by_link_text() | |
partial link text | find_element_by_partial_link_text() | |
xpath | find_element_by_xpath() | |
css selector | find_element_by_css_selector() |
>>> ele = b.find_element_by_id(\'kw\') >>> ele1=b.find_element_by_name(\'wd\')
1.2 元素操作方式
方法 | 说明 |
clear | 清除元素内容 |
send_keys | 模拟按键输入 |
click | 点击 |
submit | 提交表单 |
>>> ele.clear() >>> ele.send_keys(\'自动化测试\') >>> b.back() #退回 >>> ele1.send_keys(\'测试\')
>>> ele2= b.find_element_by_class_name(\'s_ipt\') >>> ele2.send_keys(\'selenium\') >>> ele3=b.find_element_by_tag_name(\'input\') >>> ele3.size {\'height\': 0.0, \'width\': 0.0} >>> ele3.id \'3e2e100e-b754-4ce1-b1d7-7872079247da\' >>> ele2.id \'2f622532-63aa-4018-8a4c-683f382ae01a\' #id不同,右键查看页面源代码,有其他input
WebElement功能列表:
功能/属性 | 描述 | 实例 |
size | 获取元素的大小 | element.size |
tag_name | 获取元素的HTML标签名称 | element.tag_name |
text | 获取元素的文本值 | element.text |
>>> b.get(\'http://www.dji.com\') >>> b.maximize_window() #最大化窗口 >>> ele=b.find_element_by_link_text(\'消费级产品\') >>> ele.click() >>> ele1=b.find_element_by_partial_link_text(\'消费级\') >>> ele1.click() >>> ele_css=b.find_element_by_css_selector(\'html.js.no-touch.csstransforms3d.csstransitions body.dji-zh-CN.dji-pc nav#site-header.dui-navbar.site-header.collapsed div.navbar-container div#siteHeaderNavbar ul.navbar-category li.category-item a.ga-data\') #审查元素后复制css路径 >>> ele_css=b.find_element_by_css_selector(\'input[class=\\\'search-input\\\']\') #可以定位任一元素 >>> ele_css.send_keys(\'社区\')
如果没有元素与之匹配,则抛出NoSucnElementException异常。
其他WebElement常用方法:
1.3 xpath定位
- xml路径语言:用来确定xml文档中某部分位置的语言;
- xpath用于在xml文档中通过元素和属性进行导航;
- xpath是一个W3C标准;
- 对xml/html有一定的了解。
xpah节点类型:元素、属性、文本、命名空间、指令处理、注释及文档。
xpath:通过路径表达式从xml文档中选取节点或节点设置
表达式 | 结果 |
/xxx | 选取根节点xx |
/xxx/yyy | 根据绝对路径选择元素 |
//xxx | 整个文档扫描,找到所有xxx元素 |
//xxx/yyy | 所有父元素为xxx的yyy元素 |
. | 选取当前节点的父元素节点 |
.. | 选取父元素地址 |
//xxx[@id] | 选取所有xxx元素中有id属性的元素 |
//xxx[@id=yyy] | 选取所有xxx元素id属性为yyy的元素 |
b.get(r\'C:\\Users\\zhouxy\\Desktop\\bookmark.html\') ele = b.find_element_by_xpath(\'/html\') #绝对路径 ele.text ele = b.find_element_by_xpath(\'/html/body/form/input\') #默认第一个输入框 ele.get_attribute(\'type\') #-->‘text’ #第二个输入框 ele1=b.find_element_by_xpath(\'/html/body/from/input[2]\') #并通过input下标找到 e= find.element_by_xpath(\'//input\') #相对路径 e.get_attribute(\'name\') ele = b.find_element_by_xpath(\'//input/..\') ele.tag_name #-->form 上一级目录 e = b.find_element_by_xpath(\'//input[@id]\') #\'//input[@name="xxx"]\'
#遍历所有 ele= b.find_element_by_xpath(\'//*\') #-->html #运用函数 ele= b.find_element_by_xpath(\'//*[count[input]=2]\') #-->form
#从表单开始定位
ele= b.find_element_by_xpath(\'//form[@id=“form”/span/input]\')
#组合定位
ele= b.find_element_by_xpath(\'//input[@name="wd"] and @id="kw"]\')
表达式 | 结果 |
//*[count(xxx)=2] | 统计xxx元素个数=2的节点 |
//*[local-name()=\'xxx\'] | 找到tag为xxx的元素 |
//*[starts-with(local_name(),\'x\')] | 找到所有tag以x开头的元素 |
//*[contain(local_name())=3] | 找到所有tag包含x的元素 |
//*[string-length(local-name())=3] | 找到所有tag长度为3的元素 |
//xxx | //yyy | 多个路径查找 |
ele1 = b.find_element_by_xpath(\'//*[local-name()="input"]\') #相当于(\'//input\'),默认取第一个input ele2 = b.find_element_by_xpath(\'//*[start-with(local-name(),"i")]\') ele3 = b.find_element_by_xpath(\'//*[contain(local-name(),"i")]\') ele4 = b.find_element_by_xpath(\'//*[contain(local-name(),"i")]\') ele5 = b.find_element_by_xpath(\'//*[contain(local-name(),"i")][last()]\') #包含i的tag_name倒数第一个元素 ele5 = b.find_element_by_xpath(\'//*[contain(local-name(),"i")][last()]-1\') #包含i目录倒数第二个元素 ele.get_attribute(\'name\') #获取元素的属性 ele6 = b.find_element_by_xpath(\'//*[string-length(local-name())=3]\') #长度等于3的tag_name ele7=b.find_element_by_xpath(\'//title | // input[last()]\') #-->title
1.4 css selector定位
选择器 | 描述 | 举例 |
* | 通配选择器,选择所有的元素 | * |
<type> | 选择特定类型的元素,支持基本HTML标签 | h1 |
.<class> | 选择具有特定class的元素。 | .class1 |
<type>.<class> | 特定类型和特定class的交集。(直接将多个选择器连着一起表示交集) | h1.class1 |
#<id> | 选择具有特定id属性值的元素 | #id1 |
e= find_element_by_css_selector(".s_ipt") e= find_element_by_css_selector("#kw")
通过属性选择器定位:
选择器 | 描述 | 举例 |
[attr] | 选取定义attr属性的元素,即使该属性没有值 | [placeholder] |
[attr="val"] | 选取attr属性等于val的元素 | [placeholder="请输入关键词"] |
[attr^="val"] | 选取attr属性开头为val的元素 | [placeholder^="请输入"] |
[attr$="val"] | 选取attr属性结尾为val的元素 | [placeholder$="关键词"] |
[attr*="val"] | 选取attr属性包含val的元素 | [placeholder*="入关"] |
[attr~="val"] | 选取attr属性包含多个空格分隔的属性,其中一个等于val的元素 | [placeholder~="关键词"] |
[attr|="val"] | 选取attr属性等于val的元素或第一个属性值等于val的元素 | [placeholder|="关键词"] |
2 鼠标和键盘事件
2.1 AcitonChains类与输入事件
- from selenium.webdriver.common.action_chains import AcitonChains
- ActionCharis(driver):用于生成模拟用户行为
- perform():执行存储行为
2.2 鼠标事件
表达式 | 说明 |
context_click | 右击事件 |
double_click | 双击事件 |
drag_and_drop | 拖动 |
move_to_element() | 鼠标停在一个元素上 |
click_and_hold | 按下鼠标左键在一个元素上 |
>>> from selenium import webdriver >>> b = webdriver.Firefox() >>> b.get(\'http://www.dji.com\') >>> from selenium.webdriver.common.action_chains import ActionChains >>> ele=b.find_element_by_link_text(\'消费级产品\') >>> ActionChains(b).move_to_element(ele).perform() >>> sub_ele=b.find_element_by_link_text(\'御 Mavic Air\') >>> sub_ele.click()
2.3 键盘事件:send_keys()
from selenium.webdriver.common keys import Keys
表达式 | 说明 |
send_keys(Keys.BACKSPACE) | 退格键 |
send_keys(Keys.CONTRL,\'a\') | 全选 |
send_keys(Keys.CONTRL,\'v\') | 粘贴 |
send_keys(Keys.CONTRL,\'c\') | 复制 |
send_keys(Keys.CONTRL,\'x\') | 剪切 |
send_keys(Keys.ENTER\') | 回车 |
>>> s =b.find_element_by_name(\'q\') >>> s.sent_keys(\'大疆\') >>> s.clear() >>> s.send_keys(\'大疆啊\') >>> from selenium.webdriver.common.keys import Keys >>> s.send_keys(Keys.BACKSPACE) >>> s.send_keys(Keys.CONTROL,\'a\') >>> s.send_keys(Keys.CONTROL,\'x\') >>> s.send_keys(Keys.CONTROL,\'v\') >>> ele=b.find_element_by_link_text(\'大疆司空\') >>> s.send_keys(Keys.ENTER)
3 对话框与多窗口管理
>>> d = webdriver.Firefox() >>> d.get(\'http://www.baidu.com\') >>> d.find_element_by_id(\'kw\').clear() >>> d.find_element_by_id(\'kw\').send_keys(\'大疆科技\') >>> d.find_element_by_id(\'su\').click() >>> d.find_element_by_partial_link_text(\'DJI大疆创新 - 所有产品\').click() >>> d.window_handles [\'4294967297\', \'4294967301\'] #列出所有的句柄 >>> d.current_window_handle \'4294967297\' #显示当前句柄 >>>d.switch_to_window(d.window_handles[0]) #切换句柄 >>> d.close() #关闭tab >>> d.quit() #退出浏览器
4 下拉框处理
需要特定的Select类并导入,from selenium.webdriver.support.select import Select
5 alter对话框处理
需要先切换到弹框上的,alert = driver.switch_to_alert()
Alter方法:
swich_to_alert() | 切到alter,返回一个alter对象 |
accept | 确认 |
dismiss | 取消 |
send_keys() | 有输入框才能使用,否则报错 |
>>>alert=b.swich_to_alert
6 测试脚本中的等待方法
6.1 元素等待机制
隐式等待:为了解决由于网络延迟或利用Ajax动态加载元素所导致的程序响应时间不一致。当一个测试用例执行的时候,WebDriver找不到任意一个元素,将会等待,等待时间超过后,则抛出NoSuchElementException。
显式等待:可以为脚本设置一些预置或定制化的条件,等待条件满足后再执行测试。显示等待可以只作用于有同步需求的测试用例。
WebDriver提供WebDriverWait类和expected_conditions类来实现显式等待。
implicitly_wait() | 设置webdriver等待时间,等待时间后报异常 |
WebDriverWait |
等待条件满足或者超时后退出 from selenium.webdriver.support.ui import WebDriverWait |
6.2 WebDriverWair方法:
构造函数:def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY)
poll_frequency-->check-->until-->method return Not False
-->not until-->method return False
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
Url = \'http://10.10.200.86:10004/ccs-web/index.jsp\'
Account = \'zhouxy\'
Password = \'111\'
def get_ele_time(driver,times,func):
return WebDriverWait(driver,times).until(func)
def login_test():
b = webdriver.Firefox() #启动浏览器
b.get(Url) #输入url
b.maximize_window()
login_ele = get_ele_time(b,10,lambda b:b.find_element_by_xpath(\'/html/body/form/ \\
table/tbody/tr[3]/td/table/tbody/tr[3]/td/table/tbody/tr[1]/td[7]/img\')) #也可以用expected_conditions有定义好的预期等待条件
username_ele = b.find_element_by_id(\'j_username\') #用户名元素
username_ele.clear() #清空
username_ele.send_keys(Account) #输入用户名
password_ele = b.find_element_by_id(\'j_password\')
password_ele.clear()
password_ele.send_keys(Password)
login_ele.click()
try :
ele = b.find_element_by_link_text(\'Login fail: 错误的凭证\')
print(\'登录失败\')
except:
print(\'登录成功\')
time.sleep(10)
b.close()
if __name__ == \'__main__\':
login_test()
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC \'\'\' 10秒钟等待浏览器弹出的对话框,如果出现,就点击确定按钮 \'\'\' WebDriverWait(chromedriver,10).until(EC.alert_is_present()).accept()
7 文件上传
7.1 普通上传(通过input框)
# -*- coding: utf-8 -*- from selenium import webdriver driver = webdriver.Firefox() driver.get(\'http://sahitest.com/demo/php/fileUpload.htm\') upload = driver.find_element_by_id(\'file\') upload.send_keys(\'d:\\\\baidu.py\') # send_keys print upload.get_attribute(\'value\') # check value driver.quit()
7.2 flash上传(非input标签)
有几种解决方案:
- autoIT,借助外力,我们去调用其生成的au3或exe文件。
- Python pywin32库,识别对话框句柄,进而操作
- SendKeys库
- keybd_event,跟3类似,不过是模拟按键,ctrl+a,ctrl+c, ctrl+v…
8 文件下载
对于Firefox,需要设置Profile:
browser.download.dir
:指定下载路径browser.download.folderList
:设置成2
表示使用自定义下载路径;设置成0
表示下载到桌面;设置成1
表示下载到默认路径browser.download.manager.showWhenStarting
:在开始下载时是否显示下载管理器browser.helperApps.neverAsk.saveToDisk
:对所给出文件类型不再弹出框进行询问
from selenium import webdriver from time import sleep profile = webdriver.FirefoxProfile() profile.set_preference(\'browser.download.dir\', \'d:\\\\\') profile.set_preference(\'browser.download.folderList\', 2) profile.set_preference(\'browser.download.manager.showWhenStarting\', False) profile.set_preference(\'browser.helperApps.neverAsk.saveToDisk\', \'application/zip\') driver = webdriver.Firefox(firefox_profile=profile) driver.get(\'http://sahitest.com/demo/saveAs.htm\') driver.find_element_by_xpath(\'//a[text()="testsaveas.zip"]\').click() sleep(3) driver.quit()
9 滚动条
from selenium import webdriver import os dr = webdriver.Firefox() dir = os.path.join(\'file:///\'+os.getcwd()+\'\\\\h1.html\') dr.get(dir) dr.implicitly_wait(3) js=\'document.getElementsByClassName("scroll")[0].scrollTop=0\' # 就是这么简单,修改这个元素的scrollTop就可以 dr.execute_script(js)
document.getElementsByClassName("scroll")[0].scrollHeight # 获取滚动条高度 document.getElementsByClassName("scroll")[0].scrollWidth # 获取横向滚动条宽度 document.getElementsByClassName("scroll")[0].scrollLeft=xxx # 控制横向滚动条位置
10 自动发送邮件
10.1 SMTP模块发送邮件
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议。
import smtplib from email.mime.text import MIMEText from email.header import Header def sent_email(SMTP_host,Username,Password,Content,Subject,Revicer): #1.实例化SMTP smtp = smtplib.SMTP() #2.链接邮件服务器 smtp.connect(SMTP_host) #3.配置发送者邮箱密码 smtp.login(Username,Password) #4.配置发送内容msg msg = MIMEText(Content,\'html\',\'utf-8\') # 三个参数:第一个为文本内容,第二个置文本格式,第三个设置编码 msg[\'Subject\']= Header(Subject,\'utf-8\') #邮件主题 msg[\'From\'] = Username msg[\'To\'] = Revicer #5.配置发送邮箱,接收邮箱,以及发送内容 smtp.sendmail(Username,Revicer,msg.as_string()) #6.关闭邮件服务 smtp.quit() if __name__ == \'__main__\': sent_email(\'smtp.163.com\',\'****@163.com\',\'******\',\'<html><h1>你好</h1></html>\',\'邮件主题\',\'****@163.com\')
10.2 email模块
email模块下有mime包,mime英文全称为“Multipurpose Internet Mail Extensions”,即多用途互联网邮件扩展,是目前互联网电子邮件普遍遵循的邮件技术规范。
该mime包下常用的有三个模块:text,image,multpart。
- 构造一个邮件对象就是一个
Message
对象 - 如果构造一个
MIMEText
对象,就表示一个文本邮件对象(如果发送内容为中文,需要选择“plain”,要不然无法显示) - 如果构造一个
MIMEImage
对象,就表示一个作为附件的图片 - 要把多个对象组合起来,就用
MIMEMultipart
对象 - 而
MIMEBase
可以表示任何对象。它们的继承关系如下:
Message
+- MIMEBase
+- MIMEMultipart
+- MIMENonMultipart
+- MIMEMessage
+- MIMEText
+- MIMEImage
10.2.1 添加普通文本
text = "This is a text\\nHere is the link you want:\\nhttp:\\\\www.baidu.com" 2 msg = MINEText(text, \'plain\', utf-8)
10.2.2 添加超文本
html = """ <html> <body> <p> Here is the <a href="http://www.baidu.com">link</a> you wanted. </p> </body> </html> """ msg = MIMEText(html,\'html\', \'utf-8\')
10.2.3 添加附件
sendfile = open(\'D:\\\\python\\\\sendfile.txt\', \'rb\').read() msg = MINEText(sendfile, \'base64\', \'utf-8\') msg[\'Content-type\'] = \'application/octet-stream\' msg[\'Content-Disposition\'] = \'attachment;filename= "文件显示名字.txt"\'
10.2.4 添加图片
sendimagefile=open(r\'D:\\pythontest\\testimage.png\',\'rb\').read() msg = MIMEImage(sendimagefile) msg.add_header(\'Content-ID\',\'<image1>\')
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage from email.header import Header import os def send_file(SMTP_host,from_addr,from_pwd,to_addr,file_addr,subject): smtp = smtplib.SMTP(SMTP_host) smtp.login(from_addr,from_pwd) # 邮件主题/发送者/接受者 msg = MIMEMultipart() msg[\'Subject\']= Header(subject,\'utf-8\') msg[\'From\'] = from_addr msg[\'To\'] = to_addr # 邮件正文 msg.attach(MIMEText(\'如附件所示\',\'plain\',\'utf-8\')) # 邮件附件 with open(file_addr,\'rb\') as f : file = f.read() att = MIMEText(file,\'base64\',\'utf-8\') att[\'Content-type\'] = \'application/octet-stream\' att[\'Content-Dispositon\'] = \'attachment;filename="test.html"\' #文件名 msg.attach(att) smtp.sendmail(from_addr,to_addr,msg.as_string()) smtp.quit() if __name__ == \'__main__\': try: dir = os.path.join(os.getcwd()+\'//h1.html\') send_file(\'smtp.163.com\',\'****@163.com\',\'******\',\'****@163.com\',dir,\'主题\') print(\'邮件发送成功\') except smtplib.SMTPException: print(\'Error:无法发送邮件\')
10.3 自动发送邮件
import unittest,smtplib from test_mathfunc import TestMathFunc from HTMLTestRunner import HTMLTestRunner import time,os,sys email_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(email_path) from web_test.test_email import send_file def SendReport(report_dir): Selenium - Web自动化测试的基本操作实现如何设置 vscode 的代码片段,以便在自动完成后自动触发 vscode 的智能感知?
CTS测试CtsWindowManagerDeviceTestCases模块的testShowWhenLockedImeActivityAndShowSoftInput测试fail项解决方法(代码片段