当前位置: 首页 > news >正文

selenium4 web自动化测试

Web应用包含超文本标记语言(HTML)、层叠样式表演(CSS)、JavaScript脚本的Web页面。

HTML表单由不同类型的元素组成的,包含<form>、<input>、<button>、<label>

Python接口自动化测试零基础入门到精通(2025最新版)

1 webdriver的API与定位元素

from selenium import webdriverb = webdriver.Firefox()
b.get('http://www.baidu.com') #输入url
print(b.title) #打印元素
print(b.current_url) #打印url

Webdriver常用方法:

1.1 8种元素定位的方法

元素名称webdriver API说明
idfind_element_by_id() 
namefind_element_by_name() 
class namefind_element_by_class_name() 
tag namefind_element_by_tag_name() 
link textfind_element_by_link_text() 
partial link textfind_element_by_partial_link_text() 
xpathfind_element_by_xpath() 
css selectorfind_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'),默认取第一个inputele2 = 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_nameele7=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类与输入事件

  1. from selenium.webdriver.common.action_chains import AcitonChains
  2. ActionCharis(driver):用于生成模拟用户行为
  3. 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 WebDriverWaitUrl = '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) #输入urlb.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 webdriverdriver = 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 valuedriver.quit()

复制代码

7.2 flash上传(非input标签)

有几种解决方案:

  1. autoIT,借助外力,我们去调用其生成的au3或exe文件。
  2. Python pywin32库,识别对话框句柄,进而操作
  3. SendKeys库
  4. 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 sleepprofile = 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 Headerdef sent_email(SMTP_host,Username,Password,Content,Subject,Revicer):#1.实例化SMTPsmtp = smtplib.SMTP()#2.链接邮件服务器smtp.connect(SMTP_host)#3.配置发送者邮箱密码smtp.login(Username,Password)#4.配置发送内容msgmsg = MIMEText(Content,'html','utf-8') # 三个参数:第一个为文本内容,第二个置文本格式,第三个设置编码msg['Subject']= Header(Subject,'utf-8') #邮件主题msg['From'] = Usernamemsg['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 osdef 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_addrmsg['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_filedef SendReport(report_dir):# 获取最新报告case_list = os.listdir(report_dir) #获取report目录下所有文件,以列表形式返回case_list.sort(key=lambda fn:os.path.getatime(report_dir+'\\'+fn)) #对case_list中所有元素按时间从大到小排序latest_report = os.path.join(report_dir,case_list[-1])print(latest_report)return latest_reportif __name__ == '__main__':suite = unittest.TestSuite()tests = [TestMathFunc('test_add'),TestMathFunc('test_minus'),TestMathFunc('test_divide')]suite.addTests(tests)now = time.strftime('%Y%m%d%H%M%S')with open(now+'HTMLReport.html','wb') as f:runner = HTMLTestRunner(stream=f,title='计算器测试',description = '测试报告',verbosity=2)runner.run(suite)R = SendReport("C:\\Users\\zhouxy\\PycharmProjects\\untitled\\unit_test")try:send_file('smtp.163.com','****@163.com','******','****@163.com',R,'主题')print('邮件发送成功')except smtplib.SMTPException:print('Error:无法发送邮件')

复制代码

11 测试用例设计

数据设计:字典形式

keyval
url打开地址
text_id登录元素
userid/pwdid/loginid输入账号元素
uname/pwd输入账号信息
errorid检查错误条件

http://www.dtcms.com/a/288586.html

相关文章:

  • pip关于缓存的用法
  • minizinc学习记录
  • 如何优雅解决缓存与数据库的数据一致性问题?
  • Docker实践:使用Docker部署WhoDB开源轻量级数据库管理工具
  • 飞船躲避陨石小游戏流量主微信抖音小程序开源
  • 【ESP32设备通信】-使用Modbus RTU读取传感器数据
  • 嵌入式硬件篇---按键
  • 嵌入式硬件篇---机械臂运动学解算(3自由度)
  • CentOS 服务器docker pull 拉取失败
  • 在vue中遇到Uncaught TypeError: Assignment to constant variable(常亮无法修改)
  • 后台管理系统登录模块(双token的实现思路)
  • 音视频学习(四十一):H264帧内压缩技术
  • 通俗易懂神经网络:从基础到实现
  • 【JavaFX国产化适配】快捷键注册(检测快捷键冲突、注册事件)
  • Syncthing实时共享同步数据 服务器数据备份软件(linux、windows)
  • 全面解析MySQL(2)——CRUD基础
  • 从零到精通:用DataBinding解锁MVVM的开发魔法
  • 第十四讲 | AVL树实现
  • Dify工作流实战
  • 安装minerU的API服务
  • 如何避免广度优先搜索(BFS)在有环图中陷入无限循环
  • ADC和DMA简述
  • 第四次作业
  • linux + 宝塔面板 部署 django网站 启动方式:uwsgi 和gunicorn如何选择 ?
  • 用 Jetpack Compose 写 Android 的 “Hello World”
  • windows + phpstorm 2024 + phpstudy 8 + php7.3 + thinkphp6 配置xdebug调试
  • YOLOv8目标检测项目代码详解与习题
  • C++ 桶排序、基数排序、堆排序
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(一)
  • Spring之事务使用指南