Top Banner
SERVERLESS TDD All images copyright Warner Bros. Entertainment Inc.
89

Serverless Test Driven Development

Apr 15, 2017

Download

Software

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Serverless Test Driven Development

SERVERLESS TDD

All images copyright Warner Bros. Entertainment Inc.

Page 2: Serverless Test Driven Development

Filippo Liverani@filippo

Page 3: Serverless Test Driven Development
Page 4: Serverless Test Driven Development

SERVERLESS

Page 5: Serverless Test Driven Development

https://www.flickr.com/photos/mtm/70428057

Page 6: Serverless Test Driven Development

WHAT?

Page 7: Serverless Test Driven Development
Page 8: Serverless Test Driven Development

1. BaaS - Backend as a Service

2. FaaS - Function as a Service

Page 9: Serverless Test Driven Development

1. BaaS - Backend as a Service

2. FaaS - Function as a Service

Page 10: Serverless Test Driven Development

VM

Page 11: Serverless Test Driven Development

VM

CONTAINER

Page 12: Serverless Test Driven Development

VM

CONTAINER

FUNCTION

Page 13: Serverless Test Driven Development

CONCEPTS

stateless

event driven

deployment == upload

scaling

restrictions

Page 14: Serverless Test Driven Development

WHY?

Page 15: Serverless Test Driven Development

run code without managing your server your server applications

team focus on task

CHANGE OF FOCUS

Page 16: Serverless Test Driven Development

new billing model

unprecedented speed to market

Page 17: Serverless Test Driven Development

MICROSERVICES FRIENDLY

MONOLITH

Page 18: Serverless Test Driven Development

MICROSERVICES FRIENDLY

MONOLITH

CONTAINER

CONTAINER

CONTAINER

CONTAINER

Page 19: Serverless Test Driven Development

MICROSERVICES FRIENDLY

MONOLITH

CONTAINER

CONTAINER

CONTAINER

CONTAINER

FUNCTION

FUNCTION

FUNCTION

FUNCTION

FUNCTION

FUNCTION

FUNCTION

FUNCTION

FUNCTION

Page 20: Serverless Test Driven Development

IS IT WORTH IT?

Page 21: Serverless Test Driven Development

BENEFITS

operational and scaling costsfastest scalingsimple deploymentdecreased time to market

Page 22: Serverless Test Driven Development

DRAWBACKS

vendor lock-in and controlrestrictions

startup latencylogging , monitoring and debugging

service discovery

Page 23: Serverless Test Driven Development

TDD

Page 24: Serverless Test Driven Development

WHAT?

Page 25: Serverless Test Driven Development

write a failing unit

test

Page 26: Serverless Test Driven Development

write a failing unit

test

make it pass

Page 27: Serverless Test Driven Development

write a failing unit

test

make it pass

refactor

Page 28: Serverless Test Driven Development

write a failing acceptance

test

Page 29: Serverless Test Driven Development

write a failing

unit test

make it passrefactor

write a failing acceptance

test

Page 30: Serverless Test Driven Development

write a failing

unit test

make it passrefactor

write a failing acceptance

test

Page 31: Serverless Test Driven Development

WHY?

Page 32: Serverless Test Driven Development

small incremental changescontinuous validation

rapid feedback

Page 33: Serverless Test Driven Development

reduces complexitybreaking down a difficult problem

into smaller pieces

Page 34: Serverless Test Driven Development

it drives design

Page 35: Serverless Test Driven Development

IS IT WORTH IT?

Page 36: Serverless Test Driven Development

BENEFITS

higher code qualityregression test suitefeedback and confidence

Page 37: Serverless Test Driven Development

BENEFITS

implicit acceptance criteriaexecutable documentationprevent gold plating

Page 38: Serverless Test Driven Development

CHALLENGES

takes time to masterrequires discipline

changing habits is hardinternal quality perception

Page 39: Serverless Test Driven Development

SOME CODE

Page 40: Serverless Test Driven Development

Client Movies APIHTTP

Page 41: Serverless Test Driven Development

AWS LAMBDA

Page 42: Serverless Test Driven Development

AWS API GATEWAY

Page 43: Serverless Test Driven Development

Client

API Gateway

Lambda

Lambda Proxy integration

HTTP

Page 44: Serverless Test Driven Development

SERVERLESS FRAMEWORK

Page 45: Serverless Test Driven Development

DOCKER

Page 46: Serverless Test Driven Development

FROM ambakshi/amazon-linux

RUN curl -k --silent\

https://nodejs.org/dist/v4.3.2/node-v4.3.2-linux-x64.tar.gz |\

tar --strip-components 1 -xzf - -C /usr/local/

RUN npm install -g [email protected]

WORKDIR /home/ec2user

CMD bash

Dockerfile

