selenium操作不同的浏览器,需要下载不同浏览器的驱动
以chrome浏览器为例:
1、进入到下载页面,找到符合自己浏览器版本的驱动
2、下载好了之后,右键解压到当前文件夹
3、将得到的chromedriver.exe放到Python的安装目录

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class Zen_Tao:
def __init__(self):
# 初始化一个chrome浏览器(驱动谷歌浏览器时,直接使用webdriver.Chrome()可能会报错,建议使用一下方法)
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
self.drive = webdriver.Chrome(options=options)
# 最大化窗口
self.drive.maximize_window()
# 隐式等待,设置最大的等待时长,只对查找元素(find_elementXXX)生效
self.drive.implicitly_wait(2)
def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
def sign_out(self):
'''退出浏览器'''
self.drive.close() # 关闭浏览器
self.drive.quit() # 关闭浏览器并且关闭驱动
if __name__ == "__main__":
run = Zen_Tao()
run.log_on()
run.sign_out()


def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 1.用 id 属性定位查找
self.drive.find_element(By.ID, "account")
# 2.用 name 属性定位查找
self.drive.find_element(By.NAME, "account")
# 3.用 class 属性定位查找
self.drive.find_element(By.CLASS_NAME, "form-control")
# 4.用 xpath 属性定位查找
self.drive.find_element(By.XPATH, '//*[@id="account"]')
# 5.具有给定标签名称的第一个元素将被返回
self.drive.find_element(By.TAG_NAME, "input")
# 6.用 css 属性定位查找
# 方法一[标签名]
self.drive.find_element(By.CSS_SELECTOR, 'input')
# 方法二[id], #代表id
self.drive.find_element(By.CSS_SELECTOR, '#account')
# 方法三[class], .代表class
self.drive.find_element(By.CSS_SELECTOR, '.form-control')
# 方法四[其他属性]
self.drive.find_element(By.CSS_SELECTOR, '[name="account"]')
# 7.链接文本值与位置匹配的第一个元素将被返回
# (通过标签对之间的文本进行定位)
self.drive.find_element(By.LINK_TEXT, "忘记密码")
# 8.具有部分链接文本值与位置匹配的第一个元素将被返回
# (partial link其实是对link的一个扩展,因为有些时候链接文本很长,这时候就可以使用其中的一部分来进行定位)
self.drive.find_element(By.PARTIAL_LINK_TEXT, "忘记")
def log_on(self):
'''代码执行'''
# 1.通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 2.标签名和id属性值组合定位
self.drive.find_element(By.CSS_SELECTOR, 'input#account')
# 3.标签名和class属性值组合定位
self.drive.find_element(By.CSS_SELECTOR, 'input.form-control')
# 4.标签名和属性(含属性值)组合定位
self.drive.find_element(By.CSS_SELECTOR, 'input[name="account"]')
# 5.多个属性组合定位
self.drive.find_element(By.CSS_SELECTOR, '[class="form-control"][name="account"]')

def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 1.查询元素时,我们也可以先查询父级,然后再查询子级,父级和子级用空格隔开,如上图所示(div - table - input)
self.drive.find_element(By.CSS_SELECTOR, '.col-8 [class="table table-form"] #account')

def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 定位第一个元素
self.drive.find_element(By.CSS_SELECTOR, '[class="form-control"]')
# 定位第二个元素,find_elements后面加了s
self.drive.find_elements(By.CSS_SELECTOR, '[class="form-control"]')[1]

def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 输入:send_keys()
self.drive.find_element(By.CSS_SELECTOR, '#account').send_keys("admin")
# 清空: clear()
self.drive.find_element(By.CSS_SELECTOR, '#account').clear()
# 单机操作(相当于鼠标点击):click()
self.drive.find_element(By.CSS_SELECTOR, '.form-actions #submit').click()
# 点击登录按钮,一般情况下,使用click()进行点击
# 有些时候也可以使用submit()代替click(),相当于敲回车
def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('https://www.baidu.com/')
# 输入内容,点击百度一下
self.drive.find_element(By.CSS_SELECTOR, '[class="s_ipt"]').send_keys("软件测试")
# 回车操作(相当于按回车键):submit()
self.drive.find_element(By.CSS_SELECTOR, '[id="su"]').submit()
-Text获取元素内容

# text 获取元素内容
text = self.drive.find_element(By.CSS_SELECTOR, '.form-actions a').text
print(text)
# 结果:忘记密码

# 获取元素内容
get = self.drive.find_element(By.CSS_SELECTOR, '#loginPanel h2').get_attribute('innerText')
print(get)
# 结果:易软天创项目管理系统

