SlideShare a Scribd company logo
メルカリアッテの
実務で使えた、
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

PDF
GAE/GoでWebアプリ開発入門
PDF
Goのパッケージ構成で 試行錯誤してみた話 ~ Gocon 2015 Summer
PDF
Goでwebアプリを開発してみよう
PDF
GAE/GoでLINE Messaging API を使う
PDF
エディタの壁を越えるGoの開発ツールの文化と作成法
PDF
Goでかんたんソースコードの静的解析
PDF
Goとテスト
PDF
Go1.8 for Google App Engine
GAE/GoでWebアプリ開発入門
Goのパッケージ構成で 試行錯誤してみた話 ~ Gocon 2015 Summer
Goでwebアプリを開発してみよう
GAE/GoでLINE Messaging API を使う
エディタの壁を越えるGoの開発ツールの文化と作成法
Goでかんたんソースコードの静的解析
Goとテスト
Go1.8 for Google App Engine

What's hot (20)

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

Viewers also liked (20)

PDF
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
PDF
Test Yourself - テストを書くと何がどう変わるか
PDF
ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意
PDF
テストを書こう、Unity編
PDF
React系(別言語含む)の サーバーサイドレンダリング について考えよう
PDF
神に近づくx/net/context (Finding God with x/net/context)
PPTX
MongoDBの可能性の話
PDF
SLOのすすめ
PDF
Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介
PDF
An introduction and future of Ruby coverage library
PDF
AWS X-Rayによるアプリケーションの分析とデバッグ
PPTX
AndApp開発における全て #denatechcon
PDF
Blockchain on Go
PDF
Apache Spark Streaming + Kafka 0.10 with Joan Viladrosariera
PDF
golang.tokyo #6 (in Japanese)
PPTX
ScalaからGoへ
PDF
Microservices at Mercari
PDF
Swaggerでのapi開発よもやま話
PDF
Fast and Reliable Swift APIs with gRPC
PPTX
Solving anything in VCL
Clojure の各種React系ラッパーライブラリのサーバーサイドレンダリングの現状について
Test Yourself - テストを書くと何がどう変わるか
ゲームジャムに使える! いろんな素材サイトとライセンスに関するご注意
テストを書こう、Unity編
React系(別言語含む)の サーバーサイドレンダリング について考えよう
神に近づくx/net/context (Finding God with x/net/context)
MongoDBの可能性の話
SLOのすすめ
Spiderストレージエンジンの使い方と利用事例 他ストレージエンジンの紹介
An introduction and future of Ruby coverage library
AWS X-Rayによるアプリケーションの分析とデバッグ
AndApp開発における全て #denatechcon
Blockchain on Go
Apache Spark Streaming + Kafka 0.10 with Joan Viladrosariera
golang.tokyo #6 (in Japanese)
ScalaからGoへ
Microservices at Mercari
Swaggerでのapi開発よもやま話
Fast and Reliable Swift APIs with gRPC
Solving anything in VCL
Ad

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

PDF
JS開発におけるTDDと自動テストツール利用の勘所
PDF
エキスパートGo
PDF
Rocroにおけるgcp活用事例
PDF
Goにおけるバージョン管理の必要性 − vgoについて −
PDF
Go Friday 傑作選
PDF
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
PDF
静的解析を使った開発ツールの開発
PDF
Tokyor14 - R言語でユニットテスト
PDF
はこだてIKA 第4回勉強会 単体テスト
PDF
第4回勉強会 単体テストのすすめ
PDF
マイクロサービスにおけるテスト自動化 with Karate
PDF
GoによるWebアプリ開発のキホン
PPTX
Go guide for Java programmer
PDF
Goとtest coverage
PDF
JavaScript経験者のためのGo言語入門
PDF
ソフトウェアテスト入門
PDF
人生がときめくAPIテスト自動化 with Karate
PDF
書こう! 使おう! 単体テスト
PDF
超簡単!!なTestLinkの使い方
PDF
書こう! 使おう! 単体テスト
JS開発におけるTDDと自動テストツール利用の勘所
エキスパートGo
Rocroにおけるgcp活用事例
Goにおけるバージョン管理の必要性 − vgoについて −
Go Friday 傑作選
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
静的解析を使った開発ツールの開発
Tokyor14 - R言語でユニットテスト
はこだてIKA 第4回勉強会 単体テスト
第4回勉強会 単体テストのすすめ
マイクロサービスにおけるテスト自動化 with Karate
GoによるWebアプリ開発のキホン
Go guide for Java programmer
Goとtest coverage
JavaScript経験者のためのGo言語入門
ソフトウェアテスト入門
人生がときめくAPIテスト自動化 with Karate
書こう! 使おう! 単体テスト
超簡単!!なTestLinkの使い方
書こう! 使おう! 単体テスト

More from Takuya Ueda (11)

PDF
WebAssembly with Go
PDF
そうだ、Goを始めよう
PDF
マスター・オブ・goパッケージ
PDF
メルカリ カウルのマスタデータの更新
PDF
Static Analysis in Go
PDF
Go静的解析ハンズオン
PDF
Google Assistant関係のセッションまとめ
PDF
Cloud Functionsの紹介
PDF
Namespace API を用いたマルチテナント型 Web アプリの実践
PDF
Mobile Apps by Pure Go with Reverse Binding
PDF
粗探しをしてGoのコントリビューターになる方法
WebAssembly with Go
そうだ、Goを始めよう
マスター・オブ・goパッケージ
メルカリ カウルのマスタデータの更新
Static Analysis in Go
Go静的解析ハンズオン
Google Assistant関係のセッションまとめ
Cloud Functionsの紹介
Namespace API を用いたマルチテナント型 Web アプリの実践
Mobile Apps by Pure Go with Reverse Binding
粗探しをしてGoのコントリビューターになる方法

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