| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1289,6 +1289,27 @@ added: v18.0.0 | |||
| 1289 | 1289 | Configures the test runner to only execute top level tests that have the `only` | |
| 1290 | 1290 | option set. | |
| 1291 | 1291 | ||
| 1292 | + ### `--test-shard` | ||
| 1293 | + | ||
| 1294 | + <!-- YAML | ||
| 1295 | + added: REPLACEME | ||
| 1296 | + --> | ||
| 1297 | + | ||
| 1298 | + Test suite shard to execute in a format of `<index>/<total>`, where | ||
| 1299 | + | ||
| 1300 | + `index` is a positive integer, index of divided parts | ||
| 1301 | + `total` is a positive integer, total of divided part | ||
| 1302 | + This command will divide all tests files into `total` equal parts, | ||
| 1303 | + and will run only those that happen to be in an `index` part. | ||
| 1304 | + | ||
| 1305 | + For example, to split your tests suite into three parts, use this: | ||
| 1306 | + | ||
| 1307 | + ```bash | ||
| 1308 | + node --test --test-shard=1/3 | ||
| 1309 | + node --test --test-shard=2/3 | ||
| 1310 | + node --test --test-shard=3/3 | ||
| 1311 | + ``` | ||
| 1312 | + | ||
| 1292 | 1313 | ### `--throw-deprecation` | |
| 1293 | 1314 | ||
| 1294 | 1315 | <!-- YAML | |
@@ -1952,6 +1973,7 @@ Node.js options that are allowed are: | |||
| 1952 | 1973 | * `--test-only` | |
| 1953 | 1974 | * `--test-reporter-destination` | |
| 1954 | 1975 | * `--test-reporter` | |
| 1976 | + * `--test-shard` | ||
| 1955 | 1977 | * `--throw-deprecation` | |
| 1956 | 1978 | * `--title` | |
| 1957 | 1979 | * `--tls-cipher-list` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -901,6 +901,11 @@ changes: | |||
| 901 | 901 | If unspecified, subtests inherit this value from their parent. | |
| 902 | 902 | **Default:** `Infinity`. | |
| 903 | 903 | * `watch` {boolean} Whether to run in watch mode or not. **Default:** `false`. | |
| 904 | + * `shard` {Object} Running tests in a specific shard. **Default:** `undefined`. | ||
| 905 | + * `index` {number} is a positive integer between 1 and `<total>` | ||
| 906 | + that specifies the index of the shard to run. This option is _required_. | ||
| 907 | + * `total` {number} is a positive integer that specifies the total number | ||
| 908 | + of shards to split the test files to. This option is _required_. | ||
| 904 | 909 | * Returns: {TestsStream} | |
| 905 | 910 | ||
| 906 | 911 | ```mjs | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -409,6 +409,9 @@ The destination for the corresponding test reporter. | |||
| 409 | 409 | Configures the test runner to only execute top level tests that have the `only` | |
| 410 | 410 | option set. | |
| 411 | 411 | . | |
| 412 | + .It Fl -test-shard | ||
| 413 | + Test suite shard to execute in a format of <index>/<total>. | ||
| 414 | + . | ||
| 412 | 415 | .It Fl -throw-deprecation | |
| 413 | 416 | Throw errors for deprecations. | |
| 414 | 417 | . | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,16 @@ const { getOptionValue } = require('internal/options'); | |||
| 7 | 7 | const { isUsingInspector } = require('internal/util/inspector'); | |
| 8 | 8 | const { run } = require('internal/test_runner/runner'); | |
| 9 | 9 | const { setupTestReporters } = require('internal/test_runner/utils'); | |
| 10 | + const { | ||
| 11 | + codes: { | ||
| 12 | + ERR_INVALID_ARG_VALUE, | ||
| 13 | + }, | ||
| 14 | + } = require('internal/errors'); | ||
| 15 | + const { | ||
| 16 | + NumberParseInt, | ||
| 17 | + RegExpPrototypeExec, | ||
| 18 | + StringPrototypeSplit, | ||
| 19 | + } = primordials; | ||
| 10 | 20 | ||
| 11 | 21 | prepareMainThreadExecution(false); | |
| 12 | 22 | markBootstrapComplete(); | |
@@ -21,7 +31,32 @@ if (isUsingInspector()) { | |||
| 21 | 31 | inspectPort = process.debugPort; | |
| 22 | 32 | } | |
| 23 | 33 | ||
| 24 | - run({ concurrency, inspectPort, watch: getOptionValue('--watch'), setup: setupTestReporters }) | ||
| 34 | + let shard; | ||
| 35 | + const shardOption = getOptionValue('--test-shard'); | ||
| 36 | + if (shardOption) { | ||
| 37 | + if (!RegExpPrototypeExec(/^\d+\/\d+$/, shardOption)) { | ||
| 38 | + process.exitCode = 1; | ||
| 39 | + | ||
| 40 | + throw new ERR_INVALID_ARG_VALUE( | ||
| 41 | + '--test-shard', | ||
| 42 | + shardOption, | ||
| 43 | + 'must be in the form of <index>/<total>', | ||
| 44 | + ); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + const { 0: indexStr, 1: totalStr } = StringPrototypeSplit(shardOption, '/'); | ||
| 48 | + | ||
| 49 | + const index = NumberParseInt(indexStr, 10); | ||
| 50 | + const total = NumberParseInt(totalStr, 10); | ||
| 51 | + | ||
| 52 | + shard = { | ||
| 53 | + __proto__: null, | ||
| 54 | + index, | ||
| 55 | + total, | ||
| 56 | + }; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + run({ concurrency, inspectPort, watch: getOptionValue('--watch'), setup: setupTestReporters, shard }) | ||
| 25 | 60 | .once('test:fail', () => { | |
| 26 | 61 | process.exitCode = 1; | |
| 27 | 62 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -39,10 +39,18 @@ const console = require('internal/console/global'); | |||
| 39 | 39 | const { | |
| 40 | 40 | codes: { | |
| 41 | 41 | ERR_INVALID_ARG_TYPE, | |
| 42 | + ERR_INVALID_ARG_VALUE, | ||
| 42 | 43 | ERR_TEST_FAILURE, | |
| 44 | + ERR_OUT_OF_RANGE, | ||
| 43 | 45 | }, | |
| 44 | 46 | } = require('internal/errors'); | |
| 45 | - const { validateArray, validateBoolean, validateFunction } = require('internal/validators'); | ||
| 47 | + const { | ||
| 48 | + validateArray, | ||
| 49 | + validateBoolean, | ||
| 50 | + validateFunction, | ||
| 51 | + validateObject, | ||
| 52 | + validateInteger, | ||
| 53 | + } = require('internal/validators'); | ||
| 46 | 54 | const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector'); | |
| 47 | 55 | const { isRegExp } = require('internal/util/types'); | |
| 48 | 56 | const { kEmptyObject } = require('internal/util'); | |
@@ -459,7 +467,7 @@ function run(options) { | |||
| 459 | 467 | if (options === null || typeof options !== 'object') { | |
| 460 | 468 | options = kEmptyObject; | |
| 461 | 469 | } | |
| 462 | - let { testNamePatterns } = options; | ||
| 470 | + let { testNamePatterns, shard } = options; | ||
| 463 | 471 | const { concurrency, timeout, signal, files, inspectPort, watch, setup } = options; | |
| 464 | 472 | ||
| 465 | 473 | if (files != null) { | |
@@ -468,6 +476,22 @@ function run(options) { | |||
| 468 | 476 | if (watch != null) { | |
| 469 | 477 | validateBoolean(watch, 'options.watch'); | |
| 470 | 478 | } | |
| 479 | + if (shard != null) { | ||
| 480 | + validateObject(shard, 'options.shard'); | ||
| 481 | + // Avoid re-evaluating the shard object in case it's a getter | ||
| 482 | + shard = { __proto__: null, index: shard.index, total: shard.total }; | ||
| 483 | + | ||
| 484 | + validateInteger(shard.total, 'options.shard.total', 1); | ||
| 485 | + validateInteger(shard.index, 'options.shard.index'); | ||
| 486 | + | ||
| 487 | + if (shard.index <= 0 || shard.total < shard.index) { | ||
| 488 | + throw new ERR_OUT_OF_RANGE('options.shard.index', `>= 1 && <= ${shard.total} ("options.shard.total")`, shard.index); | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + if (watch) { | ||
| 492 | + throw new ERR_INVALID_ARG_VALUE('options.shard', watch, 'shards not supported with watch mode'); | ||
| 493 | + } | ||
| 494 | + } | ||
| 471 | 495 | if (setup != null) { | |
| 472 | 496 | validateFunction(setup, 'options.setup'); | |
| 473 | 497 | } | |
@@ -489,7 +513,11 @@ function run(options) { | |||
| 489 | 513 | } | |
| 490 | 514 | ||
| 491 | 515 | const root = createTestTree({ concurrency, timeout, signal }); | |
| 492 | - const testFiles = files ?? createTestFileList(); | ||
| 516 | + let testFiles = files ?? createTestFileList(); | ||
| 517 | + | ||
| 518 | + if (shard) { | ||
| 519 | + testFiles = ArrayPrototypeFilter(testFiles, (_, index) => index % shard.total === shard.index - 1); | ||
| 520 | + } | ||
| 493 | 521 | ||
| 494 | 522 | let postRun = () => root.postRun(); | |
| 495 | 523 | let filesWatcher; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -581,6 +581,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 581 | 581 | "run tests with 'only' option set", | |
| 582 | 582 | &EnvironmentOptions::test_only, | |
| 583 | 583 | kAllowedInEnvvar); | |
| 584 | + AddOption("--test-shard", | ||
| 585 | + "run test at specific shard", | ||
| 586 | + &EnvironmentOptions::test_shard, | ||
| 587 | + kAllowedInEnvvar); | ||
| 584 | 588 | AddOption("--test-udp-no-try-send", "", // For testing only. | |
| 585 | 589 | &EnvironmentOptions::test_udp_no_try_send); | |
| 586 | 590 | AddOption("--throw-deprecation", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -161,6 +161,7 @@ class EnvironmentOptions : public Options { | |||
| 161 | 161 | std::vector<std::string> test_reporter_destination; | |
| 162 | 162 | bool test_only = false; | |
| 163 | 163 | bool test_udp_no_try_send = false; | |
| 164 | + std::string test_shard; | ||
| 164 | 165 | bool throw_deprecation = false; | |
| 165 | 166 | bool trace_atomics_wait = false; | |
| 166 | 167 | bool trace_deprecation = false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,4 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const test = require('node:test'); | ||
| 3 | + | ||
| 4 | + test('a.cjs this should pass'); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,4 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const test = require('node:test'); | ||
| 3 | + | ||
| 4 | + test('b.cjs this should pass'); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,4 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const test = require('node:test'); | ||
| 3 | + | ||
| 4 | + test('c.cjs this should pass'); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments