Emulate Lambda Locally for Testing and Profiling

Emulambda Is a Way to Locally Run, Profile, and Test Lambda Functions.

Posted by Ryan S. Brown on Tue, Nov 3, 2015
In Project Spotlight
Tags: python, testing, frameworks

Each Lambda function is small, you may not feel the need to write many tests. It’s worth it to write them anyways, you never know what modifications you’ll want to make in the future. Emulambda provides a CLI harness to test your Python functions and profile their resource usage.

Let’s make a Python function and try benchmarking it and calculate costs. Beyond cost planning, I would use Emulambda to test functions that do a lot of parsing of event data, or are invoked in more than one context.

Note: emulambda does not currently support Windows, but can be used if you comment out the usage of the signal and resource modules.

Install Emulambda

If you want to keep your Emulambda setup separate from your system packages, or if your OS doesn’t use Python 2.7 as the default, create a new virtualenv or use pipsi. For this function, we’ll only require Python 2.7 so there won’t be any dependencies other than emulambda.

pip install git+https://github.com/fugue/emulambda.git

Now that it’s installed, make sure the executable is accessible from your shell by running emulambda. You should see something like this:

usage: emulambda [-h] [-s] [-t TIMEOUT] [-v] lambdapath eventfile
emulambda: error: too few arguments

Great, now we can test some code.

Test Lambda Function

Our simple function will just make an HTTP request to the AWS Lambda homepage and check to make sure Lambda still doesn’t need any servers.

import urllib2
def lambda_handler(event, context):
    print "Hello, AWS Lambda"
    lambda_home = urllib2.urlopen("https://aws.amazon.com/lambda/")
    if "No Servers" in lambda_home.read():
        print "Yay, no servers"

Save the function as test_event.py on your local machine. Normally, functions will include libraries, or at least more code, but that’s not the point of this demo.

Test Event Data

To run our test, we need to provide an event for it to react to. The simplest kind of event is a scheduled invocation, so let’s make a test event and save it as test-event.json.

{
  "account": "123456789012",
  "region": "us-east-1",
  "detail": {},
  "detail-type": "Scheduled Event",
  "source": "aws.events",
  "time": "1970-01-01T00:00:00Z",
  "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c",
  "resources": [
    "arn:aws:events:us-east-1:123456789012:rule/my-schedule"
  ]
}

You can find other example events in the Lambda console by configuring the test event for your function.

Running the Test

When we run the test, emulambda will be:

  1. Loading the code in the lambda_handler function.
  2. Parsing the provided test JSON.
  3. Running the function with the input(s) given.
  4. Printing resource usage.

Run the test by supplying the import path for the Lambda function and the test data.

$ emulambda -v test_event.lambda_handler test-event.json
Hello, AWS Lambda
Yay, no servers
Executed test_event.lambda_handler
Estimated...
...execution clock time:                 882ms (900ms billing bucket)
...execution peak RSS memory:            3K (3496 bytes)
----------------------RESULT----------------------
None

Since the code does so little, we can choose to use the smallest Lambda environment, which gives us 128 MB of memory for just 208 nanodollars (0.000000208 USD) per 100 milliseconds. Scaled up, this is 2.08 microdollars per second.

Our function takes 882 milliseconds to run, so we would be billed for 900ms of compute time since Lambda rounds to the next 100ms. Each run costs 1.872 microdollars, meaning for three dollars (the price of a fancy coffee) our test function can run 534,188 times.

Recap

In this post, we’ve seen how to supply events to Lambda functions for local testing, review the memory usage and runtime of our functions, and predict how much they will cost to run.

If you want to hear more about testing Lambda functions, have other questions, or know of a cool project that uses AWS Lambda, drop me a line at ryan@serverlesscode.com or keep up via RSS.


Tweet this, send to Hackernews, or post on Reddit