Page 47: Serverless Test Driven Development

$ docker build -t xpeppers/lambda .

$ docker run -it -v $(pwd):/home/ec2user xpeppers/lambda

Page 48: Serverless Test Driven Development

$ serverless create --template aws-nodejs

Page 49: Serverless Test Driven Development

Serverless: Creating new Serverless service…

_______ __

| _ .-----.----.--.--.-----.----| .-----.-----.-----.

| |___| -__| _| | | -__| _| | -__|__ --|__ --|

|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|

| | | The Serverless Application Framework

| | serverless.com, v1.0.3

-------'

Serverless: Successfully created service with template: "aws-nodejs"

Serverless: NOTE: Please update the "service" property in serverless.yml

with your service name

Page 50: Serverless Test Driven Development

service: movie-service

provider:

name: aws

runtime: nodejs4.3

stage: test

region: eu-central-1

plugins:

- serverless-offline

functions:

movies:

handler: index.movies

events:

- http:

path: movies

method: get

cors: true

serverless.yml

Page 51: Serverless Test Driven Development

module.exports.movies = (event, context, callback) => {

const response = {

statusCode: 200,

body: '{"message":"Hello!"}'

};

callback(null, response);

};

index.js

Page 52: Serverless Test Driven Development

$ serverless offline start -s development

Page 53: Serverless Test Driven Development

Serverless: Starting Offline: test/eu-central-1.

Serverless: Routes for movies:

Serverless: GET /movies

Serverless: Offline listening on http://localhost:3000

Page 54: Serverless Test Driven Development

$ curl -v localhost:3000/movies

Page 55: Serverless Test Driven Development

< HTTP/1.1 200 OK

< Content-Type: application/json

< vary: origin

< cache-control: no-cache

< content-length: 2

< accept-ranges: bytes

< Date: Fri, 04 Nov 2016 16:24:31 GMT

< Connection: keep-alive

{"message":"Hello!"}

Page 56: Serverless Test Driven Development

Serverless: GET /movies (λ: movies)

Serverless: The first request might take a few extra seconds

Serverless: [200]

{"statusCode":200,"body":"{\"message\":\"Hello!\"}"}

Page 57: Serverless Test Driven Development

{

"name": "serverless-tdd",

"version": "1.0.0"

},

"dependencies": {

"serverless-offline": "3.2.1"

},

"devDependencies": {

"chai": "3.5.0",

"mocha": "3.1.2",

"supertest": "2.0.0",

"supertest-as-promised": "3.2.0"

}

}

package.json

Page 58: Serverless Test Driven Development

$ npm install

$ mkdir -p test/acceptance

Page 59: Serverless Test Driven Development

const endpoint = process.env.ENDPOINT

? process.env.ENDPOINT : 'http://localhost:3000';

const client = supertest(endpoint);

describe('get movies', function() {

it('return movie list', function() {

const movies = require('../../movies.json');

return client.get('/movies')

.expect(200)

.then((res) => {

expect(res.body).to.eql(movies);

});

});

});

test/acceptance/get-movies-test.js

Page 60: Serverless Test Driven Development

[{

"Title":"2001: A Space Odyssey",

"Year":"1968",

"Rated":"G",

"Released":"12 May 1968",

"Runtime":"149 min",

"Genre":"Adventure, Mystery, Sci-Fi",

"Director":"Stanley Kubrick",

"Writer":"Stanley Kubrick (screenplay), Arthur C. Clarke (screenplay)",

"Actors":"Keir Dullea, Gary Lockwood, William Sylvester, Daniel Richter",

...

movies.json

Page 61: Serverless Test Driven Development

$ node_modules/.bin/mocha test/acceptance

Page 62: Serverless Test Driven Development

get movies

1) return movie list

0 passing (28ms)

1 failing

1) get movies return movie list:

AssertionError: expected { message: 'Hello!' } to deeply equal [ Array(4) ]

at test/acceptance/get-movies-test.js:12:29

Page 63: Serverless Test Driven Development

module.exports.movies = (event, context, callback) => {

const movieService = new MovieService();

movieService.getMovies()

.then((response) => {

callback(null, response);

});

};

index.js

Page 64: Serverless Test Driven Development

$ mkdir -p test/unit

Page 65: Serverless Test Driven Development

describe('MovieService', function() {

it('get movies from repository', function() {

const movies = [{Title: "Test Title"}];

const response = {

statusCode: 200,

body: '[{"Title":"Test Title"}]'

};

const movieRepository = sinon.stub();

movieRepository.findAll = sinon.stub().returns(Promise.resolve(movies));

const movieService = new MovieService(movieRepository);

return expect(movieService.getMovies()).to.eventually.eql(response);

});

});

test/unit/movie-service-test.js

