Самодельная
параметризация и
параллелизация
тестов для JS
фреймворковРазработчик: Иван Котович
6 ноября, 2016
6 НОЯБРЯ, 2016
РАЗРАБОТЧИК: ИВАН КОТОВИЧ
Самодельная
параметризация и
параллелизация
тестов для JS
фреймворков
3CONFIDENTIAL
Иван Котович
Software Test Automation Engineer
• Более 2-х лет в JS автоматизации
• Разработал с нуля и внедрил в проект несколько
тестовых фреймворка на Java и JavaScript
• Участвую в Test Automation mentoring program как
ментор
• Читаю лекции в EPAM lab по автоматизации на JS
4CONFIDENTIAL
Параллелизация и параметризация на JS
Инструменты сборки (Grunt, Gulp)1
Параметризация с помощью инструментов сборки2
process.env объект содержащий настройки пользовательской среды3
child_process и его возможности4
Параллелизация тестов с помощью child process5
Итого6
5CONFIDENTIAL
Параллелизация и параметризация на JS
Инструменты сборки
…
6CONFIDENTIAL
Параллелизация и параметризация на JS
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
grunt.initConfig({
protractor:{
options:{
keepAlive:true,
noColor:false
},
target:{
options:{
configFile:'test/e2e/protractor-conf.js',
args:{
seleniumAddress:'http://localhost:4444/wd/hub',
baseUrl:'https://www.somehost.com/',
cucumberOpts:{
tags:['~@ignore']
}
}
}
}
}
});
grunt.loadNpmTasks('grunt-protractor-runner');
grunt.registerTask('e2e', 'Run e2e tests', function(target) {
console.log('E2e tests start');
grunt.task.run(['protractor:'+target]);
});
};
Инструменты сборки: Grunt
7CONFIDENTIAL
Параллелизация и параметризация на JS
gulp.task('protractor', function(callback) {
gulp.src(['example_spec.js'])
.pipe(gulpProtractorAngular({
'configFile': 'protractor.conf.js',
'debug': false,
'autoStartStopServer': true
}))
.on('error', function(e) {
console.log(e);
})
.on('end', callback);
});
Инструменты сборки: Gulp
Плюсы
• Лаконичен
• Простое API
• Потоковая передача данных
Минусы
• Меньше специализированных модулей
• Сложности в понимании процесса
потоковой передачи данных
8CONFIDENTIAL
Параллелизация и параметризация на JS
Параметризация с помощью инструментов сборки
var gulp = require('gulp'),
util = require('gulp-util');
gulp.task('cucumber', function() {
util.env.browser ? process.env.BROWSER = util.env.browser : process.env.BROWSER = 'chrome';
util.env.view ? process.env.VIEW = util.env.view : process.env.VIEW = 'desktop';
return gulp.src('test/features/*')
.pipe(cucumber({
'steps': 'test/step_definitions/*.js',
'support': 'test/support/*.js',
'format': 'json:test/reports/json/json-report.json',
'emitErrors': false
}));
});
gulp cucumber –-browser=chrome –-view=mobile
//выставление параметров через конфиг.bat
set BROWSER=firefox
set VIEW=mobile
gulp cucumber
9CONFIDENTIAL
Параллелизация и параметризация на JS
process.env объект содержащий настройки пользовательской среды
• process объект – глобаль ный объект
содержащий информацию о текущем node
процессе и предоставляющий инструменты
контроля над ним
• process доступен во всем приложении
• process.env содержит объект с информацией о
пользовательской среде
• process.env удобное место для хранения
конфигурационной информации для
приложения ( в том числе и для тестов )
$node -e ‘process.env.foo = "bar“’ && echo $foo
process.env.foo = 'bar';
console.log(process.env.foo);
chrome: {
'browserName' : 'chrome',
'chromeOptions' : {
'args': [chromeView[process.env.VIEW]]
}
}
10CONFIDENTIAL
Параллелизация и параметризация на JS
child_process и его возможности
• child_process – модуль который дает
возможность создавать дочерние процессы
• child_process предоставляет удобное API для
создания и управления дочерними процессами
• Child process такой же процесс содержащий
process объект
child_process.exec(command[, options][, callback])
child_process.execFile(file[, args][, options][, callback])
child_process.fork(modulePath[, args][, options])
child_process.spawn(command[, args][, options])
const exec = require('child_process').exec;
exec('cat *.js bad_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
11CONFIDENTIAL
Параллелизация и параметризация на JS
Параллелизация тестов с помощью child process
gulp parallel = gulp cucumber Х 4
var q = require('q');
var exec = require('child-process-promise').exec;
gulp.task(‘parallel', function(){
var promises = [];
var f1 = function(){
return exec('gulp cucumber')
.then(function (results) {console.log(results.stdout);})
.catch(function (err) {console.error('ERROR: ', err);});
};
for( var i = 0; i<4; i++){
promises.push(f1());
}
return q.all(promises);
});
Минус: зачем нам 4
параллельных прогона с
одинаковыми параметрами ??
12CONFIDENTIAL
Параллелизация и параметризация на JS
SO
? …
13CONFIDENTIAL
Параметризация параллельных прогонов
Параллелизация и параметризация на JS
var q = require('q');
var exec = require('child-process-promise').exec;
gulp.task(‘parallel', function(){
var threads = util.env.threads ? util.env.threads : 3,
browsersStr = util.env.browsers ? util.env.browsers : 'chrome/chrome/chrome',
viewsStr = util.env.views ? util.env.views : 'desktop/desktop/desktop',
promises = [],
browsers = browsersStr.split('/'),
views = viewsStr.split('/');
var f1 = function(browser,view){
return exec('gulp cucumber --browser='+browser+' --view='+view)
.then(function (results) {console.log(results.stdout);})
.catch(function (err) {console.error('ERROR: ', err);});
};
for( var i = 0; i<threads; i++){
if(browsers[i] !== 'firefox' && browsers[i] !== 'phantomjs'){
browsers[i] = 'chrome';
}
if(views[i] !== 'mobile' && views[i] !== 'tabletL' && views[i] !== 'tabletP'){
views[i] = 'desktop';
}
promises.push(f1(browsers[i],views[i]));
}
return q.all(promises);
});
gulp parallel –threads=2 –-browsers=chrome/firefox –-views=mobile/desktop
14CONFIDENTIAL
Параллелизация и параметризация на JS
15CONFIDENTIAL
Параллелизация и параметризация на JS
Итого: Что мы имеем?
• Удобный параметризируемый прогон
тестов в одном потоке с
возможностью выбора браузера и
разрешения окна браузера через
командную строку или конфиг
• Удобный параметризируемый прогон
тестов в разных процессах с
возможностью задать количество
дочерних процессов, браузер и вью
для каждого
• Возможность добавлять
дополнительные параметры для
выборки по тэгам, спекам итд
• Поле для дальнейших исследований и
улучшений
• Удовлетворение от проделанной
работы
Note: Параллелизация в protractor и
других JS фреймворках основана на
тех же принципах
16CONFIDENTIAL
• “JavaScript Patterns” Stoyan Stefanov
Useful literature Useful links
• https://nodejs.org/api/
• https://www.npmjs.com/package/gru
nt
• https://www.npmjs.com/package/gul
p
• https://www.npmjs.com/package/chil
d-process-promise
Параллелизация и параметризация на JS
17CONFIDENTIAL
Параллелизация и параметризация на JS
ВОПРОСЫ ...

