Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing Serverless Applications - AWS Community Days Sofia

Testing Serverless Applications - AWS Community Days Sofia

Building serverless applications with AWS Lambda sounds exciting, but how does serverless change how we should approach testing? This talk explains the differences with testing serverless applications, what are the risks and how does serverless change integration and unit testing.

---
Aleksandar is an AWS Serverless Hero and an experienced senior software engineer at ScienceExchange, coauthor of “Serverless Applications with Node.js” book, published by Manning Publications. He is based in Belgrade and co-organizer of JS Belgrade, Map Meetup Belgrade and Serverless Belgrade. Contributor to AWS SAM, AWS Lambda Builders and many other open source libraries.

Aleksandar Simovic

May 11, 2019
Tweet

More Decks by Aleksandar Simovic

Other Decks in Programming

Transcript

  1. simalexan Aleksandar Simovic Senior Software Engineer @ ScienceExchange AWS Serverless

    Hero coauthor of “Serverless Applications with Node.js” book AWS SAM & Lambda Builders Contributor
  2. simalexan • “Industry standard”. • “90% test coverage is required.”

    • “Code compliance”. • “You need to ensure that the code works”. The Usual replies
  3. simalexan • “I don’t know, my CTO told me” •

    “I read HackerNews, I want to look smart” • “Because DHH said that.” • “Ensure quality.” The “real” replies
  4. simalexan • John Null • E Lee • GoVeg.com But

    Testing only to find or prevent
 defects is not enough
  5. simalexan Technical workflow risks Handling success / error workflow responses

    Are we using the incoming events
 correctly? Workflow risks
  6. simalexan Business logic 
 risks What is the correct structure

    
 of our data By which order do we process our data? Is the file conversion correct? Are we saving in a correct folder in the bucket?
  7. simalexan Integration risks Are our AppSync GraphQL objects properly set

    in DynamoDB? Are we reading AND
 writing events from API Gateway to S3 correctly?
  8. simalexan Alistair Cockburn Allow an application to equally be driven

    by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.
  9. simalexan const AWS = require('aws-sdk'), stripe = require('stripe'), qs =

    require('querystring'), processResponse = require('./process-response'), stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); exports.handler = async (event) => { if (!event.body) { return processResponse('invalid', 400); } const newCharge = qs.parse(event.body); if (!newCharge.amount || !newCharge.currency) { return 'invalid arguments, please provide amount and currency fields as mentioned in the app README'; } return await stripe.charges.create({ source: newCharge.stripeToken, amount: newCharge.amount, currency: newCharge.currency, description: 'Charge Description' }) };
  10. simalexan const pubsubRepository = require('./pubsub-repository'), paymentProcessorRepository = require('./payment-processor'), TOPIC_ARN =

    process.env.TOPIC_ARN; module.exports = async function chargeCustomer( secretKey, token, email, amount, currency, description = 'Charge Description', paymentProcessor = paymentProcessorRepository, pubsub = pubsubRepository, subject = TOPIC_ARN ){ const createdCharge = await paymentProcessor.createCharge(secretKey, token, amount, currency, description); createdCharge.email = email; await pubsub.publish(createdCharge, subject); return createdCharge; }
  11. simalexan const AWS = require('aws-sdk'), sns = new AWS.SNS(), NO_DATA_REPLY

    = 'You must provide data to the your PubSub'; module.exports = { publish: async function publish( data, topic, pubSub = sns ){ return await pubSub.publish({ Message: JSON.stringify(data), TopicArn: topic }).promise(); } };
  12. simalexan Integration tests are cheaper, but also more important, because

    a common serverless app is split into many small pieces
  13. simalexan • Jest • Jasmine • Mocha • Cypress •

    any other popular tool For example, for Node.js you can use:
  14. simalexan const convertFromSentry = require('../src/convert-from-sentry'), lambdaProxyEvent = require('./test-events/lambda-proxy-event'), wrapEvent =

    (event) => { const result = JSON.parse(JSON.stringify(lambdaProxyEvent)); result.body = JSON.stringify(event); return result; }; describe('Convert from Sentry', () => { describe('Error type', () => { test('should pickup the error type if defined', () => { const event = wrapEvent(require('./test-events/raven-exception')); expect(convertFromSentry(event).type).toBe('TypeError'); }); test('should use runtime error type if undefined', () => { const event = wrapEvent(require('./test-events/raven-manually-tracked')); expect(convertFromSentry(event).type).toBe('RuntimeError'); }); }); describe('Error message', () => { test('should pickup the message if exception value defined', () => { const event = wrapEvent(require('./test-events/raven-exception')); expect(convertFromSentry(event).message).toBe(`Cannot read property 'captureException' of undefined`); }); test('should use body message if exception value undefined', () => { const event = wrapEvent(require('./test-events/raven-manually-tracked')); expect(convertFromSentry(event).message).toBe('error'); }); }); });
  15. simalexan • hexagonal architecture • be smart • test integrations

    that you own • or test your code with a different adapter
  16. simalexan • Jenkins • Travis CI • AWS CodePipeline •

    Semaphore CI • CircleCI • and many more
  17. simalexan Hexagonal Architecture 3 months > 2 weeks Unit /

    Integration testing + = Going serverless + $40,000 > $10
  18. simalexan • Testing your serverless applications is 
 more important

    than ever • One of the goals of testing is to reduce risk • use Hexagonal Architecture to stay flexible • serverless helps testers to do their job faster and cheaper • Testing serverless applications speeds up delivery Key takeaways