Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(integ-runner): Support non-TypeScript tests #22521

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/@aws-cdk/integ-runner/README.md
Expand Up @@ -68,6 +68,8 @@ to be a self contained CDK app. The runner will execute the following for each f
Read the list of tests from this file
- `--disable-update-workflow` (default=`false`)
If this is set to `true` then the [update workflow](#update-workflow) will be disabled
- `--test-run-command` (default=`node`)
The command used by the test runner to synth the test files. This will depend on the language the tests are written in. For example, if the tests are written in Python, you could set this parameter to 'python', 'python3' or 'python3.8'.

Example:

Expand Down
3 changes: 3 additions & 0 deletions packages/@aws-cdk/integ-runner/lib/cli.ts
Expand Up @@ -30,6 +30,7 @@ async function main() {
.options('from-file', { type: 'string', desc: 'Read TEST names from a file (one TEST per line)' })
.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('test-run-command', { type: 'string', default: 'node', desc: 'The CLI command (such as python, node, or others) that will be applied to the test files. Defaults to node.' })
.strict()
.argv;

Expand Down Expand Up @@ -76,6 +77,7 @@ async function main() {
failedSnapshots = await runSnapshotTests(pool, testsFromArgs, {
retain: argv['inspect-failures'],
verbose: Boolean(argv.verbose),
runCommand: argv['test-run-command'],
});
for (const failure of failedSnapshots) {
destructiveChanges.push(...failure.destructiveChanges ?? []);
Expand All @@ -99,6 +101,7 @@ async function main() {
dryRun: argv['dry-run'],
verbosity: argv.verbose,
updateWorkflow: !argv['disable-update-workflow'],
runCommand: argv['test-run-command'],
});
testsSucceeded = success;

Expand Down
30 changes: 28 additions & 2 deletions packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts
Expand Up @@ -97,7 +97,7 @@ export class IntegTest {
? parsed.name
: path.join(path.relative(this.info.discoveryRoot, parsed.dir), parsed.name);

const nakedTestName = parsed.name.slice(6); // Leave name without 'integ.' and '.ts'
const nakedTestName = IntegrationTests.stripPrefixAndSuffix(parsed.base); // Leave name without 'integ.' and '.ts'
this.normalizedTestName = parsed.name;
this.snapshotDir = path.join(this.directory, `${nakedTestName}.integ.snapshot`);
this.temporaryOutputDir = path.join(this.directory, `${CDK_OUTDIR_PREFIX}.${nakedTestName}`);
Expand Down Expand Up @@ -146,6 +146,32 @@ export interface IntegrationTestFileConfig {
* Discover integration tests
*/
export class IntegrationTests {

public static stripPrefixAndSuffix(fileName: string): string {
const [suffix, prefix] = Array.from(this.acceptedSuffixPrefixMapping)
.find(([suff]) => suff.test(fileName)) ?? ['', ''];

return fileName.replace(prefix, '').replace(suffix, '');
}

/**
* Will discover integration tests with naming conventions typical to each language. Examples:
* - TypeScript/JavaScript: integ.test.ts or integ-test.ts or integ_test.ts
* - Python/Go: integ_test.py
* - Java/C#: IntegTest.cs
* @private
*/
private static acceptedSuffixPrefixMapping: Map<RegExp, RegExp> = new Map<RegExp, RegExp>([
[new RegExp('\\.(cs|java)$'), new RegExp('^Integ')],
[new RegExp('\\.(py|go)$'), new RegExp('^integ_')],
[new RegExp('\\.(js)$'), new RegExp('^integ[-_.]')],
mrgrain marked this conversation as resolved.
Show resolved Hide resolved
]);

private static hasValidPrefixSuffix(fileName: string): boolean {
return Array.from(this.acceptedSuffixPrefixMapping)
.some(([suffix, prefix]) => suffix.test(fileName) && prefix.test(fileName));
}

constructor(private readonly directory: string) {
}

Expand Down Expand Up @@ -212,7 +238,7 @@ export class IntegrationTests {

private async discover(): Promise<IntegTest[]> {
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 => IntegrationTests.hasValidPrefixSuffix(path.basename(fileName)));
return this.request(integs);
}

Expand Down
13 changes: 12 additions & 1 deletion packages/@aws-cdk/integ-runner/lib/runner/runner-base.ts
Expand Up @@ -49,6 +49,14 @@ export interface IntegRunnerOptions {
*/
readonly cdk?: ICdk;

/**
* Integration tests don't have a cdk.json to get the run command from.
* You can specify a custom run command, and it will be applied to all test files.
*
* @default - test run command will be `node`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @default - test run command will be `node`
* @default - a default run command based on the language the test is written in

*/
readonly runCommand?: string;

/**
* Show output from running integration tests
*
Expand Down Expand Up @@ -150,7 +158,10 @@ export abstract class IntegRunner {
},
});
this.cdkOutDir = options.integOutDir ?? this.test.temporaryOutputDir;
this.cdkApp = `node ${path.relative(this.directory, this.test.fileName)}`;

const testRunCommand = options.runCommand ?? 'node';
this.cdkApp = `${testRunCommand} ${path.relative(this.directory, this.test.fileName)}`;

this.profile = options.profile;
if (this.hasSnapshot()) {
this.expectedTestSuite = this.loadManifest();
Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/integ-runner/lib/workers/common.ts
Expand Up @@ -103,6 +103,13 @@ export interface SnapshotVerificationOptions {
* @default false
*/
readonly verbose?: boolean;

/**
* The CLI command used to run the test files.
*
* @default - run command will be `node`
*/
readonly runCommand?: string;
}

/**
Expand Down Expand Up @@ -162,6 +169,13 @@ export interface IntegTestOptions {
* @default true
*/
readonly updateWorkflow?: boolean;

/**
* The CLI command used to run the test files.
*
* @default - run command will be `node`
*/
readonly runCommand?: string;
}

/**
Expand Down
Expand Up @@ -27,6 +27,7 @@ export function integTestWorker(request: IntegTestBatchRequest): IntegTestWorker
env: {
AWS_REGION: request.region,
},
runCommand: request.runCommand,
showOutput: verbosity >= 2,
}, testInfo.destructiveChanges);

Expand Down Expand Up @@ -105,7 +106,7 @@ export function snapshotTestWorker(testInfo: IntegTestInfo, options: SnapshotVer
}, 60_000);

try {
const runner = new IntegSnapshotRunner({ test });
const runner = new IntegSnapshotRunner({ test, runCommand: options.runCommand });
if (!runner.hasSnapshot()) {
workerpool.workerEmit({
reason: DiagnosticReason.NO_SNAPSHOT,
Expand Down
Expand Up @@ -135,6 +135,7 @@ export async function runIntegrationTestsInParallel(
dryRun: options.dryRun,
verbosity: options.verbosity,
updateWorkflow: options.updateWorkflow,
runCommand: options.runCommand,
}], {
on: printResults,
});
Expand Down