Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Feature: Test Framework Utilities #193

Closed
beanaroo opened this issue Oct 15, 2020 · 9 comments
Closed

Feature: Test Framework Utilities #193

beanaroo opened this issue Oct 15, 2020 · 9 comments
Assignees
Labels
feature-request feature request need-customer-feedback Requires more customers feedback before making or revisiting a decision

Comments

@beanaroo
Copy link

Describe the solution you'd like
This is a follow up of #144 (comment).

Having Data Classes and Typing has made a significant difference! Being able to leverage them in testing using provided samples, mocks and/or fixtures could be useful too.

A dedicated module might make sense in order not to modify existing utilities to accommodate testing ability.

Describe alternatives you've considered

  • aws_lambda_context module as described in the linked thread.
  • Sub-classing LambdaContext with setters only - not possible as Python requires @property to be redeclared

Additional context

In the mean time, I've had success with:

import pytest
from aws_lambda_powertools.utilities.typing import LambdaContext


class MockLambdaContext(LambdaContext):

    def __init__(self):
        self._function_name = 'test-fn'
        self._memory_limit_in_mb = 128
        self._invoked_function_arn = 'arn:aws:lambda:us-east-1:12345678:function:test-fn'
        self._aws_request_id = '52fdfc07-2182-154f-163f-5f0f9a621d72'


@pytest.fixture
def lambda_context() -> LambdaContext:
    return MockLambdaContext()

I was also not able to use the documented suggestion as provided. Not sure if this warrants a separate issue.

Screenshot

image

@beanaroo beanaroo added feature-request feature request triage Pending triage from maintainers labels Oct 15, 2020
@heitorlessa heitorlessa removed the triage Pending triage from maintainers label Oct 22, 2020
@to-mc
Copy link
Contributor

to-mc commented Oct 23, 2020

Thanks for this @beanaroo, and apologies for the long turnaround. Before I get stuck in to this I wanted to understand what wasn't working for you with the documented suggestion. Was it just the "Unexpected argument" hint in PyCharm you shared in a screenshot, or did it actually not work at runtime? I'm fairly sure the warning is due to a bug with PyCharm's inspections, as opposed to something wrong with the suggestion.

@to-mc to-mc pinned this issue Oct 28, 2020
@to-mc to-mc added the need-customer-feedback Requires more customers feedback before making or revisiting a decision label Oct 28, 2020
@to-mc
Copy link
Contributor

to-mc commented Oct 28, 2020

To widen the scope a bit here - I'm interested to learn more about what people find difficult or painful when testing Lambda functions, and/or any suggestions on how we can help!

@Nr18
Copy link

Nr18 commented Dec 7, 2020

I created the following class in my top-level __init__.py

import uuid
from aws_lambda_powertools.utilities.typing import LambdaContext


class LambdaTestContext(LambdaContext):

    def __init__(self, name: str, version: int = 1, region: str = "us-east-1", account_id: str = "111122223333"):
        self._function_name = name
        self._function_version = str(version)
        self._memory_limit_in_mb = 128
        self._invoked_function_arn = f"arn:aws:lambda:{region}:{account_id}:function:{name}:{version}"
        self._aws_request_id = str(uuid.uuid4())
        self._log_group_name = f"/aws/lambda/{name}"
        self._log_stream_name = str(uuid.uuid4())


Context = LambdaTestContext("MyFunctionName")

And then in my tests, I do something like this:

from tests import Context
import src.my_function.index as index

index.handler({}, Context)

I was thinking of a good place where to place the LambdaTestContext in the power tools, as we don't have tools yet for testing...

@heitorlessa
Copy link
Contributor

Yesterday, I was hunting a SNS+SQS issue (#272) and spent 80% of my time on trying to create a clean and realistic event I could test with.

This reminded me of this issue. While we didn't receive more feedback from customers, here's what I wish I had available that would've cut down 80% of my effort on the #272 PR:

  • A Pytest fixture for SNS + SQS event (largely different from SNS + Lambda only)
  • Allow me to set the body payload so I could parametrize happy and unhappy paths

Similar to the Event Data sources utility, we could move all of our test events into builder classes, where one could a) use the default payload/headers or set them, and b) create their own fixture (if pytest) or mechanism from their final object .build().

Take Kinesis, or CloudWatch Logs for example - Unit testing this not only require knowing the payload structure, but also extra boilerplate to encode it properly - bytes+base64 in the case of Kinesis, and bytes+base64+zip in the case of CloudWatch Logs.

We can do better for our customers, and for ourselves too. This would be the MVP vote for me

@Nr18
Copy link

Nr18 commented Jan 20, 2021

Right, forgot that this issue existed indeed!

So things that we are facing during development, often you use DynamoDB in Lambda functions and when unit testing you don't want to stub, mock and monkeypatch all sort of things. You want to focus on the business logic not that DynamoDB is called properly and that the mocks fit the schema that the stubber expects. This bloats the test and draws away the focus of the test case itself.

So I would love to have a simple framework that dows the heavy lifting of just that, we worked around the issue by creating a wrapper around the dynamodb client and use a monkeypatch to let it return the expected data in a simple format.

@michaelbrewer
Copy link
Contributor

I think making it easier for people to getting setup for testing with provided mocks or recommendations on what tools to use for mocking or testing AWS services. (I am a fan of using moto for simplicity)

@Nr18
Copy link

Nr18 commented Mar 8, 2021

@michaelbrewer I always avoided moto to be honest but that was because I tent to use it in unit tests and that slows them down, unit tests should be fast. That being said that does not mean that moto should not be part of the "test framework" that we are discussing here, moto could help a lot with integration tests.

I think proper documentation and good examples would prevent people from using moto in unit tests and steer them into the direction of integration tests when they want to use moto?

@michaelbrewer
Copy link
Contributor

@Nr18 different things for different people and development styles.

What has worked for me was to initially use moto (over much slower tools like sam local), to build out my lambda and run initial behavioral tests until the basics was done. Then I don't have to know too much about how the the internals of boto3 works. For AWS Powertools specifically, if would be nice to include a test utilities package to allow you similar experience, but to your point a lot faster.

Once my lambda meets the requirements and I have simplified the implementation and I felt like the structure was stable, then I would put in the mocks which would be called via the CI pipeline and speed would matter.

@michaelbrewer
Copy link
Contributor

@heitorlessa we should bump this up

@aws-powertools aws-powertools locked and limited conversation to collaborators Mar 12, 2021
@heitorlessa heitorlessa unpinned this issue Mar 15, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
feature-request feature request need-customer-feedback Requires more customers feedback before making or revisiting a decision
Projects
None yet
Development

No branches or pull requests

5 participants