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

Tests: Refactor test/unit/lib/plugins/aws/package/compile/events/stream.test.js #10330

Open
medikoo opened this issue Dec 10, 2021 · 2 comments
Open

Comments

@medikoo
Copy link
Member

@medikoo medikoo commented Dec 10, 2021

Most of the tests that currently cover core functionalities depend heavily on (and sometimes test) internal implementation characteristics. While they should be testing whether the given implementation produces desired outcome (treating its implementation more as a black box).

Current state of things is problematic for eventual internal improvements and refactors which occasionally we want to introduce, as in most of such cases proposed improvements need to be accompanied with counterproductive numerous updates to tests which are covering otherwise not altered functionalities .

At some point, we've introduced a new (black box based) way of testing the internals. It's through runServerless utility, which allows us to create a natural (as in real-world) serverless instance, and inspect the produced outcome for chosen command. More details here: https://github.com/serverless/serverless/tree/master/test#unit-tests


This is issue is about refactoring test/unit/lib/plugins/aws/package/compile/events/stream.test.js to runServerless based variant.

It's needed, so we cleanly move forward with #8396

To make refactor relatively easy:

  • Spec for new tests is fully defined and is already committed in. It's in the scope of this describe block:
    describe('test/unit/lib/plugins/aws/package/compile/events/stream.test.js', () => {
    describe('regular', () => {
    let eventSourceMappingResource;
    before(async () => {
    const { awsNaming, cfTemplate } = await runServerless({
    fixture: 'function',
    configExt: {
    functions: {
    basic: {
    events: [
    {
    stream: {
    arn: 'arn:aws:kinesis:us-east-1:123456789012:stream/some-long-name',
    functionResponseType: 'ReportBatchItemFailures',
    tumblingWindowInSeconds: 30,
    filterPatterns: [{ eventName: ['INSERT'] }, { eventName: ['MODIFY'] }],
    parallelizationFactor: 10,
    bisectBatchOnFunctionError: true,
    consumer: true,
    },
    },
    ],
    },
    dynamo: {
    handler: 'basic.handler',
    events: [
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/foo/stream/1',
    batchSize: 1,
    startingPosition: 'LATEST',
    enabled: false,
    batchWindow: 15,
    maximumRetryAttempts: 4,
    maximumRecordAgeInSeconds: 120,
    destinations: {
    onFailure: 'arn:aws:sns:region:account:snstopic',
    },
    },
    },
    ],
    },
    kinesisImportCustomIam: {
    handler: 'basic.handler',
    role: {
    'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:role/iam-role-name',
    },
    events: [
    {
    stream: {
    arn: { 'Fn::ImportValue': 'ForeignKinesis' },
    type: 'kinesis',
    consumer:
    'arn:aws:kinesis:region:account:stream/xyz/consumer/foobar:1558544531',
    },
    },
    ],
    },
    arnVariants: {
    handler: 'basic.handler',
    events: [
    {
    stream: {
    arn: { 'Fn::GetAtt': ['SomeDdbTable', 'StreamArn'] },
    type: 'dynamodb',
    destinations: {
    onFailure: {
    arn: { 'Fn::ImportValue': 'ForeignSQS' },
    type: 'sqs',
    },
    },
    },
    },
    {
    stream: {
    arn: {
    'Fn::Join': [
    ':',
    [
    'arn',
    'aws',
    'kinesis',
    {
    Ref: 'AWS::Region',
    },
    {
    Ref: 'AWS::AccountId',
    },
    'stream/MyStream',
    ],
    ],
    },
    type: 'kinesis',
    },
    },
    {
    stream: {
    arn: { Ref: 'SomeDdbTableStreamArn' },
    type: 'dynamodb',
    destinations: {
    onFailure: {
    arn: { 'Fn::ImportValue': 'ForeignSQS' },
    type: 'sqs',
    },
    },
    },
    },
    {
    stream: {
    arn: { Ref: 'ForeignKinesisStreamArn' },
    type: 'kinesis',
    },
    },
    ],
    },
    destinationVariants: {
    handler: 'basic.handler',
    events: [
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/foo/stream/1',
    destinations: {
    onFailure: {
    arn: { 'Fn::GetAtt': ['SomeSNS', 'Arn'] },
    type: 'sns',
    },
    },
    },
    },
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/foo/stream/1',
    destinations: {
    onFailure: {
    arn: {
    'Fn::Join': [
    ':',
    [
    'arn',
    'aws',
    'sqs',
    {
    Ref: 'AWS::Region',
    },
    {
    Ref: 'AWS::AccountId',
    },
    'MyQueue',
    ],
    ],
    },
    type: 'sqs',
    },
    },
    },
    },
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/buzz/stream/1',
    destinations: {
    onFailure: {
    arn: { Ref: 'SomeSNSArn' },
    type: 'sns',
    },
    },
    },
    },
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/fizz/stream/1',
    destinations: {
    onFailure: {
    arn: { Ref: 'ForeignSQSArn' },
    type: 'sqs',
    },
    },
    },
    },
    ],
    },
    },
    },
    command: 'package',
    });
    const streamLogicalId = awsNaming.getStreamLogicalId('basic', 'kinesis', 'some-long-name');
    eventSourceMappingResource = cfTemplate.Resources[streamLogicalId];
    });
    it.skip('TODO: should support ARN String for `arn`', () => {
    // Replaces
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453 (partially)
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1574-L1591
    //
    // Confirm effect of:
    // - `functions.basic.events[0].stream.arn`
    // - `functions.dynamodb.events[0].stream.arn`
    });
    it.skip('TODO: should support Fn::GetAtt for `arn`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L586-L741
    //
    // Confirm effect of `functions.arnVariants.events[0].stream.arn`
    });
    it.skip('TODO: should support Fn::ImportValue for `arn`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L586-L741
    //
    // Confirm effect of `functions.kinesisImportCustomIam.events[0].stream.arn`
    });
    it.skip('TODO: should support Fn::Join for `arn`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L586-L741
    //
    // Confirm effect of `functions.arnVariants.events[1].stream.arn`
    });
    it.skip('TODO: should support Ref for `arn`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L586-L741
    //
    // Confirm effect of:
    // - `functions.arnVariants.events[2].stream.arn`
    // - `functions.arnVariants.events[3].stream.arn`
    });
    it.skip('TODO: should support `batchSize`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.batchSize`
    });
    it.skip('TODO: should support `startingPosition`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.startingPosition`
    });
    it.skip('TODO: should support `enabled`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.enabled`
    });
    it.skip('TODO: should support `batchWindow`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.batchWindow`
    });
    it.skip('TODO: should support `maximumRetryAttempts`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.maximumRetryAttempts`
    });
    it.skip('TODO: should support `maximumRecordAgeInSeconds`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.dynamo.events[0].stream.maximumRecordAgeInSeconds`
    });
    it.skip('TODO: should support `parallelizationFactor`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.basic.events[0].stream.parallelizationFactor`
    });
    it.skip('TODO: should support `bisectBatchOnFunctionError`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1106-L1453
    //
    // Confirm effect of `functions.basic.events[0].stream.bisectBatchOnFunctionError`
    });
    it.skip('TODO: should support `consumer`', () => {
    // Replaces
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1437-L1465
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1467-L1539 (partially)
    //
    // Confirm effect of:
    // - `functions.basic.events[0].stream.consumer`
    // - `functions.kinesisImportCustomIam.events[0].stream.consumer`
    });
    it.skip('TODO: should support ARN string for `destinations.onFailure`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L370-L584
    //
    // Confirm effect of: `functions.dynamo.events[0].stream.destinations`
    });
    it.skip('TODO: should support Fn::GetAtt for `destinations.onFailure`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L743-L916
    //
    // Confirm effect of: `functions.destinationVariants.events[0].stream.destinations`
    });
    it.skip('TODO: should support Fn::ImportValue for `destinations.onFailure`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L743-L916
    //
    // Confirm effect of: `functions.arnVariants.events[2].stream.destinations`
    });
    it.skip('TODO: should support Fn::Join for `destinations.onFailure`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L743-L916
    //
    // Confirm effect of: `functions.destinationVariants.events[1].stream.destinations`
    });
    it.skip('TODO: should support Ref for `destinations.onFailure`', () => {
    // Replaces partially
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L743-L916
    //
    // Confirm effect of:
    // - `functions.destinationVariants.events[2].stream.destinations`
    // - `functions.destinationVariants.events[3].stream.destinations`
    });
    it('should support `functionResponseType`', () => {
    expect(eventSourceMappingResource.Properties.FunctionResponseTypes).to.include.members([
    'ReportBatchItemFailures',
    ]);
    });
    it('should support `tumblingWindowInSeconds`', () => {
    expect(eventSourceMappingResource.Properties.TumblingWindowInSeconds).to.equal(30);
    });
    it('should support `filterPatterns`', () => {
    expect(eventSourceMappingResource.Properties.FilterCriteria).to.deep.equal({
    Filters: [
    {
    Pattern: JSON.stringify({ eventName: ['INSERT'] }),
    },
    {
    Pattern: JSON.stringify({ eventName: ['MODIFY'] }),
    },
    ],
    });
    });
    it.skip('TODO: should ensure necessary IAM statememnts', () => {
    // Replaces
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L87-L366
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1056-L1103
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L1467-L1539 (partially)
    //
    // Confirm expected IAM statements on final role
    });
    });
    describe.skip('TODO: failures', () => {
    it("should fail if stream `type` is not set and couldn't be assumed", async () => {
    // Replaces
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L918-L932
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L955-L969
    await expect(
    runServerless({
    fixture: 'function',
    command: 'package',
    configExt: {
    functions: {
    basic: {
    events: [
    {
    stream: {
    arn: { Ref: 'SomeDdbTableStreamArn' },
    },
    },
    ],
    },
    },
    },
    })
    ).to.be.eventually.rejected.and.have.property('code', 'TODO');
    });
    it("should fail if destination `type` is not set and couldn't be assumed", async () => {
    // Replaces
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L934-L953
    // https://github.com/serverless/serverless/blob/f64f7c68abb1d6837ecaa6173f4b605cf3975acf/test/unit/lib/plugins/aws/package/compile/events/stream.test.js#L971-L990
    await expect(
    runServerless({
    fixture: 'function',
    command: 'package',
    configExt: {
    functions: {
    basic: {
    events: [
    {
    stream: {
    arn: 'arn:aws:dynamodb:region:account:table/fizz/stream/1',
    destinations: {
    onFailure: {
    arn: { Ref: 'ForeignSQSArn' },
    },
    },
    },
    },
    ],
    },
    },
    },
    })
    ).to.be.eventually.rejected.and.have.property('code', 'TODO');
    });
    });
    describe('with provisioned concurrency', () => {
    let naming;
    let eventSourceMappingResource;
    before(async () => {
    const { awsNaming, cfTemplate } = await runServerless({
    fixture: 'function',
    configExt: {
    functions: {
    basic: {
    provisionedConcurrency: 1,
    events: [{ stream: 'arn:aws:kinesis:us-east-1:123456789012:stream/myStream' }],
    },
    },
    },
    command: 'package',
    });
    naming = awsNaming;
    const streamLogicalId = awsNaming.getStreamLogicalId('basic', 'kinesis', 'myStream');
    eventSourceMappingResource = cfTemplate.Resources[streamLogicalId];
    });
    it('should reference provisioned alias', () => {
    expect(eventSourceMappingResource.Properties.FunctionName).to.deep.equal({
    'Fn::Join': [
    ':',
    [
    {
    'Fn::GetAtt': ['BasicLambdaFunction', 'Arn'],
    },
    'provisioned',
    ],
    ],
    });
    });
    it('should depend on provisioned alias', () => {
    const aliasLogicalId = naming.getLambdaProvisionedConcurrencyAliasLogicalId('basic');
    expect(eventSourceMappingResource.DependsOn).to.include(aliasLogicalId);
    });
    });
  • Each test slot indicates which test it is about to replace
  • It is indicated where (and how many) exactly runServerless runs are expected to happen, against which fixture and command they should be based
  • Necessary hints are provided

For every refactored test, the old test should be removed

Refactor can be submitted with one PR, but partial refactors are also very welcome

@olgashi
Copy link

@olgashi olgashi commented Jan 14, 2022

@medikoo
Can I please be assigned to this one?

@medikoo
Copy link
Member Author

@medikoo medikoo commented Jan 14, 2022

@olgashi done, Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants