Browse Source

feat: Allow testing of single spec modules (#11409)

* :wrench: ES6 for the spec

* :construction_worker: Allow testing of single modules

* :heart: Implement feedback

* :memo: Add a testing doc

* :memo: Link to it

* :memo: Cleanup
Felix Rieseberg 7 years ago
parent
commit
5f4b62b6c8
4 changed files with 101 additions and 52 deletions
  1. 3 3
      .github/config.yml
  2. 1 0
      docs/README.md
  3. 44 0
      docs/development/testing.md
  4. 53 49
      spec/static/index.html

+ 3 - 3
.github/config.yml

@@ -3,7 +3,7 @@
 # Comment to be posted to on first time issues
 newIssueWelcomeComment: |
   👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
-  
+
   To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md#submitting-issues).
 
 # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
@@ -11,7 +11,7 @@ newIssueWelcomeComment: |
 # Comment to be posted to on PRs from first time contributors in your repository
 newPRWelcomeComment: |
   💖 Thanks for opening this pull request! 💖
-  
+
   Here is a list of things that will help get it across the finish line:
   - Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
   - Run `npm run lint` locally to catch formatting errors earlier.
@@ -26,4 +26,4 @@ newPRWelcomeComment: |
 firstPRMergeComment: >
   Congrats on merging your first pull request! 🎉🎉🎉
 
-# It is recommend to include as many gifs and emojis as possiblec
+# It is recommend to include as many gifs and emojis as possible

+ 1 - 0
docs/README.md

@@ -96,6 +96,7 @@ an issue:
 
 * [Coding Style](development/coding-style.md)
 * [Using clang-format on C++ Code](development/clang-format.md)
+* [Testing](development/testing.md)
 * [Source Code Directory Structure](development/source-code-directory-structure.md)
 * [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md)
 * [Build System Overview](development/build-system-overview.md)

+ 44 - 0
docs/development/testing.md

@@ -0,0 +1,44 @@
+# Testing
+
+We aim to keep the code coverage of Electron high. We ask that all pull
+request not only pass all existing tests, but ideally also add new tests
+to cover changed code and new scenarios. Ensuring that we capture as
+many code paths and use cases of Electron as possible ensures that we
+all ship apps with fewer bugs.
+
+This repository comes with linting rules for both JavaScript and C++ –
+as well as unit and integration tests. To learn more about Electron's
+coding style, please see the [coding-style(coding-style.md) document.
+
+## Linting
+To ensure that your JavaScript is in compliance with the Electron coding
+style, run `npm run lint-js`, which will run `standard` against both
+Electron itself as well as the unit tests. If you are using an editor
+with a plugin/addon system, you might want to use one of the many
+[StandardJS addons](standard-addons) to be informed of coding style
+violations before you ever commit them.
+
+To run `standard` with parameters, run `npm run lint-js --` followed by
+arguments you want passed to `standard`.
+
+To ensure that your C++ is in compliance with the Electron coding style,
+run `npm run lint-cpp`, which runs a `cpplint` script. We recommend that
+you use `clang-format` and prepared [a short tutorial](clang-format.md).
+
+There is not a lot of Python in this repository, but it too is governed
+by coding style rules. `npm run lint-py` will check all Python, using
+`pylint` to do so.
+
+## Unit Tests
+
+To run all unit tests, run `npm run test`. The unit tests are an Electron
+app (surprise!) that can be found in the `spec` folder. Note that it has
+its own `package.json` and that its dependencies are therefore not defined
+in the top-level `package.json`.
+
+To run only a selected number of tests, run `npm run test -match=NAME`,
+replacing the `NAME` with the file name of the test suite you would like
+to run. As an example: If you want to run only IPC suites, you would run
+`npm run test -match=ipc`.
+
+[standard-addons]: https://standardjs.com/#are-there-text-editor-plugins

+ 53 - 49
spec/static/index.html

@@ -11,74 +11,77 @@
 <script type="text/javascript" charset="utf-8">
 (function() {
   // Disable use of deprecated functions.
-  process.throwDeprecation = true;
+  process.throwDeprecation = true
 
-  var path = require('path');
-  var electron = require ('electron');
-  var remote = electron.remote;
-  var ipcRenderer = electron.ipcRenderer;
+  const path = require('path')
+  const electron = require('electron')
+  const { remote, ipcRenderer } = electron
 
   // Check if we are running in CI.
-  var isCi = remote.getGlobal('isCi')
+  const isCi = remote.getGlobal('isCi')
 
   if (!isCi) {
-    var win = remote.getCurrentWindow();
-    win.show();
-    win.focus();
+    const win = remote.getCurrentWindow()
+    win.show()
+    win.focus()
   }
 
   // Show DevTools.
-  document.oncontextmenu = function(e) {
-    remote.getCurrentWindow().inspectElement(e.clientX, e.clientY);
+  document.oncontextmenu = (e) => {
+    remote.getCurrentWindow().inspectElement(e.clientX, e.clientY)
   }
 
   // Rediret all output to browser.
   if (isCi) {
-    global.__defineGetter__('console', function() {
+    global.__defineGetter__('console', function () {
       return {
-        log: function() {
-          args = Array.prototype.slice.call(arguments);
-          ipcRenderer.send('console.log', args);
-        },
-        error: function() {
-          args = Array.prototype.slice.call(arguments);
-          ipcRenderer.send('console.error', args);
-        },
+        log: (...args) => ipcRenderer.send('console.log', args),
+        error: (...args) => ipcRenderer.send('console.error', args)
       }
-    });
+    })
   }
 
-  var Coverage = require('electabul').Coverage;
+  const { Coverage } = require('electabul')
+  const Mocha = require('mocha')
 
-  var Mocha = require('mocha');
-  var mochaOpts = {};
-  if (process.env.MOCHA_REPORTER) {
-    mochaOpts.reporter = process.env.MOCHA_REPORTER;
-  }
-  var mocha = new Mocha(mochaOpts);
+  const mocha = new Mocha(process.env.MOCHA_REPORTER
+    ? { reporter: process.env.MOCHA_REPORTER }
+    : undefined)
 
   if (!process.env.MOCHA_REPORTER) {
-    mocha.ui('bdd').reporter(isCi ? 'tap' : 'html');
+    mocha.ui('bdd').reporter(isCi ? 'tap' : 'html')
   }
   mocha.timeout(isCi ? 30000 : 10000)
 
-  var query = Mocha.utils.parseQuery(window.location.search || '');
-  if (query.grep) mocha.grep(query.grep);
-  if (query.invert) mocha.invert();
+  const query = Mocha.utils.parseQuery(window.location.search || '')
+  if (query.grep) mocha.grep(query.grep)
+  if (query.invert) mocha.invert()
 
   // Read all test files.
-  var walker = require('walkdir').walk(path.dirname(__dirname), {
+  const walker = require('walkdir').walk(path.dirname(__dirname), {
     no_recurse: true
-  });
+  })
+
+  const crashSpec = 'api-crash-reporter-spec.js'
+
+  // This allows you to run specific modules only:
+  // npm run test -match=menu
+  const moduleMatch = process.env.npm_config_match
+    ? new RegExp(process.env.npm_config_match, 'g')
+    : /.*/gi
 
-  walker.on('file', function(file) {
-    if (/-spec\.js$/.test(file) && !file.includes('api-crash-reporter-spec.js'))
-      mocha.addFile(file);
-  });
+  walker.on('file', (file) => {
+    if (/-spec\.js$/.test(file) && moduleMatch.test(file) && !file.includes(crashSpec)) {
+      mocha.addFile(file)
+    }
+  })
 
-  walker.on('end', function() {
-    mocha.addFile(path.resolve(__dirname, '..', 'api-crash-reporter-spec.js'))
-    var runner = mocha.run(function() {
+  walker.on('end', () => {
+    if (!process.env.npm_config_match || new RegExp(process.env.npm_config_match, 'g').test(crashSpec)) {
+      mocha.addFile(path.resolve(__dirname, '..', crashSpec))
+    }
+
+    const runner = mocha.run(() => {
       if (isCi && runner.hasOnly) {
         try {
           throw new Error('A spec contains a call to it.only or describe.only and should be reverted.')
@@ -89,21 +92,22 @@
         return
       }
 
-      Mocha.utils.highlightTags('code');
+      Mocha.utils.highlightTags('code')
 
-      var coverage = new Coverage({
+      const coverage = new Coverage({
         libPath: path.join(__dirname, '..', '..', 'lib'),
         outputPath: path.join(__dirname, '..', '..', 'out', 'coverage'),
         formats: ['text', 'lcov']
-      });
+      })
       coverage.addCoverage(ipcRenderer.sendSync('get-main-process-coverage'))
       coverage.generateReport()
 
-      if (isCi)
-        ipcRenderer.send('process.exit', runner.failures);
-    });
-  });
-})();
+      if (isCi) {
+        ipcRenderer.send('process.exit', runner.failures)
+      }
+    })
+  })
+})()
 </script>
 </body>
 </html>