# 获取属性的值
get = self.drive.find_element(By.CSS_SELECTOR, '[id="keepLoginon"]').get_attribute('title')
print(get)
# 结果:保持登录
在页面中显示元素:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
<form>
<input type="text" value="用户名" id="account"><br>
<input type="password" value="密码" id="password"><br>
</form>
</body>
</html>
在页面中不显示元素:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
<form>
<input style="visibility: hidden;" type="text" value="用户名" id="account"><br>
<input type="password" value="密码" id="password"><br>
</form>
</body>
</html>
禁用输入框:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
<form>
<input disabled="disabled" type="text" value="用户名" id="account"><br>
<input type="password" value="密码" id="password"><br>
</form>
</body>
</html>
1、is_displayed()
1、is_displayed():判断元素是否存在,结果是真或假
1-1显示元素,在HTML里,在页面也显示,返回True,
1-2隐藏元素,在HTML里,不在页面显示,返回Flase
1-3不在HTML里,不存在这个元素,会报错
# 判断输入框是否在页面中显示
drive = self.drive.find_element(By.CSS_SELECTOR, '#account').is_displayed()
print(f"元素是否显示:{drive}")
2、is_enabled()
is_enabled():判断是否可用
# 判断输入框是否可以输入
drive = self.drive.find_element(By.CSS_SELECTOR, '#account').is_enabled()
print(f"输入框是否可以输入:{drive}")
3、is_selected()
is_selected():判断是否选中,一般用于复选框或单选框的选中判断
# 勾选保持登陆操作
# self.drive.find_element(By.CSS_SELECTOR, '[name="keepLogin[]"]').click()
drive = self.drive.find_element(By.CSS_SELECTOR, '[name="keepLogin[]"]').is_selected()
if drive:
print(f"已勾选:{drive}")
else:
print(f"未勾选:{drive}")
说明:在html语法中,frame 元素或者iframe元素的内部会包含一个被嵌入的另一份html文档,这个时候如果我们需要操作iframe内的文档,就需要先切换到被嵌入的文档中,才可以进行操作。


def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 登陆禅道
self.drive.find_element(By.CSS_SELECTOR, '[id="account"]').send_keys("admin")
time.sleep(1)
self.drive.find_element(By.CSS_SELECTOR, '[name="password"').send_keys("123456")
time.sleep(1)
self.drive.find_element(By.CSS_SELECTOR, '[id="submit"]').click()
time.sleep(1)
# 切换方法如下:
# 方法一
# iframe = self.drive.find_elements_by_tag_name("iframe")[0]
# self.drive.switch_to.frame(iframe)
# 方法二
# self.drive.switch_to.frame(0)
# 方法三
iframe = self.drive.find_element(By.CSS_SELECTOR, '#appIframe-my')
self.drive.switch_to.frame(iframe)
time.sleep(1)
# 点击联系人
self.drive.find_element(By.XPATH, '//*[@id="navbar"]/ul/li[5]/a').click()
# 切换到最外层表单
self.drive.switch_to.default_content()
time.sleep(1)
# 点击项目
self.drive.find_element(By.CSS_SELECTOR, '#menu [data-app="project"]').click()

def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 需要悬停的元素,悬停到语言选择框上
hover = self.drive.find_element(By.CSS_SELECTOR, '[class="btn"]')
# 鼠标悬停 ActionChains(浏览器).move_to_element(悬停的元素).perform() 执行操作
ActionChains(self.drive).move_to_element(hover).perform()
time.sleep(1)
# 选择需要的语言
self.drive.find_element(By.CSS_SELECTOR, '[data-value="zh-tw"]').click()
像iframe切换/鼠标悬停为提高成功率,最好是在操作后sleep(1)秒

def log_on(self):
'''代码执行'''
# 通过get()方法打开网页
self.drive.get('http://192.168.100.210/zentao/')
# 点击登陆
self.drive.find_element(By.CSS_SELECTOR, '[id="submit"]').click()
time.sleep(1)
# 获取警告框的文本信息
alert_msg = self.drive.switch_to.alert.text
print(alert_msg)
# 接受警告框 accept()
self.drive.switch_to.alert.accept()
# 取消警告框 dismiss()
# self.drive.switch_to.alert.dismiss()
def log_on(self):
'''代码执行'''
# 打开百度
self.drive.get('https://www.baidu.com/')
# 搜索框输入:CSDN
self.drive.find_element(By.CSS_SELECTOR, '[name="wd"]').send_keys("csdn")
time.sleep(0.5)
# 点击百度一下
self.drive.find_element(By.CSS_SELECTOR, '[id="su"]').click()
time.sleep(0.5)
# 点击CSDN官网,开启新窗口,进入CSDN官网
self.drive.find_element(By.LINK_TEXT, 'CSDN技术社区').click()
time.sleep(3)
# 获取当前窗口(当前句柄名称-handle)
windows = self.drive.current_window_handle
print(f"当前handle:{windows}")
# 获取所有窗口(所有句柄名称-handle),以列表的形式返回过来
all_windows = self.drive.window_handles
print(f"所有handle:{all_windows}")
# 切换窗口,根据所有窗口的下标来切换,窗口顺序从0开始。(此时有两个窗口,第一个百度,第二个csdn)
self.drive.switch_to.window(all_windows[0])
time.sleep(3)
# 切换到最新窗口的句柄(csdn)
self.drive.switch_to.window(all_windows[-1])
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>演示数据</title>
</head>
<body>
<select id="nr" name="wan">
<option value="10">每页显示10条</option>
<option value="20">每页显示20条</option>
<option value="50">每页显示50条</option>
<option value="100">每页显示100条</option>
</select>
</body>
</html>
def log_on(self):
'''代码执行'''
# 打开本地hthl页面
self.drive.get('file:///C:/Users/Admin/Desktop/hthl.html')
# 需要先定位到下拉框
elements = self.drive.find_element(By.CSS_SELECTOR, '#nr')
# Select(需要操作下拉框).根据什么操作
time.sleep(2)
Select(elements).select_by_index(1) # 根据index,下标定位,从0开始
time.sleep(2)
Select(elements).select_by_value('100') # 根据value定位
time.sleep(2)
Select(elements).select_by_visible_text('每页显示50条') # 根据文本定位
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel