SlideShare a Scribd company logo
1 of 40
Download to read offline
メルカリアッテの
実務で使えた、
GAE/Goの開発を
効率的にする方法
2016/11/08(火)
@appengine ja night #35
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
アジェンダ
● 自己紹介
● GAE/Goのテストを効率化する
○ インスタンスを使いまわす
○ テストの並列化
○ 差分テスト
○ ビルドタグとテスト
● GAE/Goのデバッグ
○ Goとデバッガ
○ ローカルサーバでデバッグ
自己紹介
メルカリ/ソウゾウ
上田拓也
twitter: @tenntenn
■ Go歴 / GAE歴
Go:5〜6年くらい?
GAE:最近再開、GCPUG Tokyoのスタッフ
■ 業務
GAE/Goでメルカリアッテを作ってます
Goのコミュニティを盛り上げる仕事
Gopherを描く仕事
引用元:https://cloud.google.com/about/locations/japan/
東京 GCP リージョン!
アッテ開発の技術 : Golang と Google App Engine
テスト書いてますか?
画像:http://www.slideshare.net/t_wada/jasst-2014-hokkaidotwadatdd#4
Goはテスト書きやすい
■ コンパイルする強み
● 多くのバグがコンパイルで検出できる
● 型や引数のテストは必要なし
● 重要な部分のテストに集中できる
■ インタフェースを使ってテスト
● io.Writerとio.Reader
● テストしやすい設計がやりやすい
■ 標準ツールでテストができる
● フレームワークを覚える必要なし
● Goが読めればテストが読める
参考:Goとテスト
じゃあ、なぜテスト書かないのか?
テストを書かなくなる理由
■ テストが重い
● aetestが重い
● テストするパッケージが大量にある
■ やっぱりifをたくさん書くのは大変
● フレームワーク使いたい
■ テストする時間がない
● 実装だけで精一杯
aetestとは?
■ 何ができるのか?
● http.Requestが生成できる
● context.Contextが生成できる
● テストからDatastoreなどを使える
■ どうやってるのか?
● ローカルサーバを起動
○ dev_appserver.pyを使用
■ ドキュメント
● Local Unit Testing for Go
● The aetest package
aetestの使い方
ctx, done, err := aetest.NewContext()
if err != nil {...}
defer done()
it := &memcache.Item{
Key: "some-key",
Value: []byte("some-value"),
}
err = memcache.Set(ctx, it)
if err != nil {...}
it, err = memcache.Get(ctx, "some-key")
if err != nil {...}
if string(it.Value) != "some-value" {
...
}
内部で
aetest.NewInstance()
が呼ばれている
Memcacheへ
アクセスしている
aetestが遅い理由
■ ローカルサーバの立ち上げが遅い
● NewInstanceの度に立ち上がる
● テストの数が増えればその分増える
func Test1(t *testing.T) {
ctx, done, err := aetest.NewContext()
...
}
func Test2(t *testing.T) {
ctx, done, err := aetest.NewContext()
...
}
この度に
サーバが立ちあがる!
favclip/testerator
■ テスト間でインスタンスを使いまわせる
● https://github.com/favclip/testerator
testerator.SpinUp()
testerator.SpinUp()
testerator.SpinUp()
testerator.SpinDown()
testerator.SpinDown()
testerator.SpinDown()
起動
影響なし
Datastore, Memcache,
Search APIを初期化
終了
テストの並列化
■ テストを並列化する
● t.Parallelを呼び出す
func Test1(t *testing.T) {
t.Parallel()
...
}
Datastoreなどへの
書き込みが競合するので注意
Namespaceを使う
■ テストごとに名前空間を変える
● appengine.Namespace()を呼び出す
func Test1(t *testing.T) {
t.Parallel()
...
c, err = appengine.Namespace(c, "namespace1")
...
}
サービスでNamespaceを
使ってたら使えない手段
差分テスト
■ 増えていくテスト
● プロジェクト規模と共にテストも増える
● 1/3くらいがテスト
● テスト待ちでマージできない
■ 更新してない部分はテストしたくない
● そんなに更新した箇所は多くない
● gitでバージョン管理しているのに...
うまく差分だけ
テストできないの?
coverprofile
■ テストカバレッジの分析
$ go test -coverprofile=profile fmt
$ head profile
mode: set
fmt/format.go:30.13,31.29 1 1
fmt/format.go:31.29,34.3 2 1
fmt/format.go:67.28,69.2 1 1
fmt/format.go:71.33,74.2 2 1
fmt/format.go:77.85,80.11 3 1
fmt/format.go:84.2,85.11 2 1
fmt/format.go:96.2,96.8 1 1
fmt/format.go:80.11,83.3 2 0
fmt/format.go:85.11,86.21 1 1
パッケージ名
テストできるのは
パッケージごと
カバレッジの可視化
$ go tool cover -html=profile
参考:https://blog.golang.org/cover
coverprofileの中身
■ テストが依存しているファイルが分かる
mode: set
fmt/format.go:30.13,31.29 1 1
fmt/format.go:31.29,34.3 2 1
fmt/format.go:67.28,69.2 1 1
fmt/format.go:71.33,74.2 2 1
fmt/format.go:77.85,80.11 3 1
...
fmt/scan.go:1181.46,1183.4 1 1
fmt/scan.go:1185.29,1187.9 2 1
fmt/scan.go:1195.27,1197.3 1 1
テストで通った箇所
coverprofileで差分テストをする
■ coverprofileの生成
● すべてのパッケージのcoverprofileを生成する
● coverprofileはコミットしておく
■ テストが必要なパッケージを割り出す
● git diff --name-onlyでファイル一覧を取る
● coverprofile内にファイル名が出てるか?
● 出てたらそのパッケージはテスト対象
■ 差分テスト
● テスト対象のパッケージのみテスト
● テストの際にcoverprofileを生成
● coverprofileはコミットしておく
参考:http://qiita.com/tenntenn/items/caafa121b90fc7a53a8a
差分テストの問題点
■ パッケージごとにテストが走る
● パッケージが大きいと効果なし
● testeratorの効果が減る
■ なんとなく不安
● 漏れがないのか?
goappコマンドとgoコマンド
■ GAE/Goではgoappコマンドを使う
● goコマンドと何が違うのか?
● ソースコードレベルで比べてみた
if buildContext.InstallSuffix != "" {
buildContext.InstallSuffix += "_"
}
buildContext.InstallSuffix += "appengine"
buildContext.BuildTags =
append(buildContext.BuildTags, "appengine")
InstallSuffixと
BuildTagsくらいの差分
appengieタグ
■ goappを使うとappengineタグが付く
● Standard Environment 向けにはappengineタグ
● Flexible Environment 向けにはappengineタグなし
■ goコマンドでも同じか?
● -tags "appengine"でタグが付けれる
● GOPTHとGOROOTが違うの注意
● GOROOTにappengineパッケージがある
○ google.golang.org/appengineではない
ビルドタグを活用する
■ GAEに依存する部分のテスト
■ GAEに依存しない部分のテスト
//+build appengine
package mypkg_test
...
//+build !appengine
package mypkg_test
...
ビルドタグを活用する
■ GAEに依存する部分のテストの実行
■ GAEに依存しない部分のテストの実行
$ goapp test mypkg
$ go test mypkg
重めなGAEに依存するテストと
そうでない物は分ける!
差分テストとビルドタグ
■ GAEに依存する部分のテストの実行
■ GAEに依存しない部分のテストの実行
$ goapp test -coverprofile=profile_gae mypkg
coverprofileをコミットしておけば
更新頻度の低いパッケージのテストは走らない
$ go test -coverprofile=profile mypkg
デバッグはどうしてますか?
_人人人人人人人人_
> printデバッグ <
 ̄Y^Y^Y^Y^Y^Y^Y ̄
