Add --main-process flag to run specs in the main process

…so that we can write unit tests for code in the main process. Below a
list of conventions we'll be adopting:

1. Use mocha as the test framework.
2. Use chai as the assertion library.
3. Name specs `foo-bar.spec.js`, to prevent the renderer process from
running specs written fro the main process e.g. when calling
`atom --test spec`.
4. Write specs in ES6.

Although somewhat inconsistent with the conventions we use for renderer
process specs, this will hopefully be a first step towards migrating our
entire Jasmine 1.3 test suite to a more modern environment.
This commit is contained in:
Antonio Scandurra
2016-05-24 08:23:27 +02:00
parent 720ad9c0b4
commit 62d48c64ea
4 changed files with 75 additions and 7 deletions

View File

@@ -93,13 +93,37 @@ module.exports = (grunt) ->
env: _.extend({}, process.env, {ELECTRON_ENABLE_LOGGING: true, ATOM_INTEGRATION_TESTS_ENABLED: true})
stdio: 'inherit'
grunt.log.ok "Launching core specs."
grunt.log.ok "Launching core specs (renderer process)."
spawn options, (error, results, code) ->
if process.platform is 'win32'
process.stderr.write(fs.readFileSync('ci.log')) if error
fs.unlinkSync('ci.log')
else
# TODO: Restore concurrency on Windows
callback(null, error)
runMainProcessSpecs = (callback) ->
appPath = getAppPath()
resourcePath = process.cwd()
mainProcessSpecsPath = path.resolve('spec/browser')
if process.platform in ['darwin', 'linux']
options =
cmd: appPath
args: ["--test", "--main-process", "--resource-path=#{resourcePath}", mainProcessSpecsPath]
opts:
env: process.env
stdio: 'inherit'
else if process.platform is 'win32'
options =
cmd: process.env.comspec
args: ['/c', appPath, "--test", "--main-process", "--resource-path=#{resourcePath}", mainProcessSpecsPath]
opts:
env: process.env
stdio: 'inherit'
grunt.log.ok "Launching core specs (main process)."
spawn options, (error, results, code) ->
if process.platform isnt 'windows'
packageSpecQueue?.concurrency = concurrency
callback(null, error)
@@ -117,9 +141,9 @@ module.exports = (grunt) ->
if process.env.ATOM_SPECS_TASK is 'packages'
[runPackageSpecs]
else if process.env.ATOM_SPECS_TASK is 'core'
[runCoreSpecs]
[runCoreSpecs, runMainProcessSpecs]
else
[runCoreSpecs, runPackageSpecs]
[runCoreSpecs, runMainProcessSpecs, runPackageSpecs]
method specs, (error, results) ->
failedPackages = []

View File

@@ -177,5 +177,9 @@
"waitsForPromise",
"indexedDB"
]
},
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^2.5.1"
}
}

View File

@@ -0,0 +1,31 @@
"use babel"
import Mocha from 'mocha'
import fs from 'fs-plus'
import {assert} from 'chai'
import util from 'util'
export default function (testPaths) {
global.assert = assert
const mocha = new Mocha({reporter: 'dot'})
for (let testPath of testPaths) {
if (fs.isDirectorySync(testPath)) {
for (let testFilePath of fs.listTreeSync(testPath)) {
if (/\.spec\.(coffee|js)$/.test(testFilePath)) {
mocha.addFile(testFilePath)
}
}
} else {
mocha.addFile(testPath)
}
}
mocha.run(function (failures) {
if (failures === 0) {
process.exit(0)
} else {
process.exit(1)
}
})
}

View File

@@ -9,6 +9,7 @@ fs = require 'fs-plus'
path = require 'path'
temp = require 'temp'
yargs = require 'yargs'
previousConsoleLog = console.log
console.log = require 'nslog'
start = ->
@@ -16,7 +17,13 @@ start = ->
args.env = process.env
setupAtomHome(args)
setupCompileCache()
return if handleStartupEventWithSquirrel()
if handleStartupEventWithSquirrel()
return
else if args.test and args.mainProcess
console.log = previousConsoleLog
resourcePath = if fs.existsSync(args.devResourcePath) then args.devResourcePath else require.resolve('../..')
require(path.join(args.devResourcePath, 'spec/browser/mocha-test-runner'))(args.pathsToOpen)
return
# NB: This prevents Win10 from showing dupe items in the taskbar
app.setAppUserModelId('com.squirrel.atom.atom')
@@ -130,6 +137,7 @@ parseCommandLine = ->
options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.')
options.boolean('portable').describe('portable', 'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.')
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('m', 'main-process').boolean('m').describe('m', 'Run the specified specs in the main process.')
options.string('timeout').describe('timeout', 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).')
options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
@@ -154,6 +162,7 @@ parseCommandLine = ->
safeMode = args['safe']
pathsToOpen = args._
test = args['test']
mainProcess = args['main-process']
timeout = args['timeout']
newWindow = args['new-window']
pidToKillWhenClosed = args['pid'] if args['wait']
@@ -186,6 +195,6 @@ parseCommandLine = ->
{resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test,
version, pidToKillWhenClosed, devMode, safeMode, newWindow,
logFile, socketPath, userDataDir, profileStartup, timeout, setPortable,
clearWindowState, addToLastWindow}
clearWindowState, addToLastWindow, mainProcess}
start()