Selenium (Node.js) 截图速度太慢
Selenium (Node.js) screenshots are too slow
我正在使用 Selenium + Mocha(在 Node.js 中)在站点上进行一些 UI 测试。每次测试后,我想截屏以便 review/share 可以看到结果。
但是,在完成基本的 UI 更改后(即插入文本并点击提交),有一个 AJAX 调用 + JavaScript 动画会在之后触发,我想成为我的屏幕截图的一部分。
我得到的屏幕截图似乎是在下一步已经开始之后拍摄的。 (因此,第一个测试运行 > 触发屏幕截图 > 第二个测试开始 > 实际捕获屏幕截图)
我试过 .sleep()
和超时 -- 但我的使用可能是错误的。
function takeScreenshot(name='out'){
driver.takeScreenshot().then(function(data){
var base64Data = data.replace(/^data:image\/png;base64,/,"")
fs.writeFile(`screenshots/${name}.png`, base64Data, 'base64', function(err) {
if(err) console.log(err);
});
});
}
describe('UI Tests', async function() {
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://localhost:8000').then( async function(){ await getAssets(); });
/* search | submit | reset are declared in getAssets() */
});
after(async function() {
driver.quit();
});
afterEach(async function(){
step++;
driver.sleep(3000).then(
takeScreenshot(step)
);
});
describe('User Types/Modifies Input and Submits Query', async function() {
it('type in search + click submit', async function(){
search.sendKeys("Puppies and Kittens");
submit.click();
});
it('click the X icon to clear search', async function(){
reset.click();
});
});
});
在上面的代码片段中,第一个测试 ('type in search + click submit'
) 的屏幕截图将显示输入字段已从第二个测试中清除。
发送到 selenium 的命令是异步的,这意味着一个函数将工作安排到 运行 在未来的某个时间点,但立即 return 因此代码继续进行。
在 selenium-webdrivers 的情况下,函数 return a "promise" 将在将来的某个时间点解析。 Mocha 可以使用 promise 来等待结果。
Promises 和 Mocha
Mocha 使用测试的 return 值来确定它是否应该等待承诺解决。您可以使用 await
或 .then
.
控制承诺流程
如果正在使用 Promise A+ 代码,那么测试中将始终有 return someFormOfPromise
。
it(waits, function(){
return Promise.resolve(true)
.then(res => expect(res).to.be.true)
})
如果 async
is being used, that guarantees a promise is returned but you must await
任何异步或测试将继续
it(waits, async function(){
let res = await Promise.resolve(true)
expect(res).to.be.true
})
回调类似,但它们使用 done
函数来指示测试继续进行。
it(waits, function(done){
someTrueCallback((err, res) => {
if (err) return done(err)
expect(res).to.be.true
done()
})
})
发布的代码中混合了很多Promise A+和async
,甚至还抛出了一个回调。选择一种方式并坚持下去在可能的情况下,我将使用 async
/await
.
回调到 Promise
任何异步回调都可以转换为 promise,因此从 fs.writeFile
回调函数开始,将其转换为 promise:
function writeFile(path, data, format){
return new Promise((resolve, reject)=>{
fs.writeFile(path, data, format, function(err){
if (err) return reject(err)
resolve(true)
})
})
}
幸运的是,这是非常标准的,Node.js 在 util.promisify
中有一个帮助者,所以帮助者可以成为:
const writeFile = util.promisify(fs.writeFile)
function async takeScreenshot(name='out'){
let data = await driver.takeScreenshot()
var base64Data = data.replace(/^data:image\/png;base64,/,"")
return await writeFile(`screenshots/${name}.png`, base64Data, 'base64')
}
测试
当 await
可用时,无需使用 .then
。
每当调用承诺的函数 return 时,如果您想使用已解析的值,您可能需要 await
或 let res = await...
。
describe('UI Tests', function() {
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://localhost:8000')
await getAssets()
/* search | submit | reset are declared in getAssets() */
});
after(async function() {
await driver.quit();
});
afterEach(async function(){
step++;
await takeScreenshot(step)
});
describe('User Types/Modifies Input and Submits Query', function() {
it('type in search + click submit', async function(){
await search.sendKeys("Puppies and Kittens");
await submit.click();
});
it('click the X icon to clear search', async function(){
await reset.click();
});
});
});
附带说明一下,这些测试实际上并未检查任何内容。通常是像 chai would be used to ensure things are the way you expect 这样的断言库。
我正在使用 Selenium + Mocha(在 Node.js 中)在站点上进行一些 UI 测试。每次测试后,我想截屏以便 review/share 可以看到结果。
但是,在完成基本的 UI 更改后(即插入文本并点击提交),有一个 AJAX 调用 + JavaScript 动画会在之后触发,我想成为我的屏幕截图的一部分。
我得到的屏幕截图似乎是在下一步已经开始之后拍摄的。 (因此,第一个测试运行 > 触发屏幕截图 > 第二个测试开始 > 实际捕获屏幕截图)
我试过 .sleep()
和超时 -- 但我的使用可能是错误的。
function takeScreenshot(name='out'){
driver.takeScreenshot().then(function(data){
var base64Data = data.replace(/^data:image\/png;base64,/,"")
fs.writeFile(`screenshots/${name}.png`, base64Data, 'base64', function(err) {
if(err) console.log(err);
});
});
}
describe('UI Tests', async function() {
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://localhost:8000').then( async function(){ await getAssets(); });
/* search | submit | reset are declared in getAssets() */
});
after(async function() {
driver.quit();
});
afterEach(async function(){
step++;
driver.sleep(3000).then(
takeScreenshot(step)
);
});
describe('User Types/Modifies Input and Submits Query', async function() {
it('type in search + click submit', async function(){
search.sendKeys("Puppies and Kittens");
submit.click();
});
it('click the X icon to clear search', async function(){
reset.click();
});
});
});
在上面的代码片段中,第一个测试 ('type in search + click submit'
) 的屏幕截图将显示输入字段已从第二个测试中清除。
发送到 selenium 的命令是异步的,这意味着一个函数将工作安排到 运行 在未来的某个时间点,但立即 return 因此代码继续进行。
在 selenium-webdrivers 的情况下,函数 return a "promise" 将在将来的某个时间点解析。 Mocha 可以使用 promise 来等待结果。
Promises 和 Mocha
Mocha 使用测试的 return 值来确定它是否应该等待承诺解决。您可以使用 await
或 .then
.
如果正在使用 Promise A+ 代码,那么测试中将始终有 return someFormOfPromise
。
it(waits, function(){
return Promise.resolve(true)
.then(res => expect(res).to.be.true)
})
如果 async
is being used, that guarantees a promise is returned but you must await
任何异步或测试将继续
it(waits, async function(){
let res = await Promise.resolve(true)
expect(res).to.be.true
})
回调类似,但它们使用 done
函数来指示测试继续进行。
it(waits, function(done){
someTrueCallback((err, res) => {
if (err) return done(err)
expect(res).to.be.true
done()
})
})
发布的代码中混合了很多Promise A+和async
,甚至还抛出了一个回调。选择一种方式并坚持下去在可能的情况下,我将使用 async
/await
.
回调到 Promise
任何异步回调都可以转换为 promise,因此从 fs.writeFile
回调函数开始,将其转换为 promise:
function writeFile(path, data, format){
return new Promise((resolve, reject)=>{
fs.writeFile(path, data, format, function(err){
if (err) return reject(err)
resolve(true)
})
})
}
幸运的是,这是非常标准的,Node.js 在 util.promisify
中有一个帮助者,所以帮助者可以成为:
const writeFile = util.promisify(fs.writeFile)
function async takeScreenshot(name='out'){
let data = await driver.takeScreenshot()
var base64Data = data.replace(/^data:image\/png;base64,/,"")
return await writeFile(`screenshots/${name}.png`, base64Data, 'base64')
}
测试
当 await
可用时,无需使用 .then
。
每当调用承诺的函数 return 时,如果您想使用已解析的值,您可能需要 await
或 let res = await...
。
describe('UI Tests', function() {
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://localhost:8000')
await getAssets()
/* search | submit | reset are declared in getAssets() */
});
after(async function() {
await driver.quit();
});
afterEach(async function(){
step++;
await takeScreenshot(step)
});
describe('User Types/Modifies Input and Submits Query', function() {
it('type in search + click submit', async function(){
await search.sendKeys("Puppies and Kittens");
await submit.click();
});
it('click the X icon to clear search', async function(){
await reset.click();
});
});
});
附带说明一下,这些测试实际上并未检查任何内容。通常是像 chai would be used to ensure things are the way you expect 这样的断言库。