#1107 Back tests from Jenkins

This commit is contained in:
Juan Ferrer 2019-02-11 22:57:48 +01:00
parent 796a3e1a76
commit 7e0ccfcc11
3 changed files with 166 additions and 123 deletions

6
Jenkinsfile vendored
View File

@ -62,14 +62,12 @@ pipeline {
environment {
NODE_ENV = ""
FIREFOX_BIN = "/opt/firefox/firefox-bin"
DOCKER_HOST = "${env.DOCKER_HOST_2}"
}
steps {
nodejs('node-lts') {
sh 'karma start --junit'
sh 'gulp docker'
// sh 'gulp backendUnitTest --junit' // FIXME: Docker isn't at localhost
sh 'docker rm -f salix-db'
sh 'gulp backTestDocker --junit --random --run-chown'
}
}
}

View File

@ -16,6 +16,13 @@ let langs = ['es', 'en'];
let srcDir = './front';
let modulesDir = './modules';
let buildDir = 'dist';
let containerId = 'salix-db';
let dataSources = require('./loopback/server/datasources.json');
let dbConf = dataSources.vn;
if (process.env.DOCKER_HOST)
dbConf.host = process.env.DOCKER_HOST;
let backSources = [
'!node_modules',
@ -66,43 +73,55 @@ defaultTask.description = `Starts all application services`;
// Backend tests
function backendUnitTest() {
async function backTestOnly() {
let bootOptions;
if (argv['random'])
bootOptions = {dataSources};
let app = require(`./loopback/server/server`);
app.boot(bootOptions);
let specFiles = [
'back/**/*.spec.js',
'loopback/**/*.spec.js',
'modules/*/back/**/*.spec.js'
];
await new Promise((resolve, reject) => {
const jasmine = require('gulp-jasmine');
const jasmine = require('gulp-jasmine');
let options = {errorOnFail: false};
let options = {errorOnFail: false};
if (argv.junit || argv.j) {
const reporters = require('jasmine-reporters');
options.reporter = new reporters.JUnitXmlReporter();
}
if (argv.junit) {
const reporters = require('jasmine-reporters');
options.reporter = new reporters.JUnitXmlReporter();
}
return gulp.src(specFiles)
.pipe(jasmine(options))
.on('jasmineDone', function() {
app.disconnect();
});
let backSpecFiles = [
'back/**/*.spec.js',
'loopback/**/*.spec.js',
'modules/*/back/**/*.spec.js'
];
gulp.src(backSpecFiles)
.pipe(jasmine(options))
.on('end', resolve)
.resume();
});
await app.disconnect();
}
backendUnitTest.description = `Runs the backend tests only, can receive args --junit or -j to save reports on a xml file`;
backTestOnly.description = `Runs the backend tests only, can receive --junit arg to save reports on a xml file`;
const dockerAndBackTest = gulp.series(docker, backendUnitTest);
dockerAndBackTest.description = `Restarts database and runs the backend tests`;
async function backTestDocker() {
let containerId = await docker();
await backTestOnly();
if (argv['random'])
await execP(`docker rm -fv ${containerId}`);
}
backTestDocker.description = `Runs backend tests using in site container`;
function backTest(done) {
const nodemon = require('gulp-nodemon');
let gulpBin = isWindows
? 'node_modules/.bin/gulp.cmd'
: 'node_modules/.bin/gulp';
nodemon({
exec: gulpBin,
args: ['backendUnitTest'],
exec: ['node ./node_modules/gulp/bin/gulp.js'],
args: ['backTestOnly'],
watch: backSources,
done: done
});
@ -324,20 +343,35 @@ watch.description = `Watches for changes in routes and locale files`;
* to avoid a bug with OverlayFS driver on MacOS.
*/
async function docker() {
try {
await execP('docker rm -fv salix-db');
} catch (e) {}
let d = new Date();
let pad = v => v < 10 ? '0' + v : v;
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
await execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./services/db`);
let dockerArgs = `--name ${containerId} -p 3306:${dbConf.port}`;
if (argv['random'])
dockerArgs = '-p 3306';
else {
try {
await execP(`docker rm -fv ${containerId}`);
} catch (e) {}
}
let runChown = process.platform != 'linux';
if (argv['run-chown']) runChown = true;
await execP(`docker run --env RUN_CHOWN=${runChown} -d --name salix-db -p 3306:3306 salix-db`);
let result = await execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
containerId = result.stdout;
if (argv['random']) {
let inspect = await execP(`docker inspect -f "{{json .NetworkSettings.Ports}}" ${containerId}`);
let ports = JSON.parse(inspect.stdout);
dbConf.port = ports['3306/tcp'][0]['HostPort'];
}
if (runChown) await dockerWait();
return containerId;
}
docker.description = `Builds the database image and runs a container`;
@ -350,7 +384,7 @@ docker.description = `Builds the database image and runs a container`;
async function dockerStart() {
let state;
try {
let result = await execP('docker container inspect -f "{{json .State}}" salix-db');
let result = await execP(`docker inspect -f "{{json .State}}" ${containerId}`);
state = JSON.parse(result.stdout);
} catch (err) {
return await docker();
@ -360,7 +394,7 @@ async function dockerStart() {
case 'running':
return;
case 'exited':
await execP('docker start salix-db');
await execP(`docker start ${containerId}`);
await dockerWait();
return;
default:
@ -377,6 +411,13 @@ function dockerWait() {
let elapsedTime = 0;
let maxInterval = 5 * 60 * 1000;
let myConf = {
user: dbConf.username,
password: dbConf.password,
host: dbConf.host,
port: dbConf.port
};
log('Waiting for MySQL init process...');
checker();
@ -385,7 +426,7 @@ function dockerWait() {
let state;
try {
let result = await execP('docker container inspect -f "{{json .State}}" salix-db');
let result = await execP(`docker container inspect -f "{{json .State}}" ${containerId}`);
state = JSON.parse(result.stdout);
} catch (err) {
return reject(new Error(err.message));
@ -394,11 +435,7 @@ function dockerWait() {
if (state.Status === 'exited')
return reject(new Error('Docker exited, please see the docker logs for more info'));
let conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root'
});
let conn = mysql.createConnection(myConf);
conn.on('error', () => {});
conn.connect(err => {
conn.destroy();
@ -443,21 +480,21 @@ module.exports = {
back,
backOnly,
backWatch,
backendUnitTest,
dockerAndBackTest,
backTest,
e2eOnly,
backTestOnly,
backTestDocker,
e2e,
smokesOnly,
e2eOnly,
smokes,
install,
smokesOnly,
i,
install,
build,
clean,
webpack,
webpackDevServer,
locales,
routes,
locales,
localesRoutes,
watch,
docker,

View File

@ -34,98 +34,106 @@ let modulesDir = `${appDir}/modules`;
// Internationalization
if (fs.existsSync(localeDir)) {
i18n.configure({
directory: localeDir,
defaultLocale: 'es'
});
app.use(i18n.init);
}
// Initialization
app.disconnect = async function() {
let promises = [];
for (let ds in app.dataSources)
promises.push(app.dataSources[ds].disconnect());
for (let ds in this.dataSources)
promises.push(this.dataSources[ds].disconnect());
return await Promise.all(promises);
};
app.start = function(port) {
function onListen() {
let baseUrl = app.get('url').replace(/\/$/, '');
let explorerPath = app.get('loopback-component-explorer').mountPath;
app.start = function(bootOptions, port, callback) {
let onListen = () => {
let baseUrl = this.get('url').replace(/\/$/, '');
let explorerPath = this.get('loopback-component-explorer').mountPath;
console.log(`Browse your REST API at: %s`, `${baseUrl}${explorerPath}`);
app.emit('started');
}
this.emit('started');
callback && callback();
};
let args = port ? [port, onListen] : [onListen];
return app.listen(...args);
this.boot(bootOptions, err => {
if (err) throw err;
let args = port ? [port, onListen] : [onListen];
return this.listen(...args);
});
};
let config = require('./config.json');
app.boot = function(myBootOptions, callback) {
// Internatinalization
for (let key in config)
app.set(key, config[key]);
if (fs.existsSync(localeDir)) {
i18n.configure({
directory: localeDir,
defaultLocale: 'es'
});
let modelConfigFiles = [
`${__dirname}/model-config.json`
];
let modelSources = [
`loopback/common/models`,
`loopback/server/models`,
`${__dirname}/../common/models`
];
let mixinDirs = [
`loopback/common/mixins`,
`loopback/server/mixins`,
`${__dirname}/../common/mixins`
];
let bootDirs = [
`${__dirname}/boot`
];
this.use(i18n.init);
}
addPath(`${appDir}/back`);
// Initialization
let modules = fs.readdirSync(modulesDir);
for (let mod of modules)
addPath(`${modulesDir}/${mod}/back`);
let config = require('./config.json');
function addPath(path) {
modelConfigFiles.push(`${path}/model-config.json`);
modelSources.push(`${path}/models`);
mixinDirs.push(`${path}/mixins`);
bootDirs.push(`${path}/boot`);
}
for (let key in config)
this.set(key, config[key]);
let models = {};
for (file of modelConfigFiles) {
if (fs.existsSync(file)) {
let fileModels = require(file);
for (let key in fileModels) {
if (models[key])
console.warn(`Redeclaration of '${key}' at ${file}`);
let modelConfigFiles = [
`${__dirname}/model-config.json`
];
let modelSources = [
`loopback/common/models`,
`loopback/server/models`,
`${__dirname}/../common/models`
];
let mixinDirs = [
`loopback/common/mixins`,
`loopback/server/mixins`,
`${__dirname}/../common/mixins`
];
let bootDirs = [
`${__dirname}/boot`
];
addPath(`${appDir}/back`);
let modules = fs.readdirSync(modulesDir);
for (let mod of modules)
addPath(`${modulesDir}/${mod}/back`);
function addPath(path) {
modelConfigFiles.push(`${path}/model-config.json`);
modelSources.push(`${path}/models`);
mixinDirs.push(`${path}/mixins`);
bootDirs.push(`${path}/boot`);
}
let models = {};
for (file of modelConfigFiles) {
if (fs.existsSync(file)) {
let fileModels = require(file);
for (let key in fileModels) {
if (models[key])
console.warn(`Redeclaration of '${key}' at ${file}`);
}
Object.assign(models, fileModels);
}
Object.assign(models, fileModels);
}
}
let bootOptions = {
appRootDir: __dirname,
appConfigRootDir: rootDir,
modelsRootDir: rootDir,
models: models,
modelSources: modelSources,
mixinDirs: mixinDirs,
bootDirs: bootDirs
let bootOptions = {
appRootDir: __dirname,
appConfigRootDir: rootDir,
modelsRootDir: rootDir,
models: models,
modelSources: modelSources,
mixinDirs: mixinDirs,
bootDirs: bootDirs
};
if (fs.existsSync(`/etc/salix`))
bootOptions.dsRootDir = `/etc/salix`;
Object.assign(bootOptions, myBootOptions);
boot(this, bootOptions, callback);
};
if (fs.existsSync(`/etc/salix`))
bootOptions.dsRootDir = `/etc/salix`;
boot(app, bootOptions, function(err) {
if (err) throw err;
if (require.main === module)
app.start();
});
if (require.main === module)
app.start();