برای نگارش آزمایش های اتوماتیک اپلیکیشن تان، نیاز به روشی برای هدایت اپلیکیشن تان در الکترون دارید. Spectron راه حلی متداول است که به شما اجازه می دهد توسط WebDriver فعالیت کاربران را تقلید کنید. اما همچنین ممکن است برای نوشتن درایور دلخواه خود از IPC-over-STDIO داخلی node استفاده کنید. مزیت یک درایور دلخواه (شخصی) این است که نسبت به Spectron، نیاز به منابع کمتری دارد و به شما اجازه می دهد که روش های دلخواه را در مجموعه آزمایش های خود قرار دهید.
برای ایجاد یک درایور دلخواه (شخصی) از nodejs’ child_process API استفاده می کنیم. مجموعه آزمایش فرایند Electron را ایجاد می کند، سپس یک پروتکل پیام رسانی ساده بوجود میاورد:
var childProcess = require('child_process')
var electronPath = require('electron')
// spawn the process
var env = { /* ... */ }
var stdio = ['inherit', 'inherit', 'inherit', 'ipc']
var appProcess = childProcess.spawn(electronPath, ['./app'], {stdio, env})
// listen for IPC messages from the app
appProcess.on('message', (msg) => {
// ...
})
// send an IPC message to the app
appProcess.send({my: 'message'})
از میان اپلیکیشن Electron، میتوانید پیام ها را بشنوید و با استفاده از API فرایند nodejs به آنها پاسخ دهید.
// listen for IPC messages from the test suite
process.on('message', (msg) => {
// ...
})
// send an IPC message to the test suite
process.send({my: 'message'})
حالا می توانید با استفاده از appProcess، از مجموعه آزمون با اپلیکیشن Electron ارتباط برقرار کنید.
برای راحتی کار شاید بخواهید Electron را در یک درایور که توابع سطح بالاتر را آماده می کند پوشش دهید. در اینجا مثالی برای چگونگی نحوه کار آمده است:
class TestDriver {
constructor ({path, args, env}) {
this.rpcCalls = []
// start child process
env.APP_TEST_DRIVER = 1 // let the app know it should listen for messages
this.process = childProcess.spawn(path, args, {stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env})
// handle rpc responses
this.process.on('message', (message) => {
// pop the handler
var rpcCall = this.rpcCalls[message.msgId]
if (!rpcCall) return
this.rpcCalls[message.msgId] = null
// reject/resolve
if (message.reject) rpcCall.reject(message.reject)
else rpcCall.resolve(message.resolve)
})
// wait for ready
this.isReady = this.rpc('isReady').catch((err) => {
console.error('Application failed to start', err)
this.stop()
process.exit(1)
})
}
// simple RPC call
// to use: driver.rpc('method', 1, 2, 3).then(...)
async rpc (cmd, ...args) {
// send rpc request
var msgId = this.rpcCalls.length
this.process.send({msgId, cmd, args})
return new Promise((resolve, reject) => this.rpcCalls.push({resolve, reject}))
}
stop () {
this.process.kill()
}
}
در اپلیکیشن، شما نیاز به نوشتن یک نگهدارنده (handler) ساده برای درخواست هایRPC دارید:
if (process.env.APP_TEST_DRIVER) {
process.on('message', onMessage)
}
async function onMessage ({msgId, cmd, args}) {
var method = METHODS[cmd]
if (!method) method = () => new Error('Invalid method: ' + cmd)
try {
var resolve = await method(...args)
process.send({msgId, resolve})
} catch (err) {
var reject = {
message: err.message,
stack: err.stack,
name: err.name
}
process.send({msgId, reject})
}
}
const METHODS = {
isReady () {
// do any setup needed
return true
}
// define your RPC-able methods here
}
سپس در مجموعه آزمایش تان می توانید از درایور آزمایش به صورت زیر استفاده کنید:
var test = require('ava')
var electronPath = require('electron')
var app = new TestDriver({
path: electronPath,
args: ['./app'],
env: {
NODE_ENV: 'test'
}
})
test.before(async t => {
await app.isReady
})
test.after.always('cleanup', async t => {
await app.stop()
})