_人人人人人人人人人人人人_
> panic("oh my god") <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
Goで使えるデバッガ
■ GDB
● https://golang.org/doc/gdb
● おなじみのデバッガ
■ godebug
● https://github.com/mailgun/godebug
● コード生成する面白いデバッガ
■ delve
● https://github.com/derekparker/delve
● Go専用デバッガ
● IDEの対応状況がよい
GAEのローカルサーバでのデバッグ
■ GAE/Goのプロセスにattachする必要
● 複数のプロセスが起動する場合がある
○ --max_module_instances=1で起動
● プロセスが変わる
○ delveAppengineを使う
○ http://qiita.com/tenntenn/items/0b28f65de054df0
58a0e
GAEのローカルサーバでのデバッグ
delveのIDE・エディタの対応状況
参考
:https://github.com/derekparker/delve/blob/master/Document
ation/EditorIntegration.md
IntelliJ IDEAは
GAEに対応したプラグインがある
Vimではできないの!?
vim-goで対応されないっぽい
参考:https://github.com/fatih/vim-go/issues/233
nvim-goではdelveは対応済
参考:https://asciinema.org/a/92011
delveのconnectも対応して貰えそう
参考:https://twitter.com/_zchee_/status/794928877403455488
※attachではなくconnectでした
まとめ
■ テスト
● 重いテストは工夫しだいで軽くできる
○ インスタンスの使い回し
○ テストの並列化
○ 差分テスト
○ ビルドタグ
● 必要なテストは書きましょう
■ デバッグ
● delveでデバッグしよう
● Vimmerはnvim-goの対応を待ちましょう
Thank you!
twitter: @tenntenn
Qiita: tenntenn
connpass: tenntenn

