0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

😱 🚀 🎨 tests: use truncate instead of database deletion (#8119)

* 😱  🚀  🎨  tests: use truncate instead of delete the database

refs #7718, refs #7470

- should bring massive speed improvement
- could also fix random test failures (e.g. sqlite database is busy)

* gruntfile: add knex-migrator command in test-setup
This commit is contained in:
Katharina Irrgang 2017-03-09 20:38:20 +01:00 committed by Hannah Wolfe
parent feaa25dad2
commit f8c51ac7e5
4 changed files with 205 additions and 95 deletions

View file

@ -8,9 +8,15 @@
// jshint unused: false
var overrides = require('./core/server/overrides'),
config = require('./core/server/config'),
_ = require('lodash'),
chalk = require('chalk'),
fs = require('fs-extra'),
KnexMigrator = require('knex-migrator'),
knexMigrator = new KnexMigrator({
knexMigratorFilePath: config.get('paths:appRoot')
}),
path = require('path'),
escapeChar = process.platform.match(/^win/) ? '^' : '\\',
@ -446,6 +452,13 @@ var overrides = require('./core/server/overrides'),
});
});
/**
* Ensures the target database get's automatically created.
*/
grunt.registerTask('knex-migrator', function () {
return knexMigrator.init({noScripts: true});
});
// ### Validate
// **Main testing task**
//
@ -499,7 +512,7 @@ var overrides = require('./core/server/overrides'),
// ### test-setup *(utility)(
// `grunt test-setup` will run all the setup tasks required for running tests
grunt.registerTask('test-setup', 'Setup ready to run tests',
['clean:test', 'setTestEnv']
['knex-migrator', 'clean:test', 'setTestEnv']
);
// ### Unit Tests *(sub task)*

View file