Page 66: Serverless Test Driven Development

$ node_modules/.bin/mocha test/unit

Page 67: Serverless Test Driven Development

MovieService

1) get movies from repository

1 failing

1) MovieService get movies from repository:

TypeError: MovieService is not a function

at Context.<anonymous> (test/unit/movie-service-test.js:15:26)

Page 68: Serverless Test Driven Development

class MovieService {

constructor(movieRepository) {

this.movieRepository = (typeof movieRepository !== 'undefined')

? movieRepository : new MovieRepository();

}

getMovies() {

return this.movieRepository.findAll()

.then((movies) => {

return {

statusCode: 200,

body: JSON.stringify(movies)

};

});

}

}

lib/movie-service.js

Page 69: Serverless Test Driven Development

$ node_modules/.bin/mocha test/unit

Page 70: Serverless Test Driven Development

MovieService

✓ get movies from repository

1 passing (21ms)

Page 71: Serverless Test Driven Development

$ mkdir -p test/integration

Page 72: Serverless Test Driven Development

describe('MovieRepository', function() {

it('loads movies from file', function() {

const movies = [{ Title: 'Test Title' }];

movieRepository = new MovieRepository('test/integration/test-movies.json');

return expect(movieRepository.findAll()).to.eventually.eql(movies);

});

});

test/integration/movie-repository-test.js

Page 73: Serverless Test Driven Development

[{ "Title": "Test Title" }]

test/integration/test-movies.json

Page 74: Serverless Test Driven Development

$ node_modules/.bin/mocha test/integration

Page 75: Serverless Test Driven Development

MovieRepository

1) loads movies from file

1 failing

1) MovieRepository loads movies from file:

TypeError: MovieRepository is not a function

at Context.<anonymous> (test/integration/movie-repository-test.js:9:23)

Page 76: Serverless Test Driven Development

class MovieRepository {

constructor(filename) {

this.filename = (typeof filename !== 'undefined')

? filename : 'movies.json';

}

findAll() {

return new Promise((resolve, reject) => {

fs.readFile(this.filename, 'utf8', (err, data) => {

if (err) reject(err);

else resolve(JSON.parse(data));

});

});

}

}

lib/movie-repository.js

Page 77: Serverless Test Driven Development

$ node_modules/.bin/mocha test/integration

Page 78: Serverless Test Driven Development

MovieRepository

✓ loads movies from file

1 passing (25ms)

Page 79: Serverless Test Driven Development

$ node_modules/.bin/mocha test/**

Page 80: Serverless Test Driven Development

get movies

✓ return movie list (57ms)

MovieRepository

✓ loads movies from file

MovieService

✓ get movies from repository

3 passing (99ms)

Page 81: Serverless Test Driven Development

$ curl -v localhost:3000/movies

Page 82: Serverless Test Driven Development

< HTTP/1.1 200 OK

< Content-Type: application/json

< vary: origin

< cache-control: no-cache

< content-length: 2

< accept-ranges: bytes

< Connection: keep-alive

[{"Title":"2001: A Space

Odyssey","Year":"1968","Rated":"G","Released":"12 May

1968","Runtime":"149 min","Genre":"Adventure, Mystery,

Sci-Fi","Director":"Stanley Kubrick","Writer":"Stanley Kubrick

(screenplay), Arthur C. Clarke (screenplay)","Actors":"Keir

Dullea, Gary Lockwood, William Sylvester, Daniel Richter", ...

Page 83: Serverless Test Driven Development

$ export AWS_ACCESS_KEY_ID=<key>

$ export AWS_SECRET_ACCESS_KEY=<secret>

$ serverless deploy

Page 84: Serverless Test Driven Development

Serverless: Packaging service…

Serverless: Uploading CloudFormation file to S3…

Serverless: Uploading service .zip file to S3…

Serverless: Updating Stack…

Serverless: Checking Stack update progress…

..........

Serverless: Stack update finished…

Service Information

service: movie-service

stage: test

region: eu-central-1

api keys:

None

endpoints:

GET - https://xyz.execute-api.eu-central-1.amazonaws.com/test/movies

functions:

movie-service-test-movies:

arn:aws:lambda:eu-central-1:422553113847:function:movie-service-test-movies

Page 85: Serverless Test Driven Development

$ export

ENDPOINT=https://xyz.execute-api.eu-central-1.amazonaws.com/test

$ node_modules/.bin/mocha test/acceptance

Page 86: Serverless Test Driven Development

get movies

✓ return movie list (906ms)

1 passing (919ms)

Page 87: Serverless Test Driven Development

xpeppers/serverless-tdd

Page 88: Serverless Test Driven Development

SERVERLESS + TDD

WE CAN DO IT!

Page 89: Serverless Test Driven Development

THANKS!