Merge "Selenium: record video of every test"

This commit is contained in:
jenkins-bot 2018-10-16 22:23:36 +00:00 committed by Gerrit Code Review
commit 1658759d42
2 changed files with 79 additions and 8 deletions

View file

@ -20,8 +20,26 @@ If using MediaWiki-Vagrant:
npm run selenium
By default, Chrome will run in headless mode. If you want to see Chrome, set DISPLAY
environment variable to any value:
There are three supported modes of running the tests:
- Headless. It's the default. You will not see the browser while tests are
running because it's running in a headless mode. This mode should run fine
on all supported platforms.
- Headless recording. Set DISPLAY environment variable to a value that starts
with colon (`:`) and video of each test will be recorded. Browser will run
headless. Recording videos works only on Linux.
- Visible. If you want to see the browser, set DISPLAY environment variable to
any value that does not start with colon. This mode will not work in a
headless environment like MediaWiki-Vagrant.
Example recording session:
sudo apt-get install chromedriver ffmpeg xvfb
export DISPLAY=:94
Xvfb "$DISPLAY" -screen 0 1280x1024x24 &
npm run selenium
Example visible session:
DISPLAY=1 npm run selenium

View file

@ -1,8 +1,20 @@
const fs = require( 'fs' ),
path = require( 'path' ),
saveScreenshot = require( 'wdio-mediawiki' ).saveScreenshot,
logPath = process.env.LOG_DIR || __dirname + '/log';
logPath = process.env.LOG_DIR || path.join( __dirname, '/log' );
let ffmpeg;
// get current test title and clean it, to use it as file name
function fileName( title ) {
return encodeURIComponent( title.replace( /\s+/g, '-' ) );
}
// build file path
function filePath( test, screenshotPath, extension ) {
return path.join( screenshotPath, `${fileName( test.parent )}-${fileName( test.title )}.${extension}` );
}
// relative path
function relPath( foo ) {
return path.resolve( __dirname, '../..', foo );
}
@ -135,16 +147,57 @@ exports.config = {
// =====
// See also: http://webdriver.io/guide/testrunner/configurationfile.html
/**
* Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
* @param {Object} test test details
*/
beforeTest: function ( test ) {
if ( process.env.DISPLAY && process.env.DISPLAY.startsWith( ':' ) ) {
let videoPath = filePath( test, this.screenshotPath, 'mp4' );
const { spawn } = require( 'child_process' );
ffmpeg = spawn( 'ffmpeg', [
'-f', 'x11grab', // grab the X11 display
'-video_size', '1280x1024', // video size
'-i', process.env.DISPLAY, // input file url
'-loglevel', 'error', // log only errors
'-y', // overwrite output files without asking
'-pix_fmt', 'yuv420p', // QuickTime Player support, "Use -pix_fmt yuv420p for compatibility with outdated media players"
videoPath // output file
] );
ffmpeg.stdout.on( 'data', ( data ) => {
console.log( `ffmpeg stdout: ${data}` );
} );
ffmpeg.stderr.on( 'data', ( data ) => {
console.log( `ffmpeg stderr: ${data}` );
} );
ffmpeg.on( 'close', ( code ) => {
console.log( '\n\tVideo location:', videoPath, '\n' );
console.log( `ffmpeg exited with code ${code}` );
} );
}
},
/**
* Save a screenshot when test fails.
*
* @param {Object} test Mocha Test object
*/
afterTest: function ( test ) {
var filePath;
if ( !test.passed ) {
filePath = saveScreenshot( test.title );
console.log( '\n\tScreenshot: ' + filePath + '\n' );
if ( ffmpeg ) {
// stop video recording
ffmpeg.kill( 'SIGINT' );
}
// if test passed, ignore, else take and save screenshot
if ( test.passed ) {
return;
}
// save screenshot
let screenshotPath = filePath( test, this.screenshotPath, 'png' );
browser.saveScreenshot( screenshotPath );
console.log( '\n\tScreenshot location:', screenshotPath, '\n' );
}
};