function testFile(filename, opts) {
  const filenameObj = path.parse(filename.toLowerCase());

  // Check if the file is an extension we skip
  if (EXTENSIONS_TO_SKIP.indexOf(filenameObj.ext) >= 0) {
    if (global.WF.options.verbose) {
      const msg = 'Skipped (extension).';
      gutil.log(chalk.gray('SKIP:'), chalk.cyan(filename), msg);
    }
    return Promise.resolve(false);
  }

  // Check media files & verify they're not too big
  if (MEDIA_FILES.indexOf(filenameObj.ext) >= 0) {
    if (opts.ignoreFileSize) {
      return Promise.resolve(false);
    }
    const warnOnly = IS_TRAVIS && IS_TRAVIS_ON_MAIN;
    return validateMedia.test(filename, warnOnly);
  }

  // Attempt to read the file contents
  let contents = readFile(filename);
  if (!contents) {
    return Promise.resolve(false);
  }

  // Check if the file has the wf_ignore_file attribute, if so, skip tests.
  if (wfRegEx.RE_IGNORE_FILE.test(contents)) {
    if (!opts.hideIgnored) {
      const msg = `Skipped (wf_ignore_file).`;
      logWarning(filename, null, msg);
    }
    return Promise.resolve(false);
  }

  // Check if the file is auto-generated, if it is, ignore it
  if (wfRegEx.RE_AUTO_GENERATED.test(contents)) {
    if (global.WF.options.verbose) {
      const msg = `Skipped (auto-generated).`;
      gutil.log(chalk.gray('SKIP:'), chalk.cyan(filename), msg);
    }
    return Promise.resolve(false);
  }

  // Check the app.yaml file
  if (filenameObj.base === 'app.yaml') {
    logWarning(filename, null, `'app.yaml' was changed, was that intentional?`);
    return validateYaml.test(filename, contents);
  }

  // Check the contributors file
  if (filenameObj.base === '_contributors.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => testContributors.test(filename, parsed));
  }

  // Check the contributors file
  if (filenameObj.base === 'common-typos.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => validateCommonTyposFile.test(filename, parsed));
  }

  // Check the glossary file
  if (filenameObj.base === 'glossary.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => testGlossary.test(filename, parsed));
  }

  // Check the redirects file
  if (filenameObj.base === '_redirects.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => testRedirects.test(filename, parsed));
  }

  // Check the project.yaml file
  if (filenameObj.base === '_project.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => testProject.test(filename, parsed));
  }

  // Check _book.yaml & _toc.yaml files
  if (filenameObj.base === '_book.yaml' ||
      filenameObj.base.endsWith('_toc.yaml')) {
    return validateYaml.test(filename, contents)
      .then((parsed) => testBook.test(filename, parsed));
  }

  // Check the common tags file
  if (filenameObj.base === 'commontags.json') {
    return validateJson.test(filename, contents)
      .then((parsed) => testCommonTags.test(filename, parsed));
  }

  // Check & validate the Gulp JavaScript files
  if (RE_GULP_BASE.test(filenameObj.dir) ||
      filenameObj.base === 'gulpfile.js') {
    return lintJavaScript.test(filename, esLintConfig, contents);
  }

  // Check markdown files
  if (MD_FILES.indexOf(filenameObj.ext) >= 0) {
    return validateMarkdown.test(filename, contents, opts);
  }

  // Check HTML files
  if (filenameObj.ext === '.html') {
    return validateHtml.test(filename, contents, opts);
  }

  // Check YAML files
  if (filenameObj.ext === '.yaml') {
    return validateYaml.test(filename, contents)
      .then((parsed) => {
        // Not all _toc.yaml files will be named _toc.yaml, so if it has a
        // toc element, treat it as a _toc.yaml file.
        if (parsed.toc) {
          return testBook.test(filename, parsed);
        }
      });
  }

  // Check JSON files
  if (filenameObj.ext === '.json') {
    return validateJson.test(filename, contents);
  }

  // Check JS files
  if (opts.warnOnJavaScript && filenameObj.ext === '.js') {
    return validateJavaScript.test(filename, contents);
  }

  // Check any stray files
  return validateGeneric.test(filename, contents);
}
Tests & validates a file.
  Note: The returned promise always resolves, it will never reject.

@param {string} filename The name of the file to be tested.
@param {Object} opts Options for testing the file
@return {Promise} A promise that resolves after the tests have completed.