More Related Content

What's hot

今日から始めるGopher - スタートGo #0 @GDG名古屋
今日から始めるGopher - スタートGo #0 @GDG名古屋今日から始めるGopher - スタートGo #0 @GDG名古屋
今日から始めるGopher - スタートGo #0 @GDG名古屋
Takuya Ueda
 
Goで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろうGoで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろう
Esehara Shigeo
 

What's hot (20)

Go入門
Go入門Go入門
Go入門
 
オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選オススメの標準・準標準パッケージ20選
オススメの標準・準標準パッケージ20選
 
今日から始めるGopher - スタートGo #0 @GDG名古屋
今日から始めるGopher - スタートGo #0 @GDG名古屋今日から始めるGopher - スタートGo #0 @GDG名古屋
今日から始めるGopher - スタートGo #0 @GDG名古屋
 
Go初心者向けハンズオン コマンドラインツールを作ろう
Go初心者向けハンズオン コマンドラインツールを作ろうGo初心者向けハンズオン コマンドラインツールを作ろう
Go初心者向けハンズオン コマンドラインツールを作ろう
 
今日から始める Go言語 と appengine
今日から始める Go言語 と appengine今日から始める Go言語 と appengine
今日から始める Go言語 と appengine
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化
 
GAE/Goとsyncパッケージ
GAE/GoとsyncパッケージGAE/Goとsyncパッケージ
GAE/Goとsyncパッケージ
 
実践Go ツールの作成から配布まで
実践Go ツールの作成から配布まで実践Go ツールの作成から配布まで
実践Go ツールの作成から配布まで
 
Go mobileでモバイルアプリを作ろう
Go mobileでモバイルアプリを作ろうGo mobileでモバイルアプリを作ろう
Go mobileでモバイルアプリを作ろう
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?
 
Goにおける静的解析と製品開発への応用
Goにおける静的解析と製品開発への応用Goにおける静的解析と製品開発への応用
Goにおける静的解析と製品開発への応用
 
goパッケージで型情報を用いたソースコード検索を実現する
goパッケージで型情報を用いたソースコード検索を実現するgoパッケージで型情報を用いたソースコード検索を実現する
goパッケージで型情報を用いたソースコード検索を実現する
 
GoによるiOSアプリの開発
GoによるiOSアプリの開発GoによるiOSアプリの開発
GoによるiOSアプリの開発
 
Goで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろうGoで言語処理系(の途中まで)を作ろう
Goで言語処理系(の途中まで)を作ろう
 
PyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッションPyCon JP 2016 ビギナーセッション
PyCon JP 2016 ビギナーセッション
 
Gopher Fest 2017参加レポート
Gopher Fest 2017参加レポートGopher Fest 2017参加レポート
Gopher Fest 2017参加レポート
 
Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発Go MobileでAndroidアプリ開発
Go MobileでAndroidアプリ開発
 
Cloud functionsの紹介
Cloud functionsの紹介Cloud functionsの紹介
Cloud functionsの紹介
 
GoでMinecraftっぽいの作る
GoでMinecraftっぽいの作るGoでMinecraftっぽいの作る
GoでMinecraftっぽいの作る
 
Goだけでモバイルアプリを作ろう
Goだけでモバイルアプリを作ろうGoだけでモバイルアプリを作ろう
Goだけでモバイルアプリを作ろう
 

Viewers also liked

Viewers also liked (20)

Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状についてClojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
 
Test Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるかTest Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるか
 
ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意
ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意
ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意
 
テストを書こう、Unity編
テストを書こう、Unity編テストを書こう、Unity編
テストを書こう、Unity編
 
React系(別言語含む)の サーバーサイドレンダリング について考えよう
React系(別言語含む)の サーバーサイドレンダリング について考えようReact系(別言語含む)の サーバーサイドレンダリング について考えよう
React系(別言語含む)の サーバーサイドレンダリング について考えよう
 
