docs: function getTools (_this, options) {
    options = _.extend({
      dataFolder: path.join(process.cwd(), 'test', 'data'),
      appFolder: null,
      publicFolder: null,
      pluginsFolder: null,
      extraDataAndMethods: {}
    }, options);
  
    var tools = {},
      testDataFolder = path.normalize(options.dataFolder);
  
    tools.appFolder = options.appFolder || path.join(testDataFolder, 'src');
    tools.publicFolder = options.publicFolder || path.join(testDataFolder, 'public');
    tools.pluginsFolder = options.pluginsFolder || path.join(process.cwd(), 'node_modules');
  
    /**
     * Generator utility methods.
     */
    _.extend(tools, genomatic);
  
    /**
     * Write a file.
     *
     * @param {String} filePath Path to file.
     * @param {String} contents File contents
     */
    tools.writeFile = function(filePath, contents) {
      let dir = path.dirname(filePath);
  
      tools.createFolder(dir);
  
      fs.writeFileSync(filePath, contents);
    };
  
  
  
    /**
     * Read a file.
     *
     * @param {String} filePath Path to file.
     */
    tools.readFile = function(filePath) {
      return fs.readFileSync(filePath, { encoding: 'utf8' }).toString();
    };
  
  
  
    /**
     * Check if a file exists
     *
     * @param {String} filePath Path to file.
     *
     * @return {Boolean} true if exists, false otherwise
     */
    tools.fileExists = function(filePath) {
      try {
        fs.accessSync(filePath, fs.F_OK);
        return true;
      } catch (err) {
        return false;
      }
    };
  
  
  
  
    /**
     * Delete a file.
     *
     * @param {String} filePath Path to file.
     */
    tools.deleteFile = function(filePath) {
      fs.unlinkSync(filePath);
    };
  
  
  
  
  
    /**
     * Chmod a file.
     *
     * @param {String} filePath Path to file.
     * @param {String} mode The chmod mode to set.
     */
    tools.chmodFile = function(filePath, mode) {
      fs.chmodSync(filePath, mode);
    };
  
  
  
  
    /**
     * Create a folder and its intermediate folders.
     *
     * @param {String} folder Folder to create.
     *
     * @return {Promise}
     */
    tools.createFolder = function(folder) {
      shell.mkdir('-p', folder);
    };
  
  
  
    /**
     * Delete a folder.
     *
     * @param {String} folder Folder to delete
     *
     * @return {Promise}
     */
    tools.deleteFolder = function(folder) {
      shell.rm('-rf', folder);
    };
  
  
  
  
    /**
     * Create test folders.
     */
    tools.createTestFolders = function() {
      /*
      node-findit fails to finish for empty directories, so we create dummy files to prevent this
      https://github.com/substack/node-findit/pull/26
       */
      tools.createFolder(tools.appFolder);
      tools.createFolder(tools.publicFolder);
      tools.writeFile(path.join(tools.appFolder, 'README'), 'The presence of this file ensures that node-findit works');
    };
  
  
  
  
    /**
     * Delete test folders.
     */
    tools.deleteTestFolders = function() {
      tools.deleteFolder(tools.publicFolder);
      tools.deleteFolder(tools.appFolder);
  
      let files = fs.readdirSync(tools.pluginsFolder);
  
      let plugins = _.filter(files, function(file) {
        return file.endsWith('_TESTPLUGIN');
      });
  
      _.each(plugins, function(plugin) {
        tools.deleteFolder(path.join(tools.pluginsFolder, plugin));
      })
    };
  
  
  
  
  
  
    /**
     * Create modules within given test plugin.
     *
     * The content of each created module will be a string containing the plugin name.
     *
     * @param name {String} name of plugin to create. Should be suffixed with '_TESTPLUGIN';
     * @param [modules] {Array|Object} CommonJS modules to create within the plugin.
     */
    tools.createPluginModules = function(name, modules) {
      if (!name.endsWith('_TESTPLUGIN')) {
        throw new Error('Test plugin name has incorrect suffix');
      }
  
      var pluginFolderPath = path.join(tools.pluginsFolder, name),
        publicFolderPath = path.join(pluginFolderPath, 'public'),
        srcFolderPath = path.join(pluginFolderPath, 'src');
  
      tools.createFolder(pluginFolderPath);
  
      tools.writeFile(path.join(pluginFolderPath, 'package.json'), '{ "name": "' + name + '", "version": "0.0.1" }');
      tools.writeFile(path.join(pluginFolderPath, 'index.js'), 'module.exports = {}');
  
      tools.createFolder(publicFolderPath);
      tools.createFolder(srcFolderPath);
  
      tools.writeFile(path.join(srcFolderPath, 'README'), 'The presence of this file ensures that node-findit works');
  
      tools.createModules(srcFolderPath, modules, name);
    };
  
  
  
  
    /**
     * Create modules in the app folder tree.
     *
     * @param [modules] {Array|Object} CommonJS modules to create within the app.
     */
    tools.createAppModules = function(modules) {
      tools.createModules(tools.appFolder, modules, 'app');
    };
  
  
  
  
  
  
    /**
     * Create modules.
     *
     * @param srcFolder {String} folder in which to create the module. Expected to exist.
     * @param modules {Object|Array} CommonJS modules to create.
     * @param defaultContent {String} the default content to use for a module if none provided.
     */
    tools.createModules = function(srcFolder, modules, defaultContent) {
      if (modules) {
        // if an array then generate default module content
        if (_.isArray(modules)) {
          var moduleContent = _.map(modules, function(moduleName) {
            return 'module.exports="' + defaultContent + '";';
          });
  
          modules = _.zipObject(modules, moduleContent);
        }
  
        var __createModule = function(moduleName, moduleContent) {
          var extName = path.extname(moduleName);
  
          if (!extName.length) {
            extName = '.js';
          }
  
          var fileName = path.join(srcFolder, moduleName) + extName,
            folderPath = path.dirname(fileName);
  
          tools.createFolder(folderPath);
  
          tools.writeFile(fileName, moduleContent);
        };
  
        // sequentially create each module - this avoids conflicting async calls to mkdir() for the same folder
        _.each(modules, function(moduleContent, moduleName) {
          __createModule(moduleName, modules[moduleName]);
        });
  
      } // if modules set
    };
  
  
    /**
     * Write test package.json file.
     * @param  {String} contents File contents.
     */
    tools.writePackageJson = function(contents) {
      tools.writeFile(
        path.join(tools.appFolder, '..', 'package.json'),
        contents
      );
    };
  
  
    /**
     * Delete test package.json file.
     */
    tools.deletePackageJson = function() {
      var fp = path.join(tools.appFolder, '..', 'package.json');
  
      shell.rm('-f', fp);
    };
  
  
  
    tools.clearDb = function*() {
      let models;
  
      let modelNames = _.flatten(_.toArray(arguments));
  
      if (modelNames.length) {
        models = modelNames;
      } else {
        models = _.keys(this.App.models);
      }
  
      for (let model of models) {
        yield this.App.models[model].rawQry().delete().run();
      }
    };
  
  
  
    tools.initApp = function*(initOptions) {
      waigo.reset();
  
      yield waigo.init(_.extend({
        appFolder: this.appFolder,
      }, initOptions));
  
      waigo.App = this.App = new (waigo.load('application'));
    };
  
  
  
    tools.startApp = function*(config) {
      config = _.extend({
        port: 33211,
        baseURL: 'http://localhost:33211',
        logging: {
          category: "test",
          minLevel: 'DEBUG',
          appenders: [],
        },
        db: {
          main: {
            type: 'rethinkdb',
            serverConfig: {
              db: 'waigo_test',
              servers: [
                {
                  host: '127.0.0.1',
                  port: 28015,
                },
              ],
            },
          },
        },
      }, config);
  
      yield this.App.start({
        postConfig: (cfg) => {
          _.extend(cfg, config);
        },
      });
    };
  
  
  
    tools.shutdownApp = function*() {
      if (this.App) {
        yield this.App.shutdown();
      }
    };
  
  
  
    tools.fetch = function(url, options) {
      if ('/' !== url.charAt(0)) {
        url = `/${url}`;
      }
  
      return got(this.App.config.baseURL + url, options);
    };
  
  
  
  
  
    let extra = options.extraDataAndMethods;
  
    for (let k in extra) {
      tools[k] = _.isFunction(extra[k])
        ? genomatic.bind(extra[k], _this)
        : extra[k];
    }
  
    return tools;
  }