@ -35,7 +35,9 @@ describe('Frontend Routing', function () {
}
function addPosts(done) {
testUtils.initData().then(function () {
testUtils.clearData().then(function () {
return testUtils.initData();
}).then(function () {
return testUtils.fixtures.insertPostsAndTags();
}).then(function () {
done();
@ -493,10 +495,10 @@ describe('Frontend Routing', function () {
});
describe('Site Map', function () {
before(testUtils.teardown);
before(function (done) {
testUtils.initData().then(function () {
testUtils.clearData().then(function () {
return testUtils.initData();
}).then(function () {
return testUtils.fixtures.insertPostsAndTags();
}).then(function () {
done();

View file

@ -49,6 +49,9 @@ function forkGhost(newConfig) {
.then(function (_port) {
port = _port;
return knexMigrator.reset();
})
.then(function () {
return knexMigrator.init();
})
.then(function () {

View file

@ -1,3 +1,4 @@
/*jshint expr:true*/
var Promise = require('bluebird'),
_ = require('lodash'),
fs = require('fs-extra'),
@ -11,6 +12,8 @@ var Promise = require('bluebird'),
errors = require('../../server/errors'),
db = require('../../server/data/db'),
fixtureUtils = require('../../server/data/schema/fixtures/utils'),
schema = require('../../server/data/schema').tables,
schemaTables = Object.keys(schema),
models = require('../../server/models'),
SettingsLib = require('../../server/settings'),
permissions = require('../../server/permissions'),
@ -423,7 +426,9 @@ clearData = function clearData() {
};
toDoList = {
app: function insertApp() { return fixtures.insertOne('apps', 'createApp'); },
app: function insertApp() {
return fixtures.insertOne('apps', 'createApp');
},
app_field: function insertAppField() {
// TODO: use the actual app ID to create the field
return fixtures.insertOne('apps', 'createApp').then(function () {
@ -436,32 +441,80 @@ toDoList = {
return fixtures.insertOne('app_settings', 'createAppSetting');
});
},
permission: function insertPermission() { return fixtures.insertOne('permissions', 'createPermission'); },
role: function insertRole() { return fixtures.insertOne('roles', 'createRole'); },
roles: function insertRoles() { return fixtures.insertRoles(); },
tag: function insertTag() { return fixtures.insertOne('tags', 'createTag'); },
subscriber: function insertSubscriber() { return fixtures.insertOne('subscribers', 'createSubscriber'); },
posts: function insertPostsAndTags() { return fixtures.insertPostsAndTags(); },
'posts:mu': function insertMultiAuthorPosts() { return fixtures.insertMultiAuthorPosts(); },
tags: function insertMoreTags() { return fixtures.insertMoreTags(); },
apps: function insertApps() { return fixtures.insertApps(); },
settings: function populateSettings() { return SettingsLib.init(); },
'users:roles': function createUsersWithRoles() { return fixtures.createUsersWithRoles(); },
'users:no-owner': function createUsersWithoutOwner() { return fixtures.createUsersWithoutOwner(); },
users: function createExtraUsers() { return fixtures.createExtraUsers(); },
'user:token': function createTokensForUser() { return fixtures.createTokensForUser(); },
owner: function insertOwnerUser() { return fixtures.insertOwnerUser(); },
'owner:pre': function initOwnerUser() { return fixtures.initOwnerUser(); },
'owner:post': function overrideOwnerUser() { return fixtures.overrideOwnerUser(); },
'perms:init': function initPermissions() { return permissions.init(); },
perms: function permissionsFor(obj) {
return function permissionsForObj() { return fixtures.permissionsFor(obj); };
permission: function insertPermission() {
return fixtures.insertOne('permissions', 'createPermission');
},
clients: function insertClients() { return fixtures.insertClients(); },
'client:trusted-domain': function insertClients() { return fixtures.insertClientWithTrustedDomain(); },
filter: function createFilterParamFixtures() { return filterData(DataGenerator); },
invites: function insertInvites() { return fixtures.insertInvites(); },
themes: function loadThemes() { return themes.loadAll(); }
role: function insertRole() {
return fixtures.insertOne('roles', 'createRole');
},
roles: function insertRoles() {
return fixtures.insertRoles();
},
tag: function insertTag() {
return fixtures.insertOne('tags', 'createTag');
},
subscriber: function insertSubscriber() {
return fixtures.insertOne('subscribers', 'createSubscriber');
},
posts: function insertPostsAndTags() {
return fixtures.insertPostsAndTags();
},
'posts:mu': function insertMultiAuthorPosts() {
return fixtures.insertMultiAuthorPosts();
},
tags: function insertMoreTags() {
return fixtures.insertMoreTags();
},
apps: function insertApps() {
return fixtures.insertApps();
},
settings: function populateSettings() {
return SettingsLib.init();
},
'users:roles': function createUsersWithRoles() {
return fixtures.createUsersWithRoles();
},
'users:no-owner': function createUsersWithoutOwner() {
return fixtures.createUsersWithoutOwner();
},
users: function createExtraUsers() {
return fixtures.createExtraUsers();
},
'user:token': function createTokensForUser() {
return fixtures.createTokensForUser();
},
owner: function insertOwnerUser() {
return fixtures.insertOwnerUser();
},
'owner:pre': function initOwnerUser() {
return fixtures.initOwnerUser();
},
'owner:post': function overrideOwnerUser() {
return fixtures.overrideOwnerUser();
},
'perms:init': function initPermissions() {
return permissions.init();
},
perms: function permissionsFor(obj) {
return function permissionsForObj() {
return fixtures.permissionsFor(obj);
};
},
clients: function insertClients() {
return fixtures.insertClients();
},
'client:trusted-domain': function insertClients() {
return fixtures.insertClientWithTrustedDomain();
},
filter: function createFilterParamFixtures() {
return filterData(DataGenerator);
},
invites: function insertInvites() {
return fixtures.insertInvites();
},
themes: function loadThemes() {
return themes.loadAll();
}
};
/**
@ -632,7 +685,8 @@ togglePermalinks = function togglePermalinks(request, toggle) {
doAuth(request).then(function (token) {
request.put('/ghost/api/v0.1/settings/')
.set('Authorization', 'Bearer ' + token)
.send({settings: [
.send({
settings: [
{
uuid: '75e994ae-490e-45e6-9207-0eab409c1c04',
key: 'permalinks',
@ -643,7 +697,8 @@ togglePermalinks = function togglePermalinks(request, toggle) {
updated_at: '2014-10-20T19:44:18.077Z',
updated_by: 1
}
]})
]
})
.end(function (err, res) {
if (err) {
return reject(err);
@ -659,18 +714,55 @@ togglePermalinks = function togglePermalinks(request, toggle) {
});
};
/**
* Has to run in a transaction for MySQL, otherwise the foreign key check does not work.
* Sqlite3 has no truncate command.
*/
teardown = function teardown(done) {
debug('Database reset');
debug('Database teardown');
var tables = schemaTables.concat(['migrations']);
if (done) {
knexMigrator.reset()
.then(function () {
done();
if (config.get('database:client') === 'sqlite3') {
return Promise
.mapSeries(tables, function createTable(table) {
return db.knex.raw('DELETE FROM ' + table + ';');
})
.catch(done);
} else {
return knexMigrator.reset();
.then(function () {
done && done();
})
.catch(function (err) {
// CASE: table does not exist
if (err.errno === 1) {
return done && done();
}
done && done(err);
});
}
return db.knex.transaction(function (trx) {
return db.knex.raw('SET FOREIGN_KEY_CHECKS=0;').transacting(trx)
.then(function () {
return Promise
.each(tables, function createTable(table) {
return db.knex.raw('TRUNCATE ' + table + ';').transacting(trx);
});
})
.then(function () {
return db.knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(trx);
})
.then(function () {
done && done();
})
.catch(function (err) {
// CASE: table does not exist
if (err.errno === 1146) {
return done && done();
}
return done ? done(err) : Promise.reject(err);
});
});
};
/**