在使用electron-vue寫自動化測試軟件的時候,遇到了一些關於使用selenium-webdriver的坑,來記錄一下
一、環境配置
由於vue並沒有實際運行在node的運行時中,所以,在vue中引入selenium-webdriver會引發 no such module 的報錯,這個錯誤當時困擾了我很久,因爲確實沒有意識到是不同運行時環境的問題。所以,基於這一點,我選擇了在本地起一個node服務,通過訪問node,來對selenium進行操作
const app = require('express')
const { Builder, By } = require('selenium-webdriver')
const server = app()
server.use((req, res, next) => {
if (req.path !== '/' && !req.path.includes('.')) {
res.set({
// 由於vue啓動時會自己佔用一個端口,所以我們在服務端進行配置解決跨域問題
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type,access-token',
'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
'Content-Type': 'application/json; charset=utf-8'
})
}
req.method === 'OPTIONS' ? res.status(204).end() : next()
})
var port = 10099
var host = 'localhost'
server.listen(port, host, () => {
console.log(`server running @ http://${host}:${port}`)
})
server.get('/openWeb', function (req, res) {
// 這個是對selenium進行操作的函數,會在稍後貼出
jsOpenWeb()
})
這種解決方案的問題在於,需要通過命令行來啓動本地的node服務,我這邊使用electron可以在background.js中添加node child_process代碼
// 命令行啓動node服務,可以放在app.on('ready') 中
function startServer () {
const cmdStr = 'node localServer.js'
var exec = require('child_process').exec(cmdStr, function (error, stdout, stderr) {
console.log(error)
console.log(stdout)
})
exec.on('close', function (code) {
console.log(code)
})
}
二、操作瀏覽器
相關的代碼可以參考以上文檔,但是,在js的sdk中,幾乎所有的操作均是異步執行,即所有的函數均返回Promise對象,這裏是第二個卡住我的地方,因爲我一開始並沒有理解Promise是什麼,直到和做前端的同學聊天時才得知,這是一個用於異步操作的對象,於是將原來的同步執行代碼均換爲異步執行
/**
*1.說明一下,中間註釋的部分爲之前在Chrome中測試網站會有彈窗,註釋部分爲濾除彈窗用的
*2.由於涉及到正在做抓取的網站,所以,我把域名換成百度了,都差不多,不過需要着重注意
在一個頁面有frame的時候,一定要將焦點通過switchTo函數切換到frame中,否則,
無法獲取網頁元素。如果沒有frame存在,直接摘掉switchTo().frame() 代碼塊即可操作
*/
function jsOpenWeb () {
const broswer = new Builder().forBrowser('internet explorer').build()
broswer.get('https://www.baidu.com')
// broswer.wait(until.alertIsPresent()).then(() => {
// broswer.switchTo().alert().accept().then(() => {
//broswer.findElement(By.id('fraInterface')).then((value) => {
console.log(value)
broswer.switchTo().frame(value).then(() => {
//下面兩行代碼效果一樣的
//通過元素id找到該元素並寫入值
broswer.findElement(By.id('kw')).sendKeys('搜索內容')
//通過元素name找到該元素並寫入值
broswer.findElement(By.name('')).sendKeys('搜索內容')
})
// })
// })
// })
}
三、報錯處理
1.記得把所有需要的瀏覽器驅動(IEDriverServer/ChromDriver)等等加入到環境變量中,Mac(usr/bin) Win(控制面板->系統與安全->系統->高級系統設置->高級->環境變量,將driver的路徑填寫進去就可以)
2.關於元素未找到的錯誤:
這個問題有網速相關,有frame嵌套的原因,但是在js的sdk中,更多的是沒有異步執行的關係,比如你實際上並沒有切入到frame中,就要去獲取frame中的一個input是肯定不行的,所以,建議多打斷點和log
3.IE下,input元素輸入速率過慢:
如果出現了在給input寫入值的時候,幾秒鐘才蹦出一個字符的這種現象時,請檢查你的IEDriver,看看是否是32位的,如果不是,請換成32位