Skip to content

Commit

Permalink
feat(integ-tests): add IntegTest to group test cases (#20015)
Browse files Browse the repository at this point in the history
Add a new construct, `IntegTest` that contains a list of `IntegTestCase`s. This new construct is now responsible for starting the synthesis of the manifests. Previously, it was `IntegTestCase` that did this. But this results in the last `IntegTestCase` to be synthesized to override all other test cases.

----

### All Submissions:

* [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/master/INTEGRATION_TESTS.md)?
	* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
otaviomacedo authored Apr 22, 2022
1 parent 0848312 commit b4f8d91
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 16 deletions.
20 changes: 16 additions & 4 deletions packages/@aws-cdk/integ-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ certain handler:

```ts
interface StackUnderTestProps extends StackProps {
functionProps?: lambda.FunctionProps;
architecture?: lambda.Architecture;
}

class StackUnderTest extends Stack {
Expand All @@ -34,7 +34,7 @@ class StackUnderTest extends Stack {
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
...props.functionProps,
architecture: props.architecture,
});
}
}
Expand Down Expand Up @@ -67,7 +67,8 @@ class StackUnderTest extends Stack {
const app = new App();

const stack = new Stack(app, 'stack');
new IntegTestCase(stack, 'DifferentArchitectures', {

const differentArchsCase = new IntegTestCase(stack, 'DifferentArchitectures', {
stacks: [
new StackUnderTest(app, 'Stack1', {
architecture: lambda.Architecture.ARM_64,
Expand All @@ -77,6 +78,13 @@ new IntegTestCase(stack, 'DifferentArchitectures', {
}),
],
});

// There must be exactly one instance of TestCase per file
new IntegTest(app, 'integ-test', {

// Register as many test cases as you want here
testCases: [differentArchsCase],
});
```

This is all the instruction you need for the integration test runner to know
Expand All @@ -90,7 +98,7 @@ const stackUnderTest = new Stack(app, 'StackUnderTest', /* ... */);

const stack = new Stack(app, 'stack');

new IntegTestCase(stack, 'CustomizedDeploymentWorkflow', {
const testCase = new IntegTestCase(stack, 'CustomizedDeploymentWorkflow', {
stacks: [stackUnderTest],
diffAssets: true,
stackUpdateWorkflow: true,
Expand All @@ -108,5 +116,9 @@ new IntegTestCase(stack, 'CustomizedDeploymentWorkflow', {
},
},
});

new IntegTest(app, 'integ-test', {
testCases: [testCase],
});
```

30 changes: 30 additions & 0 deletions packages/@aws-cdk/integ-tests/lib/manifest-synthesizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IntegManifest, Manifest } from '@aws-cdk/cloud-assembly-schema';
import { ISynthesisSession } from '@aws-cdk/core';
import { IntegManifestWriter } from './manifest-writer';
import { IntegTestCase } from './test-case';

const emptyManifest: IntegManifest = {
version: '',
testCases: { },
};

export class IntegManifestSynthesizer {
constructor(private readonly testCases: IntegTestCase[]) {}

synthesize(session: ISynthesisSession) {
const manifest = this.testCases
.map(tc => tc.manifest)
.reduce(mergeManifests, emptyManifest);

const snapshotDir = session.assembly.outdir;

IntegManifestWriter.write(manifest, snapshotDir);
}
}

function mergeManifests(m1: IntegManifest, m2: IntegManifest): IntegManifest {
return {
version: Manifest.version(),
testCases: { ...m1.testCases, ...m2.testCases },
};
}
50 changes: 39 additions & 11 deletions packages/@aws-cdk/integ-tests/lib/test-case.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IntegManifest, TestCase, TestOptions } from '@aws-cdk/cloud-assembly-schema';
import { attachCustomSynthesis, ISynthesisSession, Stack } from '@aws-cdk/core';
import { IntegManifestWriter } from './manifest-writer';
import { IntegManifest, Manifest, TestCase, TestOptions } from '@aws-cdk/cloud-assembly-schema';
import { attachCustomSynthesis, Stack, ISynthesisSession } from '@aws-cdk/core';
import { IntegManifestSynthesizer } from './manifest-synthesizer';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
Expand All @@ -21,18 +21,46 @@ export interface IntegTestCaseProps extends TestOptions {
* apply to all stacks under this case.
*/
export class IntegTestCase extends Construct {
constructor(scope: Construct, id: string, props: IntegTestCaseProps) {
constructor(scope: Construct, private readonly id: string, private readonly props: IntegTestCaseProps) {
super(scope, id);
}

/**
* The integration test manifest for this test case. Manifests are used
* by the integration test runner.
*/
get manifest(): IntegManifest {
return {
version: Manifest.version(),
testCases: { [this.id]: toTestCase(this.props) },
};
}
}

/**
* Integration test properties
*/
export interface IntegTestProps {
/**
* List of test cases that make up this test
*/
readonly testCases: IntegTestCase[];
}

/**
* A collection of test cases. Each test case file should contain exactly one
* instance of this class.
*/
export class IntegTest extends Construct {
constructor(scope: Construct, id: string, private readonly props: IntegTestProps) {
super(scope, id);
}

protected onPrepare(): void {
attachCustomSynthesis(this, {
onSynthesize: (session: ISynthesisSession) => {
const snapshotDir = session.assembly.outdir;
const manifest: IntegManifest = {
version: '',
testCases: { [id]: toTestCase(props) },
};

IntegManifestWriter.write(manifest, snapshotDir);
const synthesizer = new IntegManifestSynthesizer(this.props.testCases);
synthesizer.synthesize(session);
},
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/integ-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"dependencies": {
"@aws-cdk/cloud-assembly-schema": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/cx-api": "0.0.0",
"constructs": "^3.3.69"
},
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/integ-tests/rosetta/default.ts-fixture
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as lambda from '@aws-cdk/aws-lambda';
import { IntegTestCase } from '@aws-cdk/integ-tests';
import { IntegTestCase, IntegTest } from '@aws-cdk/integ-tests';
import {
App,
Construct,
Expand Down
45 changes: 45 additions & 0 deletions packages/@aws-cdk/integ-tests/test/manifest-synthesizer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { App, Stack } from '@aws-cdk/core';
import { CloudAssemblyBuilder } from '@aws-cdk/cx-api';
import { IntegTestCase } from '../lib';
import { IntegManifestSynthesizer } from '../lib/manifest-synthesizer';
import { IntegManifestWriter } from '../lib/manifest-writer';

describe(IntegManifestSynthesizer, () => {
it('synthesizes a multiple manifests', () => {
const write = jest.spyOn(IntegManifestWriter, 'write');

const app = new App();
const stack = new Stack(app, 'stack');
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-test'));
const assembly = new CloudAssemblyBuilder(tmpDir);

const synthesizer = new IntegManifestSynthesizer([
new IntegTestCase(stack, 'case1', {
stacks: [new Stack(app, 'stack-under-test-1')],
}),
new IntegTestCase(stack, 'case2', {
stacks: [new Stack(app, 'stack-under-test-2')],
}),
]);

synthesizer.synthesize({
assembly,
outdir: 'asdas',
});

expect(write).toHaveBeenCalledWith({
version: '17.0.0',
testCases: {
case1: {
stacks: ['stack-under-test-1'],
},
case2: {
stacks: ['stack-under-test-2'],
},
},
}, tmpDir);
});
});

0 comments on commit b4f8d91

Please sign in to comment.