Slide 1

Slide 1 text

Testing Against AWS APIs With Go Steve Scaffidi
 HERE Technologies Github/Twitter: @hercynium

Slide 2

Slide 2 text

Testing live systems is challenging

Slide 3

Slide 3 text

You do test, right?

Slide 4

Slide 4 text

Mock AWS* *neener, neener, neener!

Slide 5

Slide 5 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") instanceIds := GetAwsInstanceIds(awsSess) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(awsSess *awsSession.Session) []string { instanceIds := make([]string, 0) ec2Api := ec2.New(awsSess) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 6

Slide 6 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") instanceIds := GetAwsInstanceIds(awsSess) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(awsSess *awsSession.Session) []string { instanceIds := make([]string, 0) ec2Api := ec2.New(awsSess) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 7

Slide 7 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") instanceIds := GetAwsInstanceIds(awsSess) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(awsSess *awsSession.Session) []string { instanceIds := make([]string, 0) ec2Api := ec2.New(awsSess) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) From: https://godoc.org/github.com/aws/aws-sdk-go/service/ec2/ec2iface

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") instanceIds := GetAwsInstanceIds(awsSess) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(awsSess *awsSession.Session) []string { instanceIds := make([]string, 0) ec2Api := ec2.New(awsSess) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 12

Slide 12 text

Mock the Client APIs

Slide 13

Slide 13 text

ec2.EC2 --> ec2iface.EC2API

Slide 14

Slide 14 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") ec2Api := ec2.New(awsSess) instanceIds := GetAwsInstanceIds(ec2Api) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(ec2Api ec2iface.EC2API) []string { instanceIds := make([]string, 0) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 15

Slide 15 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") ec2Api := ec2.New(awsSess) instanceIds := GetAwsInstanceIds(ec2Api) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(ec2Api ec2iface.EC2API) []string { instanceIds := make([]string, 0) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 16

Slide 16 text

func main() { awsSess, e := awsSession.NewSession() kingpin.FatalIfError(e, "Could not create AWS API session") ec2Api := ec2.New(awsSess) instanceIds := GetAwsInstanceIds(ec2Api) for _, id := range instanceIds { fmt.Println(id) } } func GetAwsInstanceIds(ec2Api ec2iface.EC2API) []string { instanceIds := make([]string, 0) instDescrs, err := ec2Api.DescribeInstances(&ec2.DescribeInstancesInput{}) kingpin.FatalIfError(err, "Could not get EC2 instances") for _, res := range instDescrs.Reservations { for _, instance := range res.Instances { instanceIds = append(instanceIds, *instance.InstanceId) } } return instanceIds }

Slide 17

Slide 17 text

func makeInstance(instanceId string) *ec2.Instance { return &ec2.Instance{InstanceId: aws.String(instanceId)} } func makeDescribeInstancesOutput(instanceIds []string)
 *ec2.DescribeInstancesOutput { instances := make([]*ec2.Instance, 0) for _, id := range instanceIds { instances = append(instances, makeInstance(id)) } return &ec2.DescribeInstancesOutput{ Reservations: []*ec2.Reservation{ { Instances: instances, }, }, } }

Slide 18

Slide 18 text

type testAwsEc2API struct { ec2iface.EC2API instanceIds []string } func (d testAwsEc2API) DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { return makeDescribeInstancesOutput(d.instanceIds), nil }

Slide 19

Slide 19 text

type testAwsEc2API struct { ec2iface.EC2API instanceIds []string } func (d testAwsEc2API) DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { return makeDescribeInstancesOutput(d.instanceIds), nil }

Slide 20

Slide 20 text

func Test_GetAwsInstanceIds(t *testing.T) { tests := []struct { name string instanceIds []string }{ { name: "get all instance IDs", instanceIds:
 []string{"i-11111", "i-22222", "i-33333"}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { ec2API := &testAwsEc2API{ instanceIds: test.instanceIds, } gotInstanceIds := GetAwsInstanceIds(ec2API) assert.Equal(t, test.instanceIds, gotInstanceIds) }) } }

Slide 21

Slide 21 text

func Test_GetAwsInstanceIds(t *testing.T) { tests := []struct { name string instanceIds []string }{ { name: "get all instance IDs", instanceIds:
 []string{"i-11111", "i-22222", "i-33333"}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { ec2API := &testAwsEc2API{ instanceIds: test.instanceIds, } gotInstanceIds := GetAwsInstanceIds(ec2API) assert.Equal(t, test.instanceIds, gotInstanceIds) }) } }

Slide 22

Slide 22 text

Time for a live demo?

Slide 23

Slide 23 text

Thank You!