kibana/packages/kbn-test/src/functional_test_runner/cli.ts
Spencer 542b381fa5
[ftr] automatically determine config run order (#130983)
* [ftr] automatically determine config run order

* split lens config into two groups

* support ftr configs always running against CI

* Split detection_engine_api_integration rule exception list tests

* Add configs from previous commit

* [ftr] remove testMetadata and maintain a unique lifecycle instance per run

* Revert "[ftr] remove testMetadata and maintain a unique lifecycle instance per run"

This reverts commit d2b4fdb824.

* Split alerting_api_integration/security_and_spaces tests

* Add groups to yaml

* Revert "Revert "[ftr] remove testMetadata and maintain a unique lifecycle instance per run""

This reverts commit 56232eea68.

* stop ES more forcefully and fix timeout

* only cleanup lifecycle phases when the cleanup is totally complete

* only use kill when cleaning up an esTestInstance

* fix broken import

* fix runOptions.alwaysUseSource implementation

* fix config access

* fix x-pack/ccs config

* fix ml import file paths

* update kibana build id

* revert array.concat() change

* fix baseConfig usage

* fix pie chart data

* split up maps tests

* pull in all of group5 so that es archives are loaded correctly

* add to ftr configs.yml

* fix pie chart data without breaking legacy version

* fix more pie_chart stuff in new vis lib

* restore normal PR tasks

* bump kibana-buildkite-library

* remove ciGroup validation

* remove the script which is no longer called from checks.sh

* [CI] Auto-commit changed files from 'yarn kbn run build -i @kbn/pm'

* adapt flaky test runner scripts to handle ftrConfig paths

* fix types in alerting_api_integration

* improve flaky config parsing and use non-local var name for passing explicit configs to ftr_configs.sh

* Split xpack dashboard tests

* Add configs

* [flaky] remove key from ftr-config steps

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* restore cypress builds

* remove ciGroups from FTR config files

* fixup some docs

* add temporary script to hunt for FTR config files

* use config.base.js naming for clarity

* use script to power ftr_configs.yml

* remove usage of removed x-pack/scripts/functional_tests

* fix test names in dashboard snapshots

* bump kibana-buildkite-library

* Try retrying only failed configs

* be a little quieter about trying to get testStats from configs with testRunners defined

* Remove test code

* bump kibana-buildkite-library

* update es_snapshot and on_merge jobs too

* track duration and exit code for each config and print it at the end of the script

* store results in order, rather than by key, in case there are duplicates in $config

* bash is hard

* fix env source and use +e rather than disabling e for whole file

* bash sucks

* print config summary in jest jobs too

* define results in jest_parallel.sh

* simplify config summary print, format times a little better

* fix reference to unbound time variable, use better variable name

* skip the newline between each result

* finish with the nitpicking

* sync changes with ftr_configs.sh

* refuse to execute config files which aren't listed in the .buildkite/ftr_configs.yml

* fix config.edge.js base config import paths

* fix some readmes

* resolve paths from ftr_configs manifest

* fix readConfigFile tests

* just allow __fixtures__ configs

* list a few more cypress config files

* install the main branch of kibana-buildkite-library

* split up lens group1

* move ml data_visualizer tests to their own config

* fix import paths

* fix more imports

* install specific commit of buildkite-pipeline-library

* sort configs in ftr_configs.yml

* bump kibana-buildkite-library

* remove temporary script

* fix env var for limiting config types

* Update docs/developer/contributing/development-functional-tests.asciidoc

Co-authored-by: Christiane (Tina) Heiligers <christiane.heiligers@elastic.co>

* produce a JUnit report for saved objects field count

* apply standard concurrency limits from flaky test runner

* support customizing FTR concurrency via the env

Co-authored-by: Brian Seeders <brian.seeders@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christiane (Tina) Heiligers <christiane.heiligers@elastic.co>
2022-05-04 17:05:58 -05:00

182 lines
6.3 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { resolve } from 'path';
import { inspect } from 'util';
import { run, createFlagError, Flags } from '@kbn/dev-utils';
import { ToolingLog } from '@kbn/tooling-log';
import { getTimeReporter } from '@kbn/ci-stats-reporter';
import exitHook from 'exit-hook';
import { FunctionalTestRunner } from './functional_test_runner';
const makeAbsolutePath = (v: string) => resolve(process.cwd(), v);
const toArray = (v: string | string[]) => ([] as string[]).concat(v || []);
const parseInstallDir = (flags: Flags) => {
const flag = flags['kibana-install-dir'];
if (typeof flag !== 'string' && flag !== undefined) {
throw createFlagError('--kibana-install-dir must be a string or not defined');
}
return flag ? makeAbsolutePath(flag) : undefined;
};
export function runFtrCli() {
const runStartTime = Date.now();
const toolingLog = new ToolingLog({
level: 'info',
writeTo: process.stdout,
});
const reportTime = getTimeReporter(toolingLog, 'scripts/functional_test_runner');
run(
async ({ flags, log }) => {
const esVersion = flags['es-version'] || undefined; // convert "" to undefined
if (esVersion !== undefined && typeof esVersion !== 'string') {
throw createFlagError('expected --es-version to be a string');
}
const functionalTestRunner = new FunctionalTestRunner(
log,
makeAbsolutePath(flags.config as string),
{
mochaOpts: {
bail: flags.bail,
dryRun: flags['dry-run'],
grep: flags.grep || undefined,
invert: flags.invert,
},
kbnTestServer: {
installDir: parseInstallDir(flags),
},
suiteFiles: {
include: toArray(flags.include as string | string[]).map(makeAbsolutePath),
exclude: toArray(flags.exclude as string | string[]).map(makeAbsolutePath),
},
suiteTags: {
include: toArray(flags['include-tag'] as string | string[]),
exclude: toArray(flags['exclude-tag'] as string | string[]),
},
updateBaselines: flags.updateBaselines || flags.u,
updateSnapshots: flags.updateSnapshots || flags.u,
},
esVersion
);
if (flags.throttle) {
process.env.TEST_THROTTLE_NETWORK = '1';
}
if (flags.headless) {
process.env.TEST_BROWSER_HEADLESS = '1';
}
let teardownRun = false;
const teardown = async (err?: Error) => {
if (teardownRun) return;
teardownRun = true;
if (err) {
await reportTime(runStartTime, 'total', {
success: false,
err: err.message,
...flags,
});
log.indent(-log.getIndent());
log.error(err);
process.exitCode = 1;
} else {
await reportTime(runStartTime, 'total', {
success: true,
...flags,
});
}
process.exit();
};
process.on('unhandledRejection', (err) =>
teardown(
err instanceof Error ? err : new Error(`non-Error type rejection value: ${inspect(err)}`)
)
);
exitHook(teardown);
try {
if (flags['test-stats']) {
process.stderr.write(
JSON.stringify(await functionalTestRunner.getTestStats(), null, 2) + '\n'
);
} else {
const failureCount = await functionalTestRunner.run();
process.exitCode = failureCount ? 1 : 0;
}
} catch (err) {
await teardown(err);
} finally {
await teardown();
}
},
{
log: {
defaultLevel: 'debug',
},
flags: {
string: [
'config',
'grep',
'include',
'exclude',
'include-tag',
'exclude-tag',
'kibana-install-dir',
'es-version',
],
boolean: [
'bail',
'invert',
'test-stats',
'updateBaselines',
'updateSnapshots',
'u',
'throttle',
'headless',
'dry-run',
],
default: {
config: 'test/functional/config.js',
},
help: `
--config=path path to a config file
--bail stop tests after the first failure
--grep <pattern> pattern used to select which tests to run
--invert invert grep to exclude tests
--es-version the elasticsearch version, formatted as "x.y.z"
--include=file a test file to be included, pass multiple times for multiple files
--exclude=file a test file to be excluded, pass multiple times for multiple files
--include-tag=tag a tag to be included, pass multiple times for multiple tags. Only
suites which have one of the passed include-tag tags will be executed.
When combined with the --exclude-tag flag both conditions must be met
for a suite to run.
--exclude-tag=tag a tag to be excluded, pass multiple times for multiple tags. Any suite
which has any of the exclude-tags will be excluded. When combined with
the --include-tag flag both conditions must be met for a suite to run.
--test-stats print the number of tests (included and excluded) to STDERR
--updateBaselines replace baseline screenshots with whatever is generated from the test
--updateSnapshots replace inline and file snapshots with whatever is generated from the test
-u replace both baseline screenshots and snapshots
--kibana-install-dir directory where the Kibana install being tested resides
--throttle enable network throttling in Chrome browser
--headless run browser in headless mode
--dry-run report tests without executing them
`,
},
}
);
}