SlideShare uma empresa Scribd logo
1 de 63
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テスト[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テストTakahiro Moteki
 
Amazon Aurora Deep Dive (db tech showcase 2016)
Amazon Aurora Deep Dive (db tech showcase 2016)Amazon Aurora Deep Dive (db tech showcase 2016)
Amazon Aurora Deep Dive (db tech showcase 2016)Amazon Web Services Japan
 
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~hideakikabuto
 
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)Masanori KAMAYAMA
 
Office365のIdentity管理
Office365のIdentity管理Office365のIdentity管理
Office365のIdentity管理Naohiro Fujie
 
AWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
AWS Black Belt Online Seminar 2017 AWS Elastic BeanstalkAWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
AWS Black Belt Online Seminar 2017 AWS Elastic BeanstalkAmazon Web Services Japan
 
Goの時刻に関するテスト
Goの時刻に関するテストGoの時刻に関するテスト
Goの時刻に関するテストKentaro Kawano
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティスAmazon Web Services Japan
 
AWS Black Belt Online Seminar 2017 Amazon Athena
AWS Black Belt Online Seminar 2017 Amazon AthenaAWS Black Belt Online Seminar 2017 Amazon Athena
AWS Black Belt Online Seminar 2017 Amazon AthenaAmazon Web Services Japan
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とToru Takahashi
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールdcubeio
 
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdf
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdfわたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdf
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdfssuser868e2d
 
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)Trainocate Japan, Ltd.
 
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証ASP.NET CoreとAzure AD B2Cを使ったサクっと認証
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証Yuta Matsumura
 
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法de:code 2017
 
AWS Lambdaで作るクローラー/スクレイピング
AWS Lambdaで作るクローラー/スクレイピングAWS Lambdaで作るクローラー/スクレイピング
AWS Lambdaで作るクローラー/スクレイピングTakuro Sasaki
 
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...Amazon Web Services Japan
 
実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門Naohiro Fujie
 
AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報Amazon Web Services Japan
 

Mais procurados (20)

[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テスト[社内勉強会]ELBとALBと数万スパイク負荷テスト
[社内勉強会]ELBとALBと数万スパイク負荷テスト
 
Amazon Aurora Deep Dive (db tech showcase 2016)
Amazon Aurora Deep Dive (db tech showcase 2016)Amazon Aurora Deep Dive (db tech showcase 2016)
Amazon Aurora Deep Dive (db tech showcase 2016)
 
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~
 
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)
IDaaS を利用すべき理由とエンジニアがおさえておくべきポイント (2021年1月14日)
 
Office365のIdentity管理
Office365のIdentity管理Office365のIdentity管理
Office365のIdentity管理
 
DevOps with Database on AWS
DevOps with Database on AWSDevOps with Database on AWS
DevOps with Database on AWS
 
AWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
AWS Black Belt Online Seminar 2017 AWS Elastic BeanstalkAWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
AWS Black Belt Online Seminar 2017 AWS Elastic Beanstalk
 
Goの時刻に関するテスト
Goの時刻に関するテストGoの時刻に関するテスト
Goの時刻に関するテスト
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
 
AWS Black Belt Online Seminar 2017 Amazon Athena
AWS Black Belt Online Seminar 2017 Amazon AthenaAWS Black Belt Online Seminar 2017 Amazon Athena
AWS Black Belt Online Seminar 2017 Amazon Athena
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツール
 
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdf
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdfわたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdf
わたくし、やっぱりCDKを使いたいですわ〜CDK import編〜.pdf
 
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)
Amazon ECS AWS Fargate あるとき~ ないとき~ (トレノケ雲の会 mod2)
 
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証ASP.NET CoreとAzure AD B2Cを使ったサクっと認証
ASP.NET CoreとAzure AD B2Cを使ったサクっと認証
 
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
[DI08] その情報うまく取り出せていますか? ~ 意外と簡単、Azure Search で短時間で検索精度と利便性を向上させるための方法
 
