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 // jshint unused: false
var overrides = require('./core/server/overrides'), var overrides = require('./core/server/overrides'),
config = require('./core/server/config'),
_ = require('lodash'), _ = require('lodash'),
chalk = require('chalk'), chalk = require('chalk'),
fs = require('fs-extra'), fs = require('fs-extra'),
KnexMigrator = require('knex-migrator'),
knexMigrator = new KnexMigrator({
knexMigratorFilePath: config.get('paths:appRoot')
}),
path = require('path'), path = require('path'),
escapeChar = process.platform.match(/^win/) ? '^' : '\\', 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 // ### Validate
// **Main testing task** // **Main testing task**
// //
@ -499,7 +512,7 @@ var overrides = require('./core/server/overrides'),
// ### test-setup *(utility)( // ### test-setup *(utility)(
// `grunt test-setup` will run all the setup tasks required for running tests // `grunt test-setup` will run all the setup tasks required for running tests
grunt.registerTask('test-setup', 'Setup ready to run tests', grunt.registerTask('test-setup', 'Setup ready to run tests',
['clean:test', 'setTestEnv'] ['knex-migrator', 'clean:test', 'setTestEnv']
); );
// ### Unit Tests *(sub task)* // ### Unit Tests *(sub task)*

View file

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

View file

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

View file

@ -1,3 +1,4 @@
/*jshint expr:true*/
var Promise = require('bluebird'), var Promise = require('bluebird'),
_ = require('lodash'), _ = require('lodash'),
fs = require('fs-extra'), fs = require('fs-extra'),
@ -11,6 +12,8 @@ var Promise = require('bluebird'),
errors = require('../../server/errors'), errors = require('../../server/errors'),
db = require('../../server/data/db'), db = require('../../server/data/db'),
fixtureUtils = require('../../server/data/schema/fixtures/utils'), fixtureUtils = require('../../server/data/schema/fixtures/utils'),
schema = require('../../server/data/schema').tables,
schemaTables = Object.keys(schema),
models = require('../../server/models'), models = require('../../server/models'),
SettingsLib = require('../../server/settings'), SettingsLib = require('../../server/settings'),
permissions = require('../../server/permissions'), permissions = require('../../server/permissions'),
@ -423,7 +426,9 @@ clearData = function clearData() {
}; };
toDoList = { toDoList = {
app: function insertApp() { return fixtures.insertOne('apps', 'createApp'); }, app: function insertApp() {
return fixtures.insertOne('apps', 'createApp');
},
app_field: function insertAppField() { app_field: function insertAppField() {
// TODO: use the actual app ID to create the field // TODO: use the actual app ID to create the field
return fixtures.insertOne('apps', 'createApp').then(function () { return fixtures.insertOne('apps', 'createApp').then(function () {
@ -436,32 +441,80 @@ toDoList = {
return fixtures.insertOne('app_settings', 'createAppSetting'); return fixtures.insertOne('app_settings', 'createAppSetting');
}); });
}, },
permission: function insertPermission() { return fixtures.insertOne('permissions', 'createPermission'); }, permission: function insertPermission() {
role: function insertRole() { return fixtures.insertOne('roles', 'createRole'); }, return fixtures.insertOne('permissions', 'createPermission');
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(); }, role: function insertRole() {
'client:trusted-domain': function insertClients() { return fixtures.insertClientWithTrustedDomain(); }, return fixtures.insertOne('roles', 'createRole');
filter: function createFilterParamFixtures() { return filterData(DataGenerator); }, },
invites: function insertInvites() { return fixtures.insertInvites(); }, roles: function insertRoles() {
themes: function loadThemes() { return themes.loadAll(); } 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) { doAuth(request).then(function (token) {
request.put('/ghost/api/v0.1/settings/') request.put('/ghost/api/v0.1/settings/')
.set('Authorization', 'Bearer ' + token) .set('Authorization', 'Bearer ' + token)
.send({settings: [ .send({
settings: [
{ {
uuid: '75e994ae-490e-45e6-9207-0eab409c1c04', uuid: '75e994ae-490e-45e6-9207-0eab409c1c04',
key: 'permalinks', key: 'permalinks',
@ -643,7 +697,8 @@ togglePermalinks = function togglePermalinks(request, toggle) {
updated_at: '2014-10-20T19:44:18.077Z', updated_at: '2014-10-20T19:44:18.077Z',
updated_by: 1 updated_by: 1
} }
]}) ]
})
.end(function (err, res) { .end(function (err, res) {
if (err) { if (err) {
return reject(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) { teardown = function teardown(done) {
debug('Database reset'); debug('Database teardown');
var tables = schemaTables.concat(['migrations']);
if (done) { if (config.get('database:client') === 'sqlite3') {
knexMigrator.reset() return Promise
.then(function () { .mapSeries(tables, function createTable(table) {
done(); return db.knex.raw('DELETE FROM ' + table + ';');
}) })
.catch(done); .then(function () {
} else { done && done();
return knexMigrator.reset(); })
.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);
});
});
}; };
/** /**