Самодельная параметризация и параллелизация тестов на Webdriver (JS)

  • 1.
    Самодельная параметризация и параллелизация тестов дляJS фреймворковРазработчик: Иван Котович 6 ноября, 2016
  • 2.
    6 НОЯБРЯ, 2016 РАЗРАБОТЧИК:ИВАН КОТОВИЧ Самодельная параметризация и параллелизация тестов для JS фреймворков
  • 3.
    3CONFIDENTIAL Иван Котович Software TestAutomation Engineer • Более 2-х лет в JS автоматизации • Разработал с нуля и внедрил в проект несколько тестовых фреймворка на Java и JavaScript • Участвую в Test Automation mentoring program как ментор • Читаю лекции в EPAM lab по автоматизации на JS
  • 4.
    4CONFIDENTIAL Параллелизация и параметризацияна JS Инструменты сборки (Grunt, Gulp)1 Параметризация с помощью инструментов сборки2 process.env объект содержащий настройки пользовательской среды3 child_process и его возможности4 Параллелизация тестов с помощью child process5 Итого6
  • 5.
  • 6.
    6CONFIDENTIAL Параллелизация и параметризацияна JS module.exports = function(grunt) { require('load-grunt-tasks')(grunt); grunt.initConfig({ protractor:{ options:{ keepAlive:true, noColor:false }, target:{ options:{ configFile:'test/e2e/protractor-conf.js', args:{ seleniumAddress:'http://localhost:4444/wd/hub', baseUrl:'https://www.somehost.com/', cucumberOpts:{ tags:['~@ignore'] } } } } } }); grunt.loadNpmTasks('grunt-protractor-runner'); grunt.registerTask('e2e', 'Run e2e tests', function(target) { console.log('E2e tests start'); grunt.task.run(['protractor:'+target]); }); }; Инструменты сборки: Grunt
  • 7.
    7CONFIDENTIAL Параллелизация и параметризацияна JS gulp.task('protractor', function(callback) { gulp.src(['example_spec.js']) .pipe(gulpProtractorAngular({ 'configFile': 'protractor.conf.js', 'debug': false, 'autoStartStopServer': true })) .on('error', function(e) { console.log(e); }) .on('end', callback); }); Инструменты сборки: Gulp Плюсы • Лаконичен • Простое API • Потоковая передача данных Минусы • Меньше специализированных модулей • Сложности в понимании процесса потоковой передачи данных
  • 8.
    8CONFIDENTIAL Параллелизация и параметризацияна JS Параметризация с помощью инструментов сборки var gulp = require('gulp'), util = require('gulp-util'); gulp.task('cucumber', function() { util.env.browser ? process.env.BROWSER = util.env.browser : process.env.BROWSER = 'chrome'; util.env.view ? process.env.VIEW = util.env.view : process.env.VIEW = 'desktop'; return gulp.src('test/features/*') .pipe(cucumber({ 'steps': 'test/step_definitions/*.js', 'support': 'test/support/*.js', 'format': 'json:test/reports/json/json-report.json', 'emitErrors': false })); }); gulp cucumber –-browser=chrome –-view=mobile //выставление параметров через конфиг.bat set BROWSER=firefox set VIEW=mobile gulp cucumber
  • 9.
    9CONFIDENTIAL Параллелизация и параметризацияна JS process.env объект содержащий настройки пользовательской среды • process объект – глобаль ный объект содержащий информацию о текущем node процессе и предоставляющий инструменты контроля над ним • process доступен во всем приложении • process.env содержит объект с информацией о пользовательской среде • process.env удобное место для хранения конфигурационной информации для приложения ( в том числе и для тестов ) $node -e ‘process.env.foo = "bar“’ && echo $foo process.env.foo = 'bar'; console.log(process.env.foo); chrome: { 'browserName' : 'chrome', 'chromeOptions' : { 'args': [chromeView[process.env.VIEW]] } }
  • 10.
    10CONFIDENTIAL Параллелизация и параметризацияна JS child_process и его возможности • child_process – модуль который дает возможность создавать дочерние процессы • child_process предоставляет удобное API для создания и управления дочерними процессами • Child process такой же процесс содержащий process объект child_process.exec(command[, options][, callback]) child_process.execFile(file[, args][, options][, callback]) child_process.fork(modulePath[, args][, options]) child_process.spawn(command[, args][, options]) const exec = require('child_process').exec; exec('cat *.js bad_file | wc -l', (error, stdout, stderr) => { if (error) { console.error(`exec error: ${error}`); return; } console.log(`stdout: ${stdout}`); console.log(`stderr: ${stderr}`); });
  • 11.
    11CONFIDENTIAL Параллелизация и параметризацияна JS Параллелизация тестов с помощью child process gulp parallel = gulp cucumber Х 4 var q = require('q'); var exec = require('child-process-promise').exec; gulp.task(‘parallel', function(){ var promises = []; var f1 = function(){ return exec('gulp cucumber') .then(function (results) {console.log(results.stdout);}) .catch(function (err) {console.error('ERROR: ', err);}); }; for( var i = 0; i<4; i++){ promises.push(f1()); } return q.all(promises); }); Минус: зачем нам 4 параллельных прогона с одинаковыми параметрами ??
  • 12.
  • 13.
    13CONFIDENTIAL Параметризация параллельных прогонов Параллелизацияи параметризация на JS var q = require('q'); var exec = require('child-process-promise').exec; gulp.task(‘parallel', function(){ var threads = util.env.threads ? util.env.threads : 3, browsersStr = util.env.browsers ? util.env.browsers : 'chrome/chrome/chrome', viewsStr = util.env.views ? util.env.views : 'desktop/desktop/desktop', promises = [], browsers = browsersStr.split('/'), views = viewsStr.split('/'); var f1 = function(browser,view){ return exec('gulp cucumber --browser='+browser+' --view='+view) .then(function (results) {console.log(results.stdout);}) .catch(function (err) {console.error('ERROR: ', err);}); }; for( var i = 0; i<threads; i++){ if(browsers[i] !== 'firefox' && browsers[i] !== 'phantomjs'){ browsers[i] = 'chrome'; } if(views[i] !== 'mobile' && views[i] !== 'tabletL' && views[i] !== 'tabletP'){ views[i] = 'desktop'; } promises.push(f1(browsers[i],views[i])); } return q.all(promises); }); gulp parallel –threads=2 –-browsers=chrome/firefox –-views=mobile/desktop
  • 14.
  • 15.
    15CONFIDENTIAL Параллелизация и параметризацияна JS Итого: Что мы имеем? • Удобный параметризируемый прогон тестов в одном потоке с возможностью выбора браузера и разрешения окна браузера через командную строку или конфиг • Удобный параметризируемый прогон тестов в разных процессах с возможностью задать количество дочерних процессов, браузер и вью для каждого • Возможность добавлять дополнительные параметры для выборки по тэгам, спекам итд • Поле для дальнейших исследований и улучшений • Удовлетворение от проделанной работы Note: Параллелизация в protractor и других JS фреймворках основана на тех же принципах
  • 16.
    16CONFIDENTIAL • “JavaScript Patterns”Stoyan Stefanov Useful literature Useful links • https://nodejs.org/api/ • https://www.npmjs.com/package/gru nt • https://www.npmjs.com/package/gul p • https://www.npmjs.com/package/chil d-process-promise Параллелизация и параметризация на JS
  • 17.