Operations: Production Readiness Review – How to stop bad things from Happening
Operations: Production Readiness Review – How to stop bad things from HappeningOperations: Production Readiness Review – How to stop bad things from Happening
Operations: Production Readiness Review – How to stop bad things from Happening
 
神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)神に近づくx/net/context (Finding God with x/net/context)
神に近づくx/net/context (Finding God with x/net/context)
 
What’s New in Amazon Aurora
What’s New in Amazon AuroraWhat’s New in Amazon Aurora
What’s New in Amazon Aurora
 
MongoDBの可能性の話
MongoDBの可能性の話MongoDBの可能性の話
MongoDBの可能性の話
 
SLOのすすめ
SLOのすすめSLOのすすめ
SLOのすすめ
 
Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介
Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介
Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介
 
An introduction and future of Ruby coverage library
An introduction and future of Ruby coverage libraryAn introduction and future of Ruby coverage library
An introduction and future of Ruby coverage library
 
AWS X-Rayによるアプリケーションの分析とデバッグ
AWS X-Rayによるアプリケーションの分析とデバッグAWS X-Rayによるアプリケーションの分析とデバッグ
AWS X-Rayによるアプリケーションの分析とデバッグ
 
AndApp開発における全て #denatechcon
AndApp開発における全て #denatechconAndApp開発における全て #denatechcon
AndApp開発における全て #denatechcon
 
Blockchain on Go
Blockchain on GoBlockchain on Go
Blockchain on Go
 
Apache Spark Streaming + Kafka 0.10 with Joan Viladrosariera
Apache Spark Streaming + Kafka 0.10 with Joan ViladrosarieraApache Spark Streaming + Kafka 0.10 with Joan Viladrosariera
Apache Spark Streaming + Kafka 0.10 with Joan Viladrosariera
 
golang.tokyo #6 (in Japanese)
golang.tokyo #6 (in Japanese)golang.tokyo #6 (in Japanese)
golang.tokyo #6 (in Japanese)
 
Streaming Data Analytics with Amazon Redshift and Kinesis Firehose
Streaming Data Analytics with Amazon Redshift and Kinesis FirehoseStreaming Data Analytics with Amazon Redshift and Kinesis Firehose
Streaming Data Analytics with Amazon Redshift and Kinesis Firehose
 
ScalaからGoへ
ScalaからGoへScalaからGoへ
ScalaからGoへ
 
Microservices at Mercari
Microservices at MercariMicroservices at Mercari
Microservices at Mercari
 

Similar to メルカリアッテの実務で使えた、GAE/Goの開発を効率的にする方法

Adtech College#7 GitHubを中心とした開発フロー
Adtech College#7 GitHubを中心とした開発フローAdtech College#7 GitHubを中心とした開発フロー
Adtech College#7 GitHubを中心とした開発フロー
Naoyuki Yamada
 
JJUG CCC 2011 Fall / Web test automation with Geb and Spock
JJUG CCC 2011 Fall / Web test automation with Geb and SpockJJUG CCC 2011 Fall / Web test automation with Geb and Spock
JJUG CCC 2011 Fall / Web test automation with Geb and Spock
Nobuhiro Sue
 
Maven2 プラグイン入門
Maven2 プラグイン入門Maven2 プラグイン入門
Maven2 プラグイン入門
guestd4898b
 
明日から使えるgradle
明日から使えるgradle明日から使えるgradle
明日から使えるgradle
kimukou_26 Kimukou
 

Similar to メルカリアッテの実務で使えた、GAE/Goの開発を効率的にする方法 (20)

Javaプログラマのための頑張らないGo入門
Javaプログラマのための頑張らないGo入門Javaプログラマのための頑張らないGo入門
Javaプログラマのための頑張らないGo入門
 
Adtech College#7 GitHubを中心とした開発フロー
Adtech College#7 GitHubを中心とした開発フローAdtech College#7 GitHubを中心とした開発フロー
Adtech College#7 GitHubを中心とした開発フロー
 
粗探しをしてGoのコントリビューターになる方法
粗探しをしてGoのコントリビューターになる方法粗探しをしてGoのコントリビューターになる方法
粗探しをしてGoのコントリビューターになる方法
 
Gopenflow demo v1
Gopenflow demo v1Gopenflow demo v1
Gopenflow demo v1
 
JJUG CCC 2011 Fall / Web test automation with Geb and Spock
JJUG CCC 2011 Fall / Web test automation with Geb and SpockJJUG CCC 2011 Fall / Web test automation with Geb and Spock
JJUG CCC 2011 Fall / Web test automation with Geb and Spock
 
