mirror of
https://github.com/meteor/meteor.git
synced 2026-01-09 07:38:15 -05:00
Rename test-app -> test and test --full-app
Our old "unit" test mode didn't really enforce "unit-ness" and was perfectly capable of running integration test. So it was confusing to call the two modes unit and integration test modes. Instead, we call them "test mode" and "full app test mode", run with `meteor test` and `meteor test --full-app`. The rules for test files were also simplified -- simply *.test[s].* for test mode, and *.app-test[s].* for full app tests. `tests/` directories are simply ignored again.
This commit is contained in:
@@ -160,7 +160,7 @@
|
||||
### Testing
|
||||
|
||||
* Packages can now be marked as `testOnly` to only run as part of app
|
||||
testing with `meteor test-app`. This is achieved by setting
|
||||
testing with `meteor test`. This is achieved by setting
|
||||
`testOnly: true` to `Package.describe`.
|
||||
|
||||
|
||||
|
||||
@@ -1421,7 +1421,7 @@ main.registerCommand({
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test-app and test-packages
|
||||
// test and test-packages
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testCommandOptions = {
|
||||
@@ -1479,20 +1479,19 @@ testCommandOptions = {
|
||||
'exclude': { type: String },
|
||||
|
||||
// one of the following must be true
|
||||
'test-app': { type: Boolean, 'default': false },
|
||||
'test': { type: Boolean, 'default': false },
|
||||
'test-packages': { type: Boolean, 'default': false },
|
||||
|
||||
// For 'test-packages': Run in unit test or integration test mode
|
||||
'unit': { type: Boolean, 'default': false },
|
||||
'integration': { type: Boolean, 'default': false }
|
||||
// For 'test-packages': Run in "full app" mode
|
||||
'full-app': { type: Boolean, 'default': false }
|
||||
}
|
||||
};
|
||||
|
||||
main.registerCommand(_.extend({
|
||||
name: 'test-app',
|
||||
name: 'test',
|
||||
requiresApp: true
|
||||
}, testCommandOptions), function (options) {
|
||||
options['test-app'] = true;
|
||||
options['test'] = true;
|
||||
return doTestCommand(options);
|
||||
});
|
||||
|
||||
@@ -1590,7 +1589,7 @@ function doTestCommand(options) {
|
||||
}
|
||||
|
||||
// Use the driver package if running `meteor test-packages`. For
|
||||
// `meteor test-app`, the driver package is expected to already
|
||||
// `meteor test`, the driver package is expected to already
|
||||
// have been added to the app.
|
||||
packagesToAdd.unshift(global.testCommandMetadata.driverPackage);
|
||||
|
||||
@@ -1612,24 +1611,16 @@ function doTestCommand(options) {
|
||||
// the project for build hits errors, we don't lose them on
|
||||
// projectContext.reset.
|
||||
projectContext.projectConstraintsFile.writeIfModified();
|
||||
} else if (options["test-app"]) {
|
||||
} else if (options["test"]) {
|
||||
if (!options['driver-package']) {
|
||||
throw new Error("You must specify a driver package with --driver-package");
|
||||
}
|
||||
|
||||
global.testCommandMetadata.driverPackage = options['driver-package'];
|
||||
|
||||
// Default to `--integration`
|
||||
if (!options.unit && !options.integration) {
|
||||
options.integration = true;
|
||||
}
|
||||
|
||||
if (options.unit && options.integration) {
|
||||
throw new Error("Can't pass both --unit and --integration");
|
||||
}
|
||||
global.testCommandMetadata.isUnitTest = options.unit;
|
||||
global.testCommandMetadata.isIntegrationTest = options.integration;
|
||||
|
||||
global.testCommandMetadata.isAppTest = options['full-app'];
|
||||
global.testCommandMetadata.isTest = !global.testCommandMetadata.isAppTest;
|
||||
|
||||
projectContextOptions.projectDir = options.appDir;
|
||||
projectContextOptions.projectLocalDir = files.pathJoin(testRunnerAppDir, '.meteor', 'local');
|
||||
|
||||
@@ -1664,7 +1655,7 @@ function doTestCommand(options) {
|
||||
projectContext.initializeCatalog();
|
||||
});
|
||||
} else {
|
||||
throw new Error("Unexpected: neither test-packages nor test-app");
|
||||
throw new Error("Unexpected: neither test-packages nor test");
|
||||
}
|
||||
|
||||
// The rest of the projectContext preparation process will happen inside the
|
||||
@@ -1761,10 +1752,10 @@ var runTestAppForPackages = function (projectContext, options) {
|
||||
};
|
||||
if (options["test-packages"]) {
|
||||
buildOptions.buildMode = buildOptions.minifyMode;
|
||||
} else if (options["test-app"]) {
|
||||
} else if (options["test"]) {
|
||||
buildOptions.buildMode = "test";
|
||||
} else {
|
||||
throw new Error("Neither test-packages nor test-app in options");
|
||||
throw new Error("Neither test-packages nor test in options");
|
||||
}
|
||||
|
||||
if (options.deploy) {
|
||||
|
||||
@@ -536,27 +536,25 @@ Options:
|
||||
--verbose Print all output from builds logs.
|
||||
--no-lint Don't run linters used by the tested packages on every
|
||||
test app rebuild.
|
||||
>>> test-app
|
||||
>>> test
|
||||
Test the application
|
||||
Usage: meteor test-app --driver-package <driver> [options]
|
||||
meteor test-app --driver-package <driver> --unit [options]
|
||||
meteor test-app --driver-package <driver> --integration [options]
|
||||
Usage: meteor test --driver-package <driver> [options]
|
||||
meteor test --full-app --driver-package <driver> [options]
|
||||
|
||||
Runs tests against the application, either in *unit* or *integration*
|
||||
(the default) test mode. meteor test-app will start a special app based on
|
||||
a test driver (specified with --driver-package -- read more about driver
|
||||
packages at http://guide.meteor.com/testing.html#driver-packages)
|
||||
which handles the task of running tests and displaying the results in the
|
||||
browser when you visit it.
|
||||
Runs tests against the application.
|
||||
Will start a special app based on a test driver (specified with
|
||||
--driver-package -- read more about driver packages at
|
||||
http://guide.meteor.com/testing.html#driver-packages) which handles the
|
||||
task of running tests and displaying the results in the browser when you
|
||||
visit it.
|
||||
|
||||
In unit test mode, no files in your application are eagerly loaded, aside
|
||||
from test files (in you tests/ directory or named test[s].* or *.test[s].*).
|
||||
In normal test mode, no files in your application are eagerly loaded, aside
|
||||
from test files (files named *.test[s].* placed anywhere in your application).
|
||||
You can import your app's modules from within your tests and test them in
|
||||
isolation.
|
||||
|
||||
In integration test mode, your app is loaded as usual, and then made hidden,
|
||||
In "full app" test mode, your app is loaded as usual, and then made hidden,
|
||||
and your tests can inspect and effect the running state. Test files are
|
||||
loaded similarly to unit test mode.
|
||||
loaded similarly to unit test mode, but must be called *.app-test[s].*.
|
||||
|
||||
Open the test dashboard in your browser to run the tests and see the
|
||||
results. By default the URL is localhost:3000 but that can be changed
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import _ from 'underscore';
|
||||
import { pathSep } from '../fs/files';
|
||||
|
||||
export const TEST_FILENAME_REGEXPS = [
|
||||
// "*.test.*" or "*.tests.*"
|
||||
/\.tests?./,
|
||||
// "test.*" or "tests.*"
|
||||
/^tests?./
|
||||
];
|
||||
|
||||
// Specific filename paths for unit or integration tests.
|
||||
// Note that imporatantly they both pass the TEST_FILENAME_REGEXPS above
|
||||
export const UNIT_TEST_FILENAME_REGEXPS = [
|
||||
// "*.unit.test.*" or "*.unit.tests.*"
|
||||
/\.unit\.tests?./,
|
||||
];
|
||||
|
||||
export const INTEGRATION_TEST_FILENAME_REGEXPS = [
|
||||
// "*.integration.test.*" or "*.integration.tests.*"
|
||||
/\.integration\.tests?./,
|
||||
];
|
||||
|
||||
export const TEST_DIRNAME_REGEXPS = [
|
||||
// a directory exactly named "tests"
|
||||
/^tests\/$/
|
||||
];
|
||||
|
||||
// Given a path to a file in an app (relative to the app root
|
||||
// directory), is this file a test file?
|
||||
export function isTestFilePath(path) {
|
||||
const splitPath = path.split(pathSep);
|
||||
|
||||
// Does any path of the path other than the filename match one of
|
||||
// the test dirname forms?
|
||||
const inTestsDir = _.any(
|
||||
_.initial(splitPath),
|
||||
dirname => _.any(
|
||||
TEST_DIRNAME_REGEXPS,
|
||||
regexp => regexp.test(dirname)));
|
||||
|
||||
// Does the filename match one of the test filename forms?
|
||||
const isTestFilename = _.any(
|
||||
TEST_FILENAME_REGEXPS,
|
||||
regexp => regexp.test(_.last(splitPath)));
|
||||
|
||||
return inTestsDir || isTestFilename;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import Fiber from 'fibers';
|
||||
import {sourceMapLength} from '../utils/utils.js';
|
||||
import ImportScanner from './import-scanner.js';
|
||||
|
||||
import { isTestFilePath } from './app-test-files.js';
|
||||
import { isTestFilePath } from './test-files.js';
|
||||
|
||||
// This file implements the new compiler plugins added in Meteor 1.2, which are
|
||||
// registered with the Plugin.registerCompiler API.
|
||||
@@ -385,7 +385,7 @@ class ResourceSlot {
|
||||
// it is contained by an imports directory. Note that any files
|
||||
// contained by a node_modules directory will already have been
|
||||
// marked lazy in PackageSource#_inferFileOptions. Same for
|
||||
// non-test files if running unit tests (`meteor test-app --unit`)
|
||||
// non-test files if running (non-full-app) tests (`meteor test`)
|
||||
if (!this.packageSourceBatch.useMeteorInstall) {
|
||||
return false;
|
||||
}
|
||||
@@ -394,8 +394,8 @@ class ResourceSlot {
|
||||
const isInImports = splitPath.indexOf("imports") >= 0;
|
||||
|
||||
if (global.testCommandMetadata &&
|
||||
(global.testCommandMetadata.isUnitTest ||
|
||||
global.testCommandMetadata.isIntegrationTest)) {
|
||||
(global.testCommandMetadata.isTest ||
|
||||
global.testCommandMetadata.isAppTest)) {
|
||||
// test files should always be included, if we're running app
|
||||
// tests.
|
||||
return isInImports && !isTestFilePath(this.inputResource.path);
|
||||
|
||||
@@ -974,7 +974,7 @@ export var fullLink = Profile("linker.fullLink", function (inputFiles, {
|
||||
|
||||
var prelinkedFiles = module.getPrelinkedFiles();
|
||||
|
||||
// are we running `meteor test-app` or `meteor test-packages`?
|
||||
// are we running `meteor test` or `meteor test-packages`?
|
||||
// Include a short code snippet that sets `Meteor.isTest` and calls
|
||||
// `runTests`.
|
||||
if (global.testCommandMetadata) {
|
||||
@@ -1073,16 +1073,15 @@ export var fullLink = Profile("linker.fullLink", function (inputFiles, {
|
||||
function getTestPreamble() {
|
||||
const testDriverPackageName = global.testCommandMetadata.driverPackage;
|
||||
|
||||
let setMeteorIntegrationOrUnitTest = "";
|
||||
if (global.testCommandMetadata.isUnitTest) {
|
||||
setMeteorIntegrationOrUnitTest = "Package.meteor.Meteor.isUnitTest = true;";
|
||||
} else if (global.testCommandMetadata.isIntegrationTest) {
|
||||
setMeteorIntegrationOrUnitTest = "Package.meteor.Meteor.isIntegrationTest = true;";
|
||||
let setMeteorTest = "";
|
||||
if (global.testCommandMetadata.isTest) {
|
||||
setMeteorTest = "Package.meteor.Meteor.isTest = true;";
|
||||
} else if (global.testCommandMetadata.isAppTest) {
|
||||
setMeteorTest = "Package.meteor.Meteor.isAppTest = true;";
|
||||
}
|
||||
|
||||
return `\
|
||||
Package.meteor.Meteor.isTest = true;
|
||||
${setMeteorIntegrationOrUnitTest}
|
||||
${setMeteorTest}
|
||||
|
||||
if (Package.meteor.Meteor.isClient) {
|
||||
Package.meteor.Meteor.startup(function() {
|
||||
|
||||
@@ -19,10 +19,8 @@ import SourceArch from './source-arch.js';
|
||||
|
||||
import {
|
||||
TEST_FILENAME_REGEXPS,
|
||||
UNIT_TEST_FILENAME_REGEXPS,
|
||||
INTEGRATION_TEST_FILENAME_REGEXPS,
|
||||
TEST_DIRNAME_REGEXPS,
|
||||
isTestFilePath } from './app-test-files.js';
|
||||
APP_TEST_FILENAME_REGEXPS,
|
||||
isTestFilePath } from './test-files.js';
|
||||
|
||||
// XXX: This is a medium-term hack, to avoid having the user set a package name
|
||||
// & test-name in package.describe. We will change this in the new control file
|
||||
@@ -318,7 +316,7 @@ var PackageSource = function () {
|
||||
self.prodOnly = false;
|
||||
|
||||
// A package marked testOnly is ONLY picked up by the bundler as
|
||||
// part of the `meteor test-app` command.
|
||||
// part of the `meteor test` command.
|
||||
self.testOnly = false;
|
||||
|
||||
// If this is set, we will take the currently running git checkout and bundle
|
||||
@@ -533,7 +531,7 @@ _.extend(PackageSource.prototype, {
|
||||
* @param {Boolean} options.prodOnly A package with this flag set to true
|
||||
* will ONLY be bundled into production builds.
|
||||
* @param {Boolean} options.testOnly A package with this flag set to true
|
||||
* will ONLY be bundled as part of `meteor test-app`.
|
||||
* will ONLY be bundled as part of `meteor test`.
|
||||
*/
|
||||
describe: function (options) {
|
||||
_.each(options, function (value, key) {
|
||||
@@ -591,7 +589,7 @@ _.extend(PackageSource.prototype, {
|
||||
// when set to true, they cause a package's code to be
|
||||
// only included (i.e. linked into the bundle) in dev
|
||||
// mode, prod mode (`meteor --production`) or app tests
|
||||
// (`meteor test-app`), and excluded otherwise.
|
||||
// (`meteor test`), and excluded otherwise.
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
@@ -1349,9 +1347,9 @@ _.extend(PackageSource.prototype, {
|
||||
fileOptions.transpile = false;
|
||||
}
|
||||
|
||||
// If running in unit test mode (`meteor test-app --unit`), all
|
||||
// If running in test mode (`meteor test`), all
|
||||
// files other than test files should be loaded lazily
|
||||
if (global.testCommandMetadata && global.testCommandMetadata.isUnitTest) {
|
||||
if (global.testCommandMetadata && global.testCommandMetadata.isTest) {
|
||||
if (!isTestFilePath(relPath)) {
|
||||
fileOptions.lazy = true;
|
||||
}
|
||||
@@ -1393,12 +1391,11 @@ _.extend(PackageSource.prototype, {
|
||||
|
||||
// Unless we're running tests, ignore all test filenames and if we are, ignore the
|
||||
// type of file we *aren't* running
|
||||
if (!global.testCommandMetadata) {
|
||||
if (!global.testCommandMetadata || global.testCommandMetadata.isTest) {
|
||||
Array.prototype.push.apply(sourceReadOptions.exclude, APP_TEST_FILENAME_REGEXPS);
|
||||
}
|
||||
if (!global.testCommandMetadata || global.testCommandMetadata.isAppTest) {
|
||||
Array.prototype.push.apply(sourceReadOptions.exclude, TEST_FILENAME_REGEXPS);
|
||||
} else if (global.testCommandMetadata.isUnitTest) {
|
||||
Array.prototype.push.apply(sourceReadOptions.exclude, INTEGRATION_TEST_FILENAME_REGEXPS);
|
||||
} else if (global.testCommandMetadata.isIntegrationTest) {
|
||||
Array.prototype.push.apply(sourceReadOptions.exclude, UNIT_TEST_FILENAME_REGEXPS);
|
||||
}
|
||||
|
||||
// Read top-level source files, excluding control files that were not
|
||||
@@ -1418,14 +1415,11 @@ _.extend(PackageSource.prototype, {
|
||||
|
||||
const anyLevelExcludes = [
|
||||
/^node_modules\/$/,
|
||||
/^tests\/$/,
|
||||
arch === "os" ? /^client\/$/ : /^server\/$/,
|
||||
...sourceReadOptions.exclude,
|
||||
];
|
||||
|
||||
if (!global.testCommandMetadata) {
|
||||
Array.prototype.push.apply(anyLevelExcludes, TEST_DIRNAME_REGEXPS);
|
||||
}
|
||||
|
||||
const topLevelExcludes = isApp ? [
|
||||
...anyLevelExcludes,
|
||||
/^packages\/$/,
|
||||
|
||||
24
tools/isobuild/test-files.js
Normal file
24
tools/isobuild/test-files.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import _ from 'underscore';
|
||||
import { pathSep } from '../fs/files';
|
||||
|
||||
// We have two things "tests" and "app-tests".
|
||||
export const TEST_FILENAME_REGEXPS = [
|
||||
// "*.unit.test.*" or "*.tests.*"
|
||||
/\.tests?./,
|
||||
];
|
||||
|
||||
export const APP_TEST_FILENAME_REGEXPS = [
|
||||
// "*.integration.test.*" or "*.app-tests.*"
|
||||
/\.app-tests?./,
|
||||
];
|
||||
|
||||
// Given a path to a file in an app (relative to the app root
|
||||
// directory), is this file a test file?
|
||||
export function isTestFilePath(path) {
|
||||
const splitPath = path.split(pathSep);
|
||||
|
||||
// Does the filename match one of the test filename forms?
|
||||
return _.any(
|
||||
[...TEST_FILENAME_REGEXPS, ...APP_TEST_FILENAME_REGEXPS],
|
||||
regexp => regexp.test(_.last(splitPath)));
|
||||
}
|
||||
@@ -86,7 +86,7 @@ _.extend(ProjectContext.prototype, {
|
||||
options.explicitlyAddedLocalPackageDirs;
|
||||
|
||||
// Used to override the directory that Meteor's build process
|
||||
// writes to; used by `meteor test-app` so that you can test your
|
||||
// writes to; used by `meteor test` so that you can test your
|
||||
// app in parallel to writing it, with an isolated database.
|
||||
self.projectLocalDir = options.projectLocalDir ||
|
||||
files.pathJoin(self.projectDir, '.meteor', 'local');
|
||||
|
||||
Reference in New Issue
Block a user