Golang.tokyo
2018/08/21 (Tue)
( @duck8823 )
•
• @duck8823
•
• /
•
• Kotlin
• Golang
•
• @duck8823
•
•
•
• Kotlin
• Golang
•
• @duck8823
•
•
•
• Kotlin
• Golang
CI
• duck8823/duci
• Golang
• Docker
CI
• duck8823/duci
• Golang
• Docker
CI
• duck8823/duci
• Golang
• Docker
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
( )
• Incoming HTTP Requests
• Git Docker ( )
•
•
• Outgoing HTTP Requests
• Incoming HTTP Requests
• Git Docker ( ) )
• (
•
• Outgoing HTTP Requests
Incoming HTTP Requests
func HandlerFunc(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
body, _ := ioutil.ReadAll(r.Body)
w.Write([]byte(fmt.Sprintf("Hello %s.", body)))
}
• HandlerFunc
, . "
HandlerFunc
func Test_HandlerFunc(t *testing.T) {
// given
req := httptest.NewRequest("HELLO", "/", strings.NewReader("world"))
rec := httptest.NewRecorder()
// when
HandlerFunc(rec, req)
// then
if rec.Code != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code)
}
if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) {
t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes()))
}
}
HandlerFunc
func Test_HandlerFunc(t *testing.T) {
// given
req := httptest.NewRequest("HELLO", "/", strings.NewReader("world"))
rec := httptest.NewRecorder()
// when
HandlerFunc(rec, req)
// then
if rec.Code != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code)
}
if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) {
t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes()))
}
}
http.ResponseWriter
(*httptest.ResponseRecorder)
*http.Request
HandlerFunc
func Test_HandlerFunc(t *testing.T) {
// given
req := httptest.NewRequest("HELLO", "/", strings.NewReader("world"))
rec := httptest.NewRecorder()
// when
HandlerFunc(rec, req)
// then
if rec.Code != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code)
}
if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) {
t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes()))
}
}
HandlerFunc
func Test_HandlerFunc(t *testing.T) {
// given
req := httptest.NewRequest("HELLO", "/", strings.NewReader("world"))
rec := httptest.NewRecorder()
// when
HandlerFunc(rec, req)
// then
if rec.Code != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code)
}
if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) {
t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes()))
}
}
*httptest.ResponseRecorder
chi HandlerFunc
• URL ("/{param}") HandlerFunc
go-chi/chi
// "/{param}"
func ChiHandlerFunc(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
param := chi.URLParam(r.Context(), "param")
w.Write([]byte(fmt.Sprintf("Hello %s.", param)))
}
chi HandlerFunc
func TestChiHandlerFunc(t *testing.T) {
// given
ctx := chi.NewContext()
ctx.Params.Add("param", "world")
req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx)
rec := httptest.NewRecorder()
// when
ChiHandlerFunc(rec, req)
// then
// ...check rec
}
chi HandlerFunc
func TestChiHandlerFunc(t *testing.T) {
// given
ctx := chi.NewContext()
ctx.Params.Add("param", "world")
req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx)
rec := httptest.NewRecorder()
// when
ChiHandlerFunc(rec, req)
// then
// ...check rec
}
context.Context
chi HandlerFunc
func TestChiHandlerFunc(t *testing.T) {
// given
ctx := chi.NewContext()
ctx.Params.Add("param", "world")
req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx)
rec := httptest.NewRecorder()
// when
ChiHandlerFunc(rec, req)
// then
// ...check rec
}
*http.Request
context.Context
chi HandlerFunc
func TestChiHandlerFunc(t *testing.T) {
// given
ctx := chi.NewContext()
ctx.Params.Add("param", "world")
req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx)
rec := httptest.NewRecorder()
// when
ChiHandlerFunc(rec, req)
// then
// ...check rec
}
Incoming HTTP Requests
• httptest
• URL
• Incoming HTTP Requests
• Git Docker ( ) )
• (
•
• Outgoing HTTP Requests
Git Docker (3rd )
•
src-d/go-git moby/moby
•
•
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
}
• ( docker run )
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
}
• ( docker run )
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
}
• ( docker run )
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
}
• ( docker run )
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
}
• ( docker run )
type docker struct {
moby *client.Client
}
func (d *docker) Run(image string, cmd ...string) {
ctx := context.Background()
_, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{})
con, _ := d.moby.ContainerCreate(ctx, &container.Config{
Image: image,
Cmd: cmd
}, nil, nil, "")
err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{})
} .
•
Mock
• *client.Client
type Moby interface {
ImagePull(...) (...)
ContainerCreate(...) (container.ContainerCreateCreatedBody, error)
ContainerStart(...) error
}
type docker struct {
moby Moby
}
Mock
• google/mock/gomock
func TestDocker_Run(t *testing.T) {
ctrl := gomock.NewController(t)
mockMoby := NewMockMoby(ctrl)
mockMoby.EXPECT().
ImagePull(gomock.Any(), gomock.Any(), gomock.Any()).
AnyTimes().
Return(nil, errors.New("error image pull"))
docker := &docker{moby: mockMoby}
docker.Run("centos", "echo", "hello world")
}
Git Docker (3rd )
•
• gomock
•
( mock )
• Incoming HTTP Requests
• Git Docker ( ) )
• (
•
• Outgoing HTTP Requests
package logger
var Writer io.Writer = os.Stdout
func Debug(message string) {
fmt.Fprintf(Writer, "[DEBUG] %sn", message)
}
•
• ( os.Stdout ) io.Writer (*os.File )
func TestDebug(t *testing.T) {
// given
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "[DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
writer.Close()
actual, _ := ioutil.ReadAll(reader)
if string(actual) != expected {
t.Errorf("wont %s, but got %s", expected, actual)
}
}
func TestDebug(t *testing.T) {
// given
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "[DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
writer.Close()
actual, _ := ioutil.ReadAll(reader)
if string(actual) != expected {
t.Errorf("wont %s, but got %s", expected, actual)
}
}
) (
).(
1
( ( 2
func TestDebug(t *testing.T) {
// given
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "[DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
writer.Close()
actual, _ := ioutil.ReadAll(reader)
if string(actual) != expected {
t.Errorf("wont %s, but got %s", expected, actual)
}
}
func TestDebug(t *testing.T) {
// given
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "[DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
writer.Close()
actual, _ := ioutil.ReadAll(reader)
if string(actual) != expected {
t.Errorf("wont %s, but got %s", expected, actual)
}
}
func TestDebug(t *testing.T) {
// given
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "[DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
writer.Close()
actual, _ := ioutil.ReadAll(reader)
if string(actual) != expected {
t.Errorf("wont %s, but got %s", expected, actual)
}
}
• io.Writer
io.Pipe
• Incoming HTTP Requests
• Git Docker ( ) )
• (
•
• Outgoing HTTP Requests
•
func Debug(message string) {
now := time.Now().Format("2006-01-02 15:04:05")
fmt.Fprintf(Writer, "%s [DEBUG] %sn", now, message)
}
time.Now()
•
func Debug(message string) {
now := clock.Now().Format("2006-01-02 15:04:05")
fmt.Fprintf(Writer, "%s [DEBUG] %sn", now, message)
}
package clock
import "time"
var Now = func () time.Time {
return time.Now()
}
func TestDebug(t *testing.T) {
// given
jst, _ := time.LoadLocation("Asia/Tokyo")
clock.Now = func() time.Time {
return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst)
}
// and
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
// ...
}
func TestDebug(t *testing.T) {
// given
jst, _ := time.LoadLocation("Asia/Tokyo")
clock.Now = func() time.Time {
return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst)
}
// and
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
// ...
}
.
func TestDebug(t *testing.T) {
// given
jst, _ := time.LoadLocation("Asia/Tokyo")
clock.Now = func() time.Time {
return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst)
}
// and
reader, writer, _ := os.Pipe()
logger.Writer = writer
// and
expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n"
// when
logger.Debug("Hello World.")
// then
// ...
}
• ( )
• time.Now
• Incoming HTTP Requests
• Git Docker ( ) )
• (
•
• Outgoing HTTP Requests
Outgoing HTTP Requests
• EO
• IL P
• H / D G RA
Outgoing HTTP Requests
• 2 ) ) / ( (
func TestRequest(t *testing.T) {
defer gock.Off()
gock.New("http://example.com").
Post("/").
Reply(http.StatusOK)
resp, _ := http.Post("http://example.com/", "application/json", nil)
if resp.StatusCode != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode)
}
}
Outgoing HTTP Requests
• 2 ) ) / ( (
func TestRequest(t *testing.T) {
defer gock.Off()
gock.New("http://example.com").
Post("/").
Reply(http.StatusOK)
resp, _ := http.Post("http://example.com/", "application/json", nil)
if resp.StatusCode != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode)
}
}
Outgoing HTTP Requests
• 2 ) ) / ( (
func TestRequest(t *testing.T) {
defer gock.Off()
gock.New("http://example.com").
Post("/").
Reply(http.StatusOK)
resp, _ := http.Post("http://example.com/", "application/json", nil)
if resp.StatusCode != http.StatusOK {
t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode)
}
}
Outgoing HTTP Requests
•
•
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
Webhooks
(HTTP)
Commit Status
(HTTP)
)& )
.
& &(
Webhooks
(HTTP)
Commit Status
(HTTP)
• oc
• H
• ) ( k
• P T
• p
• he ) (M

外部環境への依存をテストする

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    ( ) • IncomingHTTP Requests • Git Docker ( ) • • • Outgoing HTTP Requests
  • 13.
    • Incoming HTTPRequests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 14.
    Incoming HTTP Requests funcHandlerFunc(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) body, _ := ioutil.ReadAll(r.Body) w.Write([]byte(fmt.Sprintf("Hello %s.", body))) } • HandlerFunc , . "
  • 15.
    HandlerFunc func Test_HandlerFunc(t *testing.T){ // given req := httptest.NewRequest("HELLO", "/", strings.NewReader("world")) rec := httptest.NewRecorder() // when HandlerFunc(rec, req) // then if rec.Code != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code) } if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) { t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes())) } }
  • 16.
    HandlerFunc func Test_HandlerFunc(t *testing.T){ // given req := httptest.NewRequest("HELLO", "/", strings.NewReader("world")) rec := httptest.NewRecorder() // when HandlerFunc(rec, req) // then if rec.Code != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code) } if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) { t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes())) } } http.ResponseWriter (*httptest.ResponseRecorder) *http.Request
  • 17.
    HandlerFunc func Test_HandlerFunc(t *testing.T){ // given req := httptest.NewRequest("HELLO", "/", strings.NewReader("world")) rec := httptest.NewRecorder() // when HandlerFunc(rec, req) // then if rec.Code != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code) } if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) { t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes())) } }
  • 18.
    HandlerFunc func Test_HandlerFunc(t *testing.T){ // given req := httptest.NewRequest("HELLO", "/", strings.NewReader("world")) rec := httptest.NewRecorder() // when HandlerFunc(rec, req) // then if rec.Code != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, rec.Code) } if !reflect.DeepEqual(rec.Body.Bytes(), []byte("Hello world.")) { t.Errorf("wont %+v, but got %+v","Hello world.", string(rec.Body.Bytes())) } } *httptest.ResponseRecorder
  • 19.
    chi HandlerFunc • URL("/{param}") HandlerFunc go-chi/chi // "/{param}" func ChiHandlerFunc(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) param := chi.URLParam(r.Context(), "param") w.Write([]byte(fmt.Sprintf("Hello %s.", param))) }
  • 20.
    chi HandlerFunc func TestChiHandlerFunc(t*testing.T) { // given ctx := chi.NewContext() ctx.Params.Add("param", "world") req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx) rec := httptest.NewRecorder() // when ChiHandlerFunc(rec, req) // then // ...check rec }
  • 21.
    chi HandlerFunc func TestChiHandlerFunc(t*testing.T) { // given ctx := chi.NewContext() ctx.Params.Add("param", "world") req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx) rec := httptest.NewRecorder() // when ChiHandlerFunc(rec, req) // then // ...check rec } context.Context
  • 22.
    chi HandlerFunc func TestChiHandlerFunc(t*testing.T) { // given ctx := chi.NewContext() ctx.Params.Add("param", "world") req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx) rec := httptest.NewRecorder() // when ChiHandlerFunc(rec, req) // then // ...check rec } *http.Request context.Context
  • 23.
    chi HandlerFunc func TestChiHandlerFunc(t*testing.T) { // given ctx := chi.NewContext() ctx.Params.Add("param", "world") req := httptest.NewRequest("HELLO", "/", nil).WithContext(ctx) rec := httptest.NewRecorder() // when ChiHandlerFunc(rec, req) // then // ...check rec }
  • 24.
  • 25.
    • Incoming HTTPRequests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 26.
    Git Docker (3rd) • src-d/go-git moby/moby • •
  • 27.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } • ( docker run )
  • 28.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } • ( docker run )
  • 29.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } • ( docker run )
  • 30.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } • ( docker run )
  • 31.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } • ( docker run )
  • 32.
    type docker struct{ moby *client.Client } func (d *docker) Run(image string, cmd ...string) { ctx := context.Background() _, err := d.moby.ImagePull(ctx, image, types.ImagePullOptions{}) con, _ := d.moby.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd }, nil, nil, "") err := d.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}) } . •
  • 33.
    Mock • *client.Client type Mobyinterface { ImagePull(...) (...) ContainerCreate(...) (container.ContainerCreateCreatedBody, error) ContainerStart(...) error } type docker struct { moby Moby }
  • 34.
    Mock • google/mock/gomock func TestDocker_Run(t*testing.T) { ctrl := gomock.NewController(t) mockMoby := NewMockMoby(ctrl) mockMoby.EXPECT(). ImagePull(gomock.Any(), gomock.Any(), gomock.Any()). AnyTimes(). Return(nil, errors.New("error image pull")) docker := &docker{moby: mockMoby} docker.Run("centos", "echo", "hello world") }
  • 35.
    Git Docker (3rd) • • gomock • ( mock )
  • 36.
    • Incoming HTTPRequests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 37.
    package logger var Writerio.Writer = os.Stdout func Debug(message string) { fmt.Fprintf(Writer, "[DEBUG] %sn", message) } • • ( os.Stdout ) io.Writer (*os.File )
  • 38.
    func TestDebug(t *testing.T){ // given reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "[DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then writer.Close() actual, _ := ioutil.ReadAll(reader) if string(actual) != expected { t.Errorf("wont %s, but got %s", expected, actual) } }
  • 39.
    func TestDebug(t *testing.T){ // given reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "[DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then writer.Close() actual, _ := ioutil.ReadAll(reader) if string(actual) != expected { t.Errorf("wont %s, but got %s", expected, actual) } } ) ( ).( 1 ( ( 2
  • 40.
    func TestDebug(t *testing.T){ // given reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "[DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then writer.Close() actual, _ := ioutil.ReadAll(reader) if string(actual) != expected { t.Errorf("wont %s, but got %s", expected, actual) } }
  • 41.
    func TestDebug(t *testing.T){ // given reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "[DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then writer.Close() actual, _ := ioutil.ReadAll(reader) if string(actual) != expected { t.Errorf("wont %s, but got %s", expected, actual) } }
  • 42.
    func TestDebug(t *testing.T){ // given reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "[DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then writer.Close() actual, _ := ioutil.ReadAll(reader) if string(actual) != expected { t.Errorf("wont %s, but got %s", expected, actual) } }
  • 43.
  • 44.
    • Incoming HTTPRequests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 45.
    • func Debug(message string){ now := time.Now().Format("2006-01-02 15:04:05") fmt.Fprintf(Writer, "%s [DEBUG] %sn", now, message) }
  • 46.
    time.Now() • func Debug(message string){ now := clock.Now().Format("2006-01-02 15:04:05") fmt.Fprintf(Writer, "%s [DEBUG] %sn", now, message) } package clock import "time" var Now = func () time.Time { return time.Now() }
  • 47.
    func TestDebug(t *testing.T){ // given jst, _ := time.LoadLocation("Asia/Tokyo") clock.Now = func() time.Time { return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst) } // and reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then // ... }
  • 48.
    func TestDebug(t *testing.T){ // given jst, _ := time.LoadLocation("Asia/Tokyo") clock.Now = func() time.Time { return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst) } // and reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then // ... } .
  • 49.
    func TestDebug(t *testing.T){ // given jst, _ := time.LoadLocation("Asia/Tokyo") clock.Now = func() time.Time { return time.Date(1987, time.March, 27, 09, 34, 00, 00, jst) } // and reader, writer, _ := os.Pipe() logger.Writer = writer // and expected := "1987-03-27 09:34:00 [DEBUG] Hello World.n" // when logger.Debug("Hello World.") // then // ... }
  • 50.
    • ( ) •time.Now
  • 51.
    • Incoming HTTPRequests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 52.
    Outgoing HTTP Requests •EO • IL P • H / D G RA
  • 53.
    Outgoing HTTP Requests •2 ) ) / ( ( func TestRequest(t *testing.T) { defer gock.Off() gock.New("http://example.com"). Post("/"). Reply(http.StatusOK) resp, _ := http.Post("http://example.com/", "application/json", nil) if resp.StatusCode != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode) } }
  • 54.
    Outgoing HTTP Requests •2 ) ) / ( ( func TestRequest(t *testing.T) { defer gock.Off() gock.New("http://example.com"). Post("/"). Reply(http.StatusOK) resp, _ := http.Post("http://example.com/", "application/json", nil) if resp.StatusCode != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode) } }
  • 55.
    Outgoing HTTP Requests •2 ) ) / ( ( func TestRequest(t *testing.T) { defer gock.Off() gock.New("http://example.com"). Post("/"). Reply(http.StatusOK) resp, _ := http.Post("http://example.com/", "application/json", nil) if resp.StatusCode != http.StatusOK { t.Errorf("wont %+v, but got %+v", http.StatusOK, resp.StatusCode) } }
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
    • oc • H •) ( k • P T • p • he ) (M