From e91d69a2505fa35555c43e11aa91ebff40e49874 Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 4 Nov 2022 13:40:10 +0000 Subject: [PATCH 1/4] feat(integ-runner): support custom `--test-regex` to match integ test files Co-authored-by: karakter98 <37190268+karakter98@users.noreply.github.com> --- packages/@aws-cdk/integ-runner/README.md | 3 + packages/@aws-cdk/integ-runner/lib/cli.ts | 14 +- .../lib/runner/integration-tests.ts | 43 ++++-- .../@aws-cdk/integ-runner/test/cli.test.ts | 45 ++++++ .../test/runner/integration-tests.test.ts | 146 +++++++++++++++--- 5 files changed, 214 insertions(+), 37 deletions(-) create mode 100644 packages/@aws-cdk/integ-runner/test/cli.test.ts diff --git a/packages/@aws-cdk/integ-runner/README.md b/packages/@aws-cdk/integ-runner/README.md index 3e2553ac3a5f9..308d6da190f6f 100644 --- a/packages/@aws-cdk/integ-runner/README.md +++ b/packages/@aws-cdk/integ-runner/README.md @@ -70,6 +70,9 @@ to be a self contained CDK app. The runner will execute the following for each f If this is set to `true` then the [update workflow](#update-workflow) will be disabled - `--app` The custom CLI command that will be used to run the test files. You can include {filePath} to specify where in the command the test file path should be inserted. Example: --app="python3.8 {filePath}". +- `--test-regex` + Detect integration test files matching this JavaScript regex pattern. If used multiple times, all files matching any one of the patterns are detected. + Example: ```bash diff --git a/packages/@aws-cdk/integ-runner/lib/cli.ts b/packages/@aws-cdk/integ-runner/lib/cli.ts index 740ce476671d6..75a6569272e24 100644 --- a/packages/@aws-cdk/integ-runner/lib/cli.ts +++ b/packages/@aws-cdk/integ-runner/lib/cli.ts @@ -13,7 +13,7 @@ import { runSnapshotTests, runIntegrationTests, IntegRunnerMetrics, IntegTestWor const yargs = require('yargs'); -async function main() { +export async function main(args: string[]) { const argv = yargs .usage('Usage: integ-runner [TEST...]') .option('list', { type: 'boolean', default: false, desc: 'List tests instead of running them' }) @@ -31,14 +31,16 @@ async function main() { .option('inspect-failures', { type: 'boolean', desc: 'Keep the integ test cloud assembly if a failure occurs for inspection', default: false }) .option('disable-update-workflow', { type: 'boolean', default: false, desc: 'If this is "true" then the stack update workflow will be disabled' }) .option('app', { type: 'string', default: undefined, desc: 'The custom CLI command that will be used to run the test files. You can include {filePath} to specify where in the command the test file path should be inserted. Example: --app="python3.8 {filePath}".' }) + .option('test-regex', { type: 'array', desc: 'Detect integration test files matching this JavaScript regex pattern. If used multiple times, all files matching any one of the patterns are detected.', default: [] }) .strict() - .argv; + .parse(args); const pool = workerpool.pool(path.join(__dirname, '../lib/workers/extract/index.js'), { maxWorkers: argv['max-workers'], }); // list of integration tests that will be executed + const testRegex = arrayFromYargs(argv['test-regex']); const testsToRun: IntegTestWorkerConfig[] = []; const destructiveChanges: DestructiveChange[] = []; const testsFromArgs: IntegTest[] = []; @@ -57,7 +59,7 @@ async function main() { let testsSucceeded = false; try { if (argv.list) { - const tests = await new IntegrationTests(argv.directory).fromCliArgs(); + const tests = await new IntegrationTests(argv.directory).fromCliArgs({ testRegex }); process.stdout.write(tests.map(t => t.discoveryRelativeFileName).join('\n') + '\n'); return; } @@ -69,7 +71,7 @@ async function main() { ? (await fs.readFile(fromFile, { encoding: 'utf8' })).split('\n').filter(x => x) : (argv._.length > 0 ? argv._ : undefined); // 'undefined' means no request - testsFromArgs.push(...(await new IntegrationTests(path.resolve(argv.directory)).fromCliArgs(requestedTests, exclude))); + testsFromArgs.push(...(await new IntegrationTests(path.resolve(argv.directory)).fromCliArgs({ testRegex, tests: requestedTests, exclude }))); // always run snapshot tests, but if '--force' is passed then // run integration tests on all failed tests, not just those that @@ -184,8 +186,8 @@ function mergeTests(testFromArgs: IntegTestInfo[], failedSnapshotTests: IntegTes return final; } -export function cli() { - main().then().catch(err => { +export function cli(args: string[] = process.argv.slice(2)) { + main(args).then().catch(err => { logger.error(err); process.exitCode = 1; }); diff --git a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts index 643dfbe56ae86..bca6cd664d4aa 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts @@ -123,10 +123,9 @@ export class IntegTest { } /** - * The list of tests to run can be provided in a file - * instead of as command line arguments. + * Configuration options how integration test files are discovered */ -export interface IntegrationTestFileConfig { +export interface IntegrationTestsDiscoveryOptions { /** * If this is set to true then the list of tests * provided will be excluded @@ -135,6 +134,27 @@ export interface IntegrationTestFileConfig { */ readonly exclude?: boolean; + /** + * List of tests to include (or exclude if `exclude=true`) + * + * @default - all matched files + */ + readonly tests?: string[]; + + /** + * Detect integration test files matching any of these JavaScript regex patterns. + * + * @default + */ + readonly testRegex?: string[]; +} + + +/** + * The list of tests to run can be provided in a file + * instead of as command line arguments. + */ +export interface IntegrationTestFileConfig extends IntegrationTestsDiscoveryOptions { /** * List of tests to include (or exclude if `exclude=true`) */ @@ -154,7 +174,7 @@ export class IntegrationTests { */ public async fromFile(fileName: string): Promise { const file: IntegrationTestFileConfig = JSON.parse(fs.readFileSync(fileName, { encoding: 'utf-8' })); - const foundTests = await this.discover(); + const foundTests = await this.discover(file.testRegex); const allTests = this.filterTests(foundTests, file.tests, file.exclude); @@ -201,17 +221,20 @@ export class IntegrationTests { * @param tests Tests to include or exclude, undefined means include all tests. * @param exclude Whether the 'tests' list is inclusive or exclusive (inclusive by default). */ - public async fromCliArgs(tests?: string[], exclude?: boolean): Promise { - const discoveredTests = await this.discover(); + public async fromCliArgs(options: IntegrationTestsDiscoveryOptions = {}): Promise { + const discoveredTests = await this.discover(options.testRegex); - const allTests = this.filterTests(discoveredTests, tests, exclude); + const allTests = this.filterTests(discoveredTests, options.tests, options.exclude); return allTests; } - private async discover(): Promise { + private async discover(patterns: string[] = ['^integ\\..*\\.js$']): Promise { const files = await this.readTree(); - const integs = files.filter(fileName => path.basename(fileName).startsWith('integ.') && path.basename(fileName).endsWith('.js')); + const integs = files.filter(fileName => patterns.some((p) => { + const regex = new RegExp(p); + return regex.test(fileName) || regex.test(path.basename(fileName)); + })); return this.request(integs); } @@ -228,7 +251,7 @@ export class IntegrationTests { const fullPath = path.join(dir, file); const statf = await fs.stat(fullPath); if (statf.isFile()) { ret.push(fullPath); } - if (statf.isDirectory()) { await recurse(path.join(fullPath)); } + if (statf.isDirectory()) { await recurse(fullPath); } } } diff --git a/packages/@aws-cdk/integ-runner/test/cli.test.ts b/packages/@aws-cdk/integ-runner/test/cli.test.ts new file mode 100644 index 0000000000000..14a10acafbcd7 --- /dev/null +++ b/packages/@aws-cdk/integ-runner/test/cli.test.ts @@ -0,0 +1,45 @@ +import * as path from 'path'; +import { main } from '../lib/cli'; + +describe('CLI', () => { + const currentCwd = process.cwd(); + beforeAll(() => { + process.chdir(path.join(__dirname, '..')); + }); + afterAll(() => { + process.chdir(currentCwd); + }); + + let stdoutMock: jest.SpyInstance; + beforeEach(() => { + stdoutMock = jest.spyOn(process.stdout, 'write').mockImplementation(() => { return true; }); + }); + afterEach(() => { + stdoutMock.mockRestore(); + }); + + test('find by default pattern', async () => { + await main(['--list', '--directory=test/test-data']); + + // Expect nothing to be found since this directory doesn't contain files with the default pattern + expect(stdoutMock.mock.calls).toEqual([['\n']]); + }); + + test('find by custom pattern', async () => { + await main(['--list', '--directory=test/test-data', '--test-regex="^xxxxx\..*\.js$"']); + + // Expect nothing to be found since this directory doesn't contain files with the default pattern + expect(stdoutMock.mock.calls).toEqual([[ + [ + 'xxxxx.integ-test1.js', + 'xxxxx.integ-test2.js', + 'xxxxx.test-with-new-assets-diff.js', + 'xxxxx.test-with-new-assets.js', + 'xxxxx.test-with-snapshot-assets-diff.js', + 'xxxxx.test-with-snapshot-assets.js', + 'xxxxx.test-with-snapshot.js', + '', + ].join('\n'), + ]]); + }); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts b/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts index 22b796b9fe52e..6f0aa990cb7a6 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts @@ -1,3 +1,4 @@ +import { writeFileSync } from 'fs'; import * as mockfs from 'mock-fs'; import { IntegrationTests } from '../../lib/runner/integration-tests'; @@ -5,12 +6,17 @@ describe('IntegrationTests', () => { const tests = new IntegrationTests('test'); let stderrMock: jest.SpyInstance; stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; }); + beforeEach(() => { mockfs({ 'test/test-data': { 'integ.integ-test1.js': 'content', 'integ.integ-test2.js': 'content', 'integ.integ-test3.js': 'content', + 'integration.test.js': 'should not match', + }, + 'other/other-data': { + 'integ.other-test1.js': 'content', }, }); }); @@ -19,32 +25,130 @@ describe('IntegrationTests', () => { mockfs.restore(); }); - test('from cli args', async () => { - const integTests = await tests.fromCliArgs(['test-data/integ.integ-test1.js']); + describe('from cli args', () => { + test('find all', async () => { + const integTests = await tests.fromCliArgs(); + + expect(integTests.length).toEqual(3); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + expect(integTests[1].fileName).toEqual(expect.stringMatching(/integ.integ-test2.js$/)); + expect(integTests[2].fileName).toEqual(expect.stringMatching(/integ.integ-test3.js$/)); + }); - expect(integTests.length).toEqual(1); - expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); - }); - test('from cli args, test not found', async () => { - const integTests = await tests.fromCliArgs(['test-data/integ.integ-test16.js']); + test('find named tests', async () => { + const integTests = await tests.fromCliArgs({ tests: ['test-data/integ.integ-test1.js'] }); - expect(integTests.length).toEqual(0); - expect(stderrMock.mock.calls[0][0]).toContain( - 'No such integ test: test-data/integ.integ-test16.js', - ); - expect(stderrMock.mock.calls[1][0]).toContain( - 'Available tests: test-data/integ.integ-test1.js test-data/integ.integ-test2.js test-data/integ.integ-test3.js', - ); + expect(integTests.length).toEqual(1); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + }); + + + test('test not found', async () => { + const integTests = await tests.fromCliArgs({ tests: ['test-data/integ.integ-test16.js'] }); + + expect(integTests.length).toEqual(0); + expect(stderrMock.mock.calls[0][0]).toContain( + 'No such integ test: test-data/integ.integ-test16.js', + ); + expect(stderrMock.mock.calls[1][0]).toContain( + 'Available tests: test-data/integ.integ-test1.js test-data/integ.integ-test2.js test-data/integ.integ-test3.js', + ); + }); + + test('exclude tests', async () => { + const integTests = await tests.fromCliArgs({ tests: ['test-data/integ.integ-test1.js'], exclude: true }); + + const fileNames = integTests.map(test => test.fileName); + expect(integTests.length).toEqual(2); + expect(fileNames).not.toContain( + 'test/test-data/integ.integ-test1.js', + ); + }); + + test('match regex', async () => { + const integTests = await tests.fromCliArgs({ testRegex: ['1\.js$', '2\.js'] }); + + expect(integTests.length).toEqual(2); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + expect(integTests[1].fileName).toEqual(expect.stringMatching(/integ.integ-test2.js$/)); + }); + + test('match regex with path', async () => { + const otherTestDir = new IntegrationTests('.'); + const integTests = await otherTestDir.fromCliArgs({ testRegex: ['other-data/integ\..*\.js$'] }); + + expect(integTests.length).toEqual(1); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.other-test1.js$/)); + }); }); - test('from cli args, exclude', async () => { - const integTests = await tests.fromCliArgs(['test-data/integ.integ-test1.js'], true); + describe('from file', () => { + const configFile = 'integ.config.json'; + const writeConfig = (settings: any, fileName = configFile) => { + writeFileSync(fileName, JSON.stringify(settings, null, 2), { encoding: 'utf-8' }); + }; - const fileNames = integTests.map(test => test.fileName); - expect(integTests.length).toEqual(2); - expect(fileNames).not.toContain( - 'test/test-data/integ.integ-test1.js', - ); + test('find all', async () => { + writeConfig({}); + const integTests = await tests.fromFile(configFile); + + expect(integTests.length).toEqual(3); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + expect(integTests[1].fileName).toEqual(expect.stringMatching(/integ.integ-test2.js$/)); + expect(integTests[2].fileName).toEqual(expect.stringMatching(/integ.integ-test3.js$/)); + }); + + + test('find named tests', async () => { + writeConfig({ tests: ['test-data/integ.integ-test1.js'] }); + const integTests = await tests.fromFile(configFile); + + expect(integTests.length).toEqual(1); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + }); + + + test('test not found', async () => { + writeConfig({ tests: ['test-data/integ.integ-test16.js'] }); + const integTests = await tests.fromFile(configFile); + + expect(integTests.length).toEqual(0); + expect(stderrMock.mock.calls[0][0]).toContain( + 'No such integ test: test-data/integ.integ-test16.js', + ); + expect(stderrMock.mock.calls[1][0]).toContain( + 'Available tests: test-data/integ.integ-test1.js test-data/integ.integ-test2.js test-data/integ.integ-test3.js', + ); + }); + + test('exclude tests', async () => { + writeConfig({ tests: ['test-data/integ.integ-test1.js'], exclude: true }); + const integTests = await tests.fromFile(configFile); + + const fileNames = integTests.map(test => test.fileName); + expect(integTests.length).toEqual(2); + expect(fileNames).not.toContain( + 'test/test-data/integ.integ-test1.js', + ); + }); + + test('match regex', async () => { + writeConfig({ testRegex: ['1\.js$', '2\.js'] }); + const integTests = await tests.fromFile(configFile); + + expect(integTests.length).toEqual(2); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.integ-test1.js$/)); + expect(integTests[1].fileName).toEqual(expect.stringMatching(/integ.integ-test2.js$/)); + }); + + test('match regex with path', async () => { + writeConfig({ testRegex: ['other-data/integ\..*\.js$'] }); + const otherTestDir = new IntegrationTests('.'); + const integTests = await otherTestDir.fromFile(configFile); + + expect(integTests.length).toEqual(1); + expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.other-test1.js$/)); + }); }); }); From fd350bbdcd3e0da3ffc695863bddb29d2e0c8cf9 Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 4 Nov 2022 15:25:27 +0000 Subject: [PATCH 2/4] chore(integ-runner): refactor to support fromFile --- packages/@aws-cdk/integ-runner/lib/cli.ts | 12 +++-- .../lib/runner/integration-tests.ts | 54 ++++++++++++++----- .../integ-runner/lib/runner/runner-base.ts | 10 +--- .../integ-runner/lib/workers/common.ts | 14 ----- .../lib/workers/extract/extract_worker.ts | 3 +- .../lib/workers/integ-test-worker.ts | 1 - .../test/runner/integ-test-runner.test.ts | 2 +- .../test/runner/integration-tests.test.ts | 20 ++++++- 8 files changed, 70 insertions(+), 46 deletions(-) diff --git a/packages/@aws-cdk/integ-runner/lib/cli.ts b/packages/@aws-cdk/integ-runner/lib/cli.ts index 75a6569272e24..c3a2256c0813b 100644 --- a/packages/@aws-cdk/integ-runner/lib/cli.ts +++ b/packages/@aws-cdk/integ-runner/lib/cli.ts @@ -50,6 +50,7 @@ export async function main(args: string[]) { const runUpdateOnFailed = argv['update-on-failed'] ?? false; const fromFile: string | undefined = argv['from-file']; const exclude: boolean = argv.exclude; + const app: string | undefined = argv.app; let failedSnapshots: IntegTestWorkerConfig[] = []; if (argv['max-workers'] < testRegions.length * (profiles ?? [1]).length) { @@ -59,7 +60,7 @@ export async function main(args: string[]) { let testsSucceeded = false; try { if (argv.list) { - const tests = await new IntegrationTests(argv.directory).fromCliArgs({ testRegex }); + const tests = await new IntegrationTests(argv.directory).fromCliArgs({ testRegex, app }); process.stdout.write(tests.map(t => t.discoveryRelativeFileName).join('\n') + '\n'); return; } @@ -71,7 +72,12 @@ export async function main(args: string[]) { ? (await fs.readFile(fromFile, { encoding: 'utf8' })).split('\n').filter(x => x) : (argv._.length > 0 ? argv._ : undefined); // 'undefined' means no request - testsFromArgs.push(...(await new IntegrationTests(path.resolve(argv.directory)).fromCliArgs({ testRegex, tests: requestedTests, exclude }))); + testsFromArgs.push(...(await new IntegrationTests(path.resolve(argv.directory)).fromCliArgs({ + app, + testRegex, + tests: requestedTests, + exclude, + }))); // always run snapshot tests, but if '--force' is passed then // run integration tests on all failed tests, not just those that @@ -79,7 +85,6 @@ export async function main(args: string[]) { failedSnapshots = await runSnapshotTests(pool, testsFromArgs, { retain: argv['inspect-failures'], verbose: Boolean(argv.verbose), - appCommand: argv.app, }); for (const failure of failedSnapshots) { destructiveChanges.push(...failure.destructiveChanges ?? []); @@ -103,7 +108,6 @@ export async function main(args: string[]) { dryRun: argv['dry-run'], verbosity: argv.verbose, updateWorkflow: !argv['disable-update-workflow'], - appCommand: argv.app, }); testsSucceeded = success; diff --git a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts index bca6cd664d4aa..d7559ea911c10 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts @@ -23,6 +23,14 @@ export interface IntegTestInfo { * Path is relative to the current working directory. */ readonly discoveryRoot: string; + + /** + * The CLI command used to run this test. + * If it contains {filePath}, the test file names will be substituted at that place in the command for each run. + * + * @default - test run command will be `node {filePath}` + */ + readonly appCommand?: string; } /** @@ -79,7 +87,16 @@ export class IntegTest { */ public readonly temporaryOutputDir: string; + /** + * The CLI command used to run this test. + * If it contains {filePath}, the test file names will be substituted at that place in the command for each run. + * + * @default - test run command will be `node {filePath}` + */ + readonly appCommand: string; + constructor(public readonly info: IntegTestInfo) { + this.appCommand = info.appCommand ?? 'node {filePath}'; this.absoluteFileName = path.resolve(info.fileName); this.fileName = path.relative(process.cwd(), info.fileName); @@ -147,6 +164,14 @@ export interface IntegrationTestsDiscoveryOptions { * @default */ readonly testRegex?: string[]; + + /** + * The CLI command used to run this test. + * If it contains {filePath}, the test file names will be substituted at that place in the command for each run. + * + * @default - test run command will be `node {filePath}` + */ + readonly app?: string; } @@ -174,11 +199,8 @@ export class IntegrationTests { */ public async fromFile(fileName: string): Promise { const file: IntegrationTestFileConfig = JSON.parse(fs.readFileSync(fileName, { encoding: 'utf-8' })); - const foundTests = await this.discover(file.testRegex); - - const allTests = this.filterTests(foundTests, file.tests, file.exclude); - return allTests; + return this.discover(file); } /** @@ -222,24 +244,30 @@ export class IntegrationTests { * @param exclude Whether the 'tests' list is inclusive or exclusive (inclusive by default). */ public async fromCliArgs(options: IntegrationTestsDiscoveryOptions = {}): Promise { - const discoveredTests = await this.discover(options.testRegex); - - const allTests = this.filterTests(discoveredTests, options.tests, options.exclude); - - return allTests; + return this.discover(options); } - private async discover(patterns: string[] = ['^integ\\..*\\.js$']): Promise { + private async discover(options: IntegrationTestsDiscoveryOptions): Promise { + const patterns = options.testRegex ?? ['^integ\\..*\\.js$']; + const files = await this.readTree(); const integs = files.filter(fileName => patterns.some((p) => { const regex = new RegExp(p); return regex.test(fileName) || regex.test(path.basename(fileName)); })); - return this.request(integs); + + return this.request(integs, options); } - private request(files: string[]): IntegTest[] { - return files.map(fileName => new IntegTest({ discoveryRoot: this.directory, fileName })); + private request(files: string[], options: IntegrationTestsDiscoveryOptions): IntegTest[] { + const discoveredTests = files.map(fileName => new IntegTest({ + discoveryRoot: this.directory, + fileName, + appCommand: options.app, + })); + + + return this.filterTests(discoveredTests, options.tests, options.exclude); } private async readTree(): Promise { diff --git a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts index 0e4ba15683eea..ed5d9a2b7e927 100644 --- a/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts +++ b/packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts @@ -49,14 +49,6 @@ export interface IntegRunnerOptions { */ readonly cdk?: ICdk; - /** - * You can specify a custom run command, and it will be applied to all test files. - * If it contains {filePath}, the test file names will be substituted at that place in the command for each run. - * - * @default - test run command will be `node {filePath}` - */ - readonly appCommand?: string; - /** * Show output from running integration tests * @@ -159,7 +151,7 @@ export abstract class IntegRunner { }); this.cdkOutDir = options.integOutDir ?? this.test.temporaryOutputDir; - const testRunCommand = options.appCommand ?? 'node {filePath}'; + const testRunCommand = this.test.appCommand; this.cdkApp = testRunCommand.replace('{filePath}', path.relative(this.directory, this.test.fileName)); this.profile = options.profile; diff --git a/packages/@aws-cdk/integ-runner/lib/workers/common.ts b/packages/@aws-cdk/integ-runner/lib/workers/common.ts index a8c3a7b92079d..7f49cb73b864c 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/common.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/common.ts @@ -103,13 +103,6 @@ export interface SnapshotVerificationOptions { * @default false */ readonly verbose?: boolean; - - /** - * The CLI command used to run the test files. - * - * @default - test run command will be `node {filePath}` - */ - readonly appCommand?: string; } /** @@ -169,13 +162,6 @@ export interface IntegTestOptions { * @default true */ readonly updateWorkflow?: boolean; - - /** - * The CLI command used to run the test files. - * - * @default - test run command will be `node {filePath}` - */ - readonly appCommand?: string; } /** diff --git a/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts b/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts index 047e03463efdf..a8166680fb7ba 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/extract/extract_worker.ts @@ -27,7 +27,6 @@ export function integTestWorker(request: IntegTestBatchRequest): IntegTestWorker env: { AWS_REGION: request.region, }, - appCommand: request.appCommand, showOutput: verbosity >= 2, }, testInfo.destructiveChanges); @@ -106,7 +105,7 @@ export function snapshotTestWorker(testInfo: IntegTestInfo, options: SnapshotVer }, 60_000); try { - const runner = new IntegSnapshotRunner({ test, appCommand: options.appCommand }); + const runner = new IntegSnapshotRunner({ test }); if (!runner.hasSnapshot()) { workerpool.workerEmit({ reason: DiagnosticReason.NO_SNAPSHOT, diff --git a/packages/@aws-cdk/integ-runner/lib/workers/integ-test-worker.ts b/packages/@aws-cdk/integ-runner/lib/workers/integ-test-worker.ts index 06d73967a2d25..77752c029abbb 100644 --- a/packages/@aws-cdk/integ-runner/lib/workers/integ-test-worker.ts +++ b/packages/@aws-cdk/integ-runner/lib/workers/integ-test-worker.ts @@ -135,7 +135,6 @@ export async function runIntegrationTestsInParallel( dryRun: options.dryRun, verbosity: options.verbosity, updateWorkflow: options.updateWorkflow, - appCommand: options.appCommand, }], { on: printResults, }); diff --git a/packages/@aws-cdk/integ-runner/test/runner/integ-test-runner.test.ts b/packages/@aws-cdk/integ-runner/test/runner/integ-test-runner.test.ts index 53bdd9f4519e0..8a2b9cbfca984 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/integ-test-runner.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/integ-test-runner.test.ts @@ -567,8 +567,8 @@ describe('IntegTest runIntegTests', () => { test: new IntegTest({ fileName: 'test/test-data/xxxxx.test-with-snapshot.js', discoveryRoot: 'test/test-data', + appCommand: 'node --no-warnings {filePath}', }), - appCommand: 'node --no-warnings {filePath}', }); integTest.runIntegTestCase({ testCaseName: 'xxxxx.test-with-snapshot', diff --git a/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts b/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts index 6f0aa990cb7a6..9b93709abdc75 100644 --- a/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts +++ b/packages/@aws-cdk/integ-runner/test/runner/integration-tests.test.ts @@ -1,6 +1,6 @@ import { writeFileSync } from 'fs'; import * as mockfs from 'mock-fs'; -import { IntegrationTests } from '../../lib/runner/integration-tests'; +import { IntegrationTests, IntegrationTestsDiscoveryOptions } from '../../lib/runner/integration-tests'; describe('IntegrationTests', () => { const tests = new IntegrationTests('test'); @@ -81,11 +81,19 @@ describe('IntegrationTests', () => { expect(integTests.length).toEqual(1); expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.other-test1.js$/)); }); + + test('can set app command', async () => { + const otherTestDir = new IntegrationTests('test'); + const integTests = await otherTestDir.fromCliArgs({ app: 'node --no-warnings {filePath}' }); + + expect(integTests.length).toEqual(3); + expect(integTests[0].appCommand).toEqual('node --no-warnings {filePath}'); + }); }); describe('from file', () => { const configFile = 'integ.config.json'; - const writeConfig = (settings: any, fileName = configFile) => { + const writeConfig = (settings: IntegrationTestsDiscoveryOptions, fileName = configFile) => { writeFileSync(fileName, JSON.stringify(settings, null, 2), { encoding: 'utf-8' }); }; @@ -150,5 +158,13 @@ describe('IntegrationTests', () => { expect(integTests.length).toEqual(1); expect(integTests[0].fileName).toEqual(expect.stringMatching(/integ.other-test1.js$/)); }); + + test('can set app command', async () => { + writeConfig({ app: 'node --no-warnings {filePath}' }); + const integTests = await tests.fromFile(configFile); + + expect(integTests.length).toEqual(3); + expect(integTests[0].appCommand).toEqual('node --no-warnings {filePath}'); + }); }); }); From ab8196b8a7833f0d11d54ca80dd98d15e78de523 Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Tue, 8 Nov 2022 00:13:36 +0000 Subject: [PATCH 3/4] Update packages/@aws-cdk/integ-runner/test/cli.test.ts --- packages/@aws-cdk/integ-runner/test/cli.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/integ-runner/test/cli.test.ts b/packages/@aws-cdk/integ-runner/test/cli.test.ts index 14a10acafbcd7..3f28440f2df04 100644 --- a/packages/@aws-cdk/integ-runner/test/cli.test.ts +++ b/packages/@aws-cdk/integ-runner/test/cli.test.ts @@ -42,4 +42,4 @@ describe('CLI', () => { ].join('\n'), ]]); }); -}); \ No newline at end of file +}); From 2cb9bd4138e005a9a372c621a52be9eb509ac038 Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Thu, 10 Nov 2022 14:24:04 +0000 Subject: [PATCH 4/4] Update packages/@aws-cdk/integ-runner/test/cli.test.ts Co-authored-by: Cory Hall <43035978+corymhall@users.noreply.github.com> --- packages/@aws-cdk/integ-runner/test/cli.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/integ-runner/test/cli.test.ts b/packages/@aws-cdk/integ-runner/test/cli.test.ts index 3f28440f2df04..bf61aa7633aac 100644 --- a/packages/@aws-cdk/integ-runner/test/cli.test.ts +++ b/packages/@aws-cdk/integ-runner/test/cli.test.ts @@ -28,7 +28,6 @@ describe('CLI', () => { test('find by custom pattern', async () => { await main(['--list', '--directory=test/test-data', '--test-regex="^xxxxx\..*\.js$"']); - // Expect nothing to be found since this directory doesn't contain files with the default pattern expect(stdoutMock.mock.calls).toEqual([[ [ 'xxxxx.integ-test1.js',