powertools-lambda-typescript icon indicating copy to clipboard operation
powertools-lambda-typescript copied to clipboard

RFC: Testing Factories for AWS Data Objects

Open simonireilly opened this issue 3 years ago • 5 comments

ref https://github.com/awslabs/aws-lambda-powertools-typescript/issues/26for strucutre of my RFC

Description of the proposal

There should be a consistent way to produce test fixtures for AWS lambda environments


Name of the core utility (and consequently the folders that contain the libraries):

  • packages/factories

Justification

When it comes to making effective use of AWS in unit and integration testing, developers will create data objects which have the interfaces of the 'aws-lambda' types package.

This is true, even within this project;

  • Here, for testing the SQS event format is compatible with a function interface: https://github.com/awslabs/aws-lambda-powertools-typescript/pull/364/files#r780652925
  • Here, where a collection of untyped JSON is used for testing fixtures: https://github.com/awslabs/aws-lambda-powertools-typescript/tree/main/tests/resources/events/aws

These untyped objects become a cause for churn, and often because a single source of truth is not present, they can misdiagnose behaviors through simple omission of fields.

Goals

  • Provide users of the nodejs lambda platform effective utilities for testing lambda handler
  • Provide consistent type-safe factories for AWS data structures and events
  • Support version of event formats to test utilities against different versions

Proposed API

There is an example here that utilizes faker and fishery to create type compliant factories that can be deep merged to allow for standard testing objects:

  • https://github.com/simonireilly/aws-cdk-utils/tree/main/packages/factories

Installation:

yarn add --dev @aws-lambda-powertools/factories
npm i -d @aws-lambda-powertools/factories

Usage

Consider the following test that is written in #364


test('when called, it set the correct segment', () => {
  // Prepare
  const provider: ProviderService = new ProviderService();
  const record: SQSRecord = {
    messageId: 'fd95260b-1600-4028-b252-590cfcc9fe6d',
    receiptHandle: 'test',
    body: 'Information about current NY Times fiction bestseller for week of 12/11/2016.',
    attributes: {
      ApproximateReceiveCount: '1',
      AWSTraceHeader: 'Root=1-61cc1005-53ff3b575736e3c74eae6bfb;Parent=1f57c53badf96998;Sampled=1',
      SentTimestamp: '1640763398126',
      SenderId: 'AROAT26JIZQWSOCCOUNE5:sqsProducer',
      ApproximateFirstReceiveTimestamp: '1640763398127',
    },
    messageAttributes: {},
    md5OfBody: 'bbdc5fdb8be7251f5c910905db994bab',
    eventSource: 'aws:sqs',
    eventSourceARN:
      'arn:aws:sqs:eu-west-1:123456789012:queue',
    awsRegion: 'eu-west-1',
  };

  const context = ContextExamples.helloworldContext;

  // Act
  provider.continueSQSRecordTrace(record, context);

  // Assess
  expect(setSegment).toHaveBeenCalledTimes(1);
});

This test becomes:

import factories from '@aws-lambda-powertools/factories';


test('when called, it set the correct segment', () => {
  // Prepare
  const provider: ProviderService = new ProviderService();
  const record = factories.sqs.record.build();
  const context = factories.sqs.context.build();

  // Act
  provider.continueSQSRecordTrace(record, context);

  // Assess
  expect(setSegment).toHaveBeenCalledTimes(1);
});

simonireilly avatar Jan 08 '22 10:01 simonireilly

@heitorlessa it is worth thinking about this across both Python, Java and Typescript (awslabs/aws-lambda-powertools-python#1169)

michaelbrewer avatar Jan 08 '22 23:01 michaelbrewer

Thanks for opening this issue @simonireilly. As a former AWS customer, I would like to say that this is something I wanted myself as well, back then. The team and I will get back to you on this one.

saragerion avatar Jan 10 '22 12:01 saragerion

I've been using @serverless/event-mocks for this, there are a few others, all are out of date and not maintained.

willfarrell avatar Jan 27 '22 22:01 willfarrell

For Python is have a lot of mocks and sample events. So whichever solution we have in mind it would be great to has the potential for reuse across python, typescript, Java and .Net.

michaelbrewer avatar Jan 28 '22 02:01 michaelbrewer