Skip to content

Commit

Permalink
feat(integ-runner): support --language presets
Browse files Browse the repository at this point in the history
  • Loading branch information
mrgrain committed Nov 11, 2022
1 parent e29df69 commit 47e1534
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 8 deletions.
4 changes: 3 additions & 1 deletion packages/@aws-cdk/integ-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ to be a self contained CDK app. The runner will execute the following for each f
- `--verbose` (default=`false`)
verbose logging, including integration test metrics
(specify multiple times to increase verbosity)
- `--parallel-regions` (default=`us-east-1`,`us-east-2`, `us-west-2`)
- `--parallel-regions` (default=`us-east-1`,`us-east-2`,`us-west-2`)
List of regions to run tests in. If this is provided then all tests will
be run in parallel across these regions
- `--directory` (default=`test`)
Expand All @@ -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
- `--language [javascript|typescript|python|java|csharp|fsharp|go]` (default=`javascript`)
Use a preset to run integration tests for the selected language
- `--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`
Expand Down
19 changes: 15 additions & 4 deletions packages/@aws-cdk/integ-runner/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as path from 'path';
import * as chalk from 'chalk';
import * as workerpool from 'workerpool';
import * as logger from './logger';
import { IntegrationTests, IntegTestInfo, IntegTest } from './runner/integration-tests';
import { IntegrationTests, IntegTestInfo, IntegTest, IntegrationTestsDiscoveryOptions, IntegrationTestsDiscovery } from './runner/integration-tests';
import { runSnapshotTests, runIntegrationTests, IntegRunnerMetrics, IntegTestWorkerConfig, DestructiveChange } from './workers';

// https://github.com/yargs/yargs/issues/1929
Expand All @@ -30,6 +30,13 @@ export async function main(args: string[]) {
.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('language', {
alias: 'l',
default: 'javascript',
choices: ['javascript', 'typescript', 'python', 'java', 'csharp', 'fsharp', 'go'],
type: 'array',
desc: 'Use this preset to run integration tests for the selected language',
})
.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()
Expand All @@ -51,6 +58,11 @@ export async function main(args: string[]) {
const fromFile: string | undefined = argv['from-file'];
const exclude: boolean = argv.exclude;
const app: string | undefined = argv.app;
const discoveryOptions: IntegrationTestsDiscoveryOptions = {
...IntegrationTestsDiscovery.fromLanguagePreset(argv.language),
app,
testRegex,
};

let failedSnapshots: IntegTestWorkerConfig[] = [];
if (argv['max-workers'] < testRegions.length * (profiles ?? [1]).length) {
Expand All @@ -60,7 +72,7 @@ export async function main(args: string[]) {
let testsSucceeded = false;
try {
if (argv.list) {
const tests = await new IntegrationTests(argv.directory).fromCliArgs({ testRegex, app });
const tests = await new IntegrationTests(argv.directory).fromCliArgs(discoveryOptions);
process.stdout.write(tests.map(t => t.discoveryRelativeFileName).join('\n') + '\n');
return;
}
Expand All @@ -73,8 +85,7 @@ export async function main(args: string[]) {
: (argv._.length > 0 ? argv._ : undefined); // 'undefined' means no request

testsFromArgs.push(...(await new IntegrationTests(path.resolve(argv.directory)).fromCliArgs({
app,
testRegex,
...discoveryOptions,
tests: requestedTests,
exclude,
})));
Expand Down
59 changes: 56 additions & 3 deletions packages/@aws-cdk/integ-runner/lib/runner/integration-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,42 @@ export class IntegTest {
}
}

/**
* Returns the name of the Python executable for this OS
*/
function pythonExecutable() {
let python = 'python3';
if (process.platform === 'win32') {
python = 'python';
}
return python;
}

class IntegrationTestPreset {
public constructor(readonly app: string, readonly testRegex: string[]) {}
}

const PRESETS = {
javascript: new IntegrationTestPreset('node {filePath}', ['^integ\..*\.js$/']),
typescript: new IntegrationTestPreset('node -r ts-node/register {filePath}', ['^integ\.(?!.*\.d\.ts$).*\.ts$']),
python: new IntegrationTestPreset(`${pythonExecutable()} {filePath}`, ['^integ_.*\.py$']),
csharp: new IntegrationTestPreset('dotnet run --project {filePath}', ['^Integ.*\.csproj$']),
fsharp: new IntegrationTestPreset('dotnet run --project {filePath}', ['^Integ.*\.fsproj$']),
// these are still unconfirmed and need testing
go: new IntegrationTestPreset('go mod download && go run {filePath}', ['^integ_.*\.go$']),
java: new IntegrationTestPreset('mvn -e -q compile exec:java', ['^Integ.*\.java$']),
};

export enum Language {
JAVASCRIPT = 'javascript',
TYPESCRIPT = 'typescript',
PYTHON = 'python',
GO = 'go',
JAVA = 'java',
CSHARP = 'csharp',
FSHARP = 'fsharp'
}

/**
* Configuration options how integration test files are discovered
*/
Expand Down Expand Up @@ -174,16 +210,30 @@ export interface IntegrationTestsDiscoveryOptions {
readonly app?: string;
}

export class IntegrationTestsDiscovery {
/**
* Get integration tests discovery options from a language preset.
*/
public static fromLanguagePreset(language?: Language): IntegrationTestsDiscoveryOptions {
if (language && PRESETS[language]) {
return PRESETS[language];
}
return {};
}

private constructor() {}
}


/**
* 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`)
* Language preset used for integration test
*/
readonly tests: string[];
readonly language?: Language;
}

/**
Expand All @@ -200,7 +250,10 @@ export class IntegrationTests {
public async fromFile(fileName: string): Promise<IntegTest[]> {
const file: IntegrationTestFileConfig = JSON.parse(fs.readFileSync(fileName, { encoding: 'utf-8' }));

return this.discover(file);
return this.discover({
...IntegrationTestsDiscovery.fromLanguagePreset(file.language),
...file,
});
}

/**
Expand Down

0 comments on commit 47e1534

Please sign in to comment.