AWS Lambdaで作るクローラー/スクレイピング
AWS Lambdaで作るクローラー/スクレイピングAWS Lambdaで作るクローラー/スクレイピング
AWS Lambdaで作るクローラー/スクレイピング
 
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...
20180704 AWS Black Belt Online Seminar Amazon Elastic File System (Amazon EFS...
 
実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門
 
AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報
 

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

Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web AppsMark
 
HashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureHashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureNicolas Corrarello
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on AndroidSven Haiges
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interfaceJoakim Gustin
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interfaceEvolve
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackNelson Glauber Leal
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaFrank Lyaruu
 
Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...Docker, Inc.
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185Mahmoud Samir Fayed
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good TestsTomek Kaczanowski
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopSages
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in GolangBo-Yi Wu
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScriptQiangning Hong
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster DivingRonnBlack
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google GoFrank Müller
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
 

Semelhante a 外部環境への依存をテストする (20)

Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web Apps
 
HashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureHashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin Infrastructure
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
 
Net/http and the http.handler interface
Net/http and the http.handler interfaceNet/http and the http.handler interface
Net/http and the http.handler interface
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Non Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJavaNon Blocking I/O for Everyone with RxJava
Non Blocking I/O for Everyone with RxJava
 
Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Deep Dumpster Diving
Deep Dumpster DivingDeep Dumpster Diving
Deep Dumpster Diving
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 

Mais de Shunsuke Maeda

私とOSS活動とPerl
私とOSS活動とPerl私とOSS活動とPerl
私とOSS活動とPerlShunsuke Maeda
 
テストを書いてGradleプラグインの開発効率を改善しよう
テストを書いてGradleプラグインの開発効率を改善しようテストを書いてGradleプラグインの開発効率を改善しよう
テストを書いてGradleプラグインの開発効率を改善しようShunsuke Maeda
 
iOSにおけるコードレビューを一歩先へ進める
iOSにおけるコードレビューを一歩先へ進めるiOSにおけるコードレビューを一歩先へ進める
iOSにおけるコードレビューを一歩先へ進めるShunsuke Maeda
 
iOSで利用できるデバイスファームのメリット・デメリットの紹介
iOSで利用できるデバイスファームのメリット・デメリットの紹介iOSで利用できるデバイスファームのメリット・デメリットの紹介
iOSで利用できるデバイスファームのメリット・デメリットの紹介Shunsuke Maeda
 
Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Shunsuke Maeda
 
Dangerでpull requestレビューの指摘事項を減らす
Dangerでpull requestレビューの指摘事項を減らすDangerでpull requestレビューの指摘事項を減らす
Dangerでpull requestレビューの指摘事項を減らすShunsuke Maeda
 

Mais de Shunsuke Maeda (7)

私とOSS活動とPerl
私とOSS活動とPerl私とOSS活動とPerl
私とOSS活動とPerl
 
テストを書いてGradleプラグインの開発効率を改善しよう
テストを書いてGradleプラグインの開発効率を改善しようテストを書いてGradleプラグインの開発効率を改善しよう
テストを書いてGradleプラグインの開発効率を改善しよう
 
DroidKaigi_devicefarm
DroidKaigi_devicefarmDroidKaigi_devicefarm
DroidKaigi_devicefarm
 
iOSにおけるコードレビューを一歩先へ進める
iOSにおけるコードレビューを一歩先へ進めるiOSにおけるコードレビューを一歩先へ進める
iOSにおけるコードレビューを一歩先へ進める
 
iOSで利用できるデバイスファームのメリット・デメリットの紹介
iOSで利用できるデバイスファームのメリット・デメリットの紹介iOSで利用できるデバイスファームのメリット・デメリットの紹介
iOSで利用できるデバイスファームのメリット・デメリットの紹介
 
Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化
 
Dangerでpull requestレビューの指摘事項を減らす
Dangerでpull requestレビューの指摘事項を減らすDangerでpull requestレビューの指摘事項を減らす
Dangerでpull requestレビューの指摘事項を減らす
 

Último

Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 

Último (20)

Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 

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

  • 11. ( ) • Incoming HTTP Requests • Git Docker ( ) • • • Outgoing HTTP Requests
  • 12.
  • 13. • Incoming HTTP Requests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 14. 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 , . "
  • 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. Incoming HTTP Requests • httptest • URL
  • 25. • Incoming HTTP Requests • 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 Moby interface { 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 HTTP Requests • Git Docker ( ) ) • ( • • Outgoing HTTP Requests
  • 37. package logger var Writer io.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) } }
  • 44. • Incoming HTTP Requests • 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 HTTP Requests • 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) } }
  • 63. • oc • H • ) ( k • P T • p • he ) (M