1 of 15

Como montamos o conjunto de práticas de testes ideal

2 of 15

Sobre mim

Lucas Medeiros

DevOps @ Involves

Primeiro contato com Go ~2 anos

3 of 15

Avisos

  • Práticas ideais para a nossa realidade
  • O universo é Java, mas temos nossa liberdade
  • 100% de cobertura não significa teste de qualidade e infalível

4 of 15

Os Problemas

  • Mock
  • Sem acompanhamento de Performance
  • Dificuldade de leitura dos testes

5 of 15

Mock

myService := &mocks.MyService{

DoSomethingFunc: func(models.Payload) (models.MyResult, error) {

return models.MyResult{

Data: "Some super important information",

Example: models.ImportantInformation{Important: true},

}, nil

},

SomethingElseFunc: func() error {

return nil

},

}

​

Vamos usar uma lib..

6 of 15

// MyService is an autogenerated mock type for the MyService type

type MyService struct {

mock.Mock

}

​

// DoSomething provides a mock function with given fields: data

func (_m *MyService) DoSomething(data models.Payload) (models.MyResult, error) {

ret := _m.Called(data)

var r0 models.MyResult

if rf, ok := ret.Get(0).(func(models.Payload) models.MyResult); ok {

r0 = rf(data)

} else {

r0 = ret.Get(0).(models.MyResult)

}

var r1 error

if rf, ok := ret.Get(1).(func(models.Payload) error); ok {

r1 = rf(data)

} else {

r1 = ret.Error(1)

}

return r0, r1

}

​

​

7 of 15

8 of 15

Mock

  • Ferramentas com muita dependência
  • Códigos gerados ilegíveis ou não intuitivos
  • Muitas possibilidades, pouco resultado

9 of 15

10 of 15

Momento de reflexão

11 of 15

Ainda há esperança

Nós podemos fazer isso!

​

myService := &mocks.MyService{}

myExpectedResult := models.MyResult{}

myService.On("DoSomething", somePayload).Return(myExpectedResult, nil).Once()

​

​

​

12 of 15

type myServiceMock struct {

doSomethingReturnErr error

doSomethingReturnValue models.MyResult

somethingElseReturnErr error

}

// NewMyServiceMock return a mock structure that implements the MyService Service interface

func NewMyServiceMock() *myServiceMock {

return &myServiceMock{}

}

​

func (m *myServiceMock) SetDoSomethingReturn(r models.MyResult, e error) {

m.doSomethingReturnValue, s.doSomethingReturnErr = r, e

}

func (m *myServiceMock) SetSomethingElseReturn(e error) {

m.somethingElseReturnErr = e

}

// MyService Interface Implementation

func (m *myServiceMock) DoSomething(data models.Payload) (models.MyResult, error) {

return m.doSomethingReturnValue, m.doSomethingReturnErr

}

​

func (m *myServiceMock) SomethingElse() error {

return m.somethingElseReturnErr

}

13 of 15

Em ação

myServiceMock := mocks.NewMyServiceMock()

myExpectedResult := models.MyResult{}

myServiceMock.SetDoSomethingReturn(myExpectedResult, nil)

14 of 15

Performance

  • Benchmarks
  • Load Tests
  • Race

func BenchmarkSomeAction( b *testing.B) {

​

// pre-load //

​

b.ResetTimer()

for n := 0; n < b.N; n++ {

someAction()

}

​

}

Requests [total, rate] 1200, 120.00

Duration [total, attack, wait] 10.094965987s, 9.949883921s, 145.082066ms

Latencies [mean, 50, 95, 99, max] 113.172398ms, 108.272568ms, 140.18235ms, 247.771566ms, 264.815246ms

Bytes In [total, mean] 3714690, 3095.57

Bytes Out [total, mean] 0, 0.00

Success [ratio] 55.42%

Status Codes [code:count] 0:535 200:665

Error Set:

$ go test -race ./...

15 of 15

Dúvidas? Sugestões?

GitHub: @lucasmdrs�E-mail: lucas@lucasmdrs.com��