20120421中国gtug
20120421中国gtug20120421中国gtug
20120421中国gtug
 
R Markdownによるドキュメント生成と バージョン管理入門
R Markdownによるドキュメント生成と バージョン管理入門R Markdownによるドキュメント生成と バージョン管理入門
R Markdownによるドキュメント生成と バージョン管理入門
 
TensorFlowを使ってテキストをクラス分類してみたら精度96.8%の分類器を簡単に得ることができた話
TensorFlowを使ってテキストをクラス分類してみたら精度96.8%の分類器を簡単に得ることができた話TensorFlowを使ってテキストをクラス分類してみたら精度96.8%の分類器を簡単に得ることができた話
TensorFlowを使ってテキストをクラス分類してみたら精度96.8%の分類器を簡単に得ることができた話
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホン
 
Tests and bugreports
Tests and bugreportsTests and bugreports
Tests and bugreports
 
Go Friday 傑作選
Go Friday 傑作選Go Friday 傑作選
Go Friday 傑作選
 
TensorFlowを使ってテキストをクラス分類してみた
TensorFlowを使ってテキストをクラス分類してみたTensorFlowを使ってテキストをクラス分類してみた
TensorFlowを使ってテキストをクラス分類してみた
 
Maven2 プラグイン入門
Maven2 プラグイン入門Maven2 プラグイン入門
Maven2 プラグイン入門
 
Gunosy_go_8_runtime
Gunosy_go_8_runtimeGunosy_go_8_runtime
Gunosy_go_8_runtime
 
Jjug 20140430 gradle_basic
Jjug 20140430 gradle_basicJjug 20140430 gradle_basic
Jjug 20140430 gradle_basic
 
Goでこれどうやるの? 入門
Goでこれどうやるの? 入門Goでこれどうやるの? 入門
Goでこれどうやるの? 入門
 
明日から使えるgradle
明日から使えるgradle明日から使えるgradle
明日から使えるgradle
 
Goはじめました
GoはじめましたGoはじめました
Goはじめました
 
RgGen ご紹介
RgGen ご紹介RgGen ご紹介
RgGen ご紹介
 
Programming camp Codereading
Programming camp CodereadingProgramming camp Codereading
Programming camp Codereading
 

More from Takuya Ueda

More from Takuya Ueda (14)

Goにおけるバージョン管理の必要性 − vgoについて −
Goにおけるバージョン管理の必要性 − vgoについて −Goにおけるバージョン管理の必要性 − vgoについて −
Goにおけるバージョン管理の必要性 − vgoについて −
 
WebAssembly with Go
WebAssembly with GoWebAssembly with Go
WebAssembly with Go
 
静的解析を使った開発ツールの開発
静的解析を使った開発ツールの開発静的解析を使った開発ツールの開発
静的解析を使った開発ツールの開発
 
そうだ、Goを始めよう
そうだ、Goを始めようそうだ、Goを始めよう
そうだ、Goを始めよう
 
マスター・オブ・goパッケージ
マスター・オブ・goパッケージマスター・オブ・goパッケージ
マスター・オブ・goパッケージ
 
メルカリ カウルのマスタデータの更新
メルカリ カウルのマスタデータの更新メルカリ カウルのマスタデータの更新
メルカリ カウルのマスタデータの更新
 
Static Analysis in Go
Static Analysis in GoStatic Analysis in Go
Static Analysis in Go
 
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
 
エキスパートGo
エキスパートGoエキスパートGo
エキスパートGo
 
Go静的解析ハンズオン
Go静的解析ハンズオンGo静的解析ハンズオン
Go静的解析ハンズオン
 
Google Assistant関係のセッションまとめ
Google Assistant関係のセッションまとめGoogle Assistant関係のセッションまとめ
Google Assistant関係のセッションまとめ
 
Cloud Functionsの紹介
Cloud Functionsの紹介Cloud Functionsの紹介
Cloud Functionsの紹介
 
Namespace API を用いたマルチテナント型 Web アプリの実践
Namespace API を用いたマルチテナント型 Web アプリの実践Namespace API を用いたマルチテナント型 Web アプリの実践
Namespace API を用いたマルチテナント型 Web アプリの実践
 
Mobile Apps by Pure Go with Reverse Binding
Mobile Apps by Pure Go with Reverse BindingMobile Apps by Pure Go with Reverse Binding
Mobile Apps by Pure Go with Reverse Binding
 

メルカリアッテの実務で使えた、GAE/Goの開発を効率的にする方法