Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

7,495 views

Published on

appengine ja night #35の発表資料です。
http://gcpja.connpass.com/event/44024/

Published in: Technology
  • Be the first to comment

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

  1. 1. メルカリアッテの 実務で使えた、 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.
  2. 2. アジェンダ ● 自己紹介 ● GAE/Goのテストを効率化する ○ インスタンスを使いまわす ○ テストの並列化 ○ 差分テスト ○ ビルドタグとテスト ● GAE/Goのデバッグ ○ Goとデバッガ ○ ローカルサーバでデバッグ
  3. 3. 自己紹介 メルカリ/ソウゾウ 上田拓也 twitter: @tenntenn ■ Go歴 / GAE歴 Go:5〜6年くらい? GAE:最近再開、GCPUG Tokyoのスタッフ ■ 業務 GAE/Goでメルカリアッテを作ってます Goのコミュニティを盛り上げる仕事 Gopherを描く仕事
  4. 4. 引用元:https://cloud.google.com/about/locations/japan/ 東京 GCP リージョン!
  5. 5. アッテ開発の技術 : Golang と Google App Engine
  6. 6. テスト書いてますか?
  7. 7. 画像:http://www.slideshare.net/t_wada/jasst-2014-hokkaidotwadatdd#4
  8. 8. Goはテスト書きやすい ■ コンパイルする強み ● 多くのバグがコンパイルで検出できる ● 型や引数のテストは必要なし ● 重要な部分のテストに集中できる ■ インタフェースを使ってテスト ● io.Writerとio.Reader ● テストしやすい設計がやりやすい ■ 標準ツールでテストができる ● フレームワークを覚える必要なし ● Goが読めればテストが読める 参考:Goとテスト
  9. 9. じゃあ、なぜテスト書かないのか?
  10. 10. テストを書かなくなる理由 ■ テストが重い ● aetestが重い ● テストするパッケージが大量にある ■ やっぱりifをたくさん書くのは大変 ● フレームワーク使いたい ■ テストする時間がない ● 実装だけで精一杯
  11. 11. aetestとは? ■ 何ができるのか? ● http.Requestが生成できる ● context.Contextが生成できる ● テストからDatastoreなどを使える ■ どうやってるのか? ● ローカルサーバを起動 ○ dev_appserver.pyを使用 ■ ドキュメント ● Local Unit Testing for Go ● The aetest package
  12. 12. 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へ アクセスしている
  13. 13. aetestが遅い理由 ■ ローカルサーバの立ち上げが遅い ● NewInstanceの度に立ち上がる ● テストの数が増えればその分増える func Test1(t *testing.T) { ctx, done, err := aetest.NewContext() ... } func Test2(t *testing.T) { ctx, done, err := aetest.NewContext() ... } この度に サーバが立ちあがる!
  14. 14. favclip/testerator ■ テスト間でインスタンスを使いまわせる ● https://github.com/favclip/testerator testerator.SpinUp() testerator.SpinUp() testerator.SpinUp() testerator.SpinDown() testerator.SpinDown() testerator.SpinDown() 起動 影響なし Datastore, Memcache, Search APIを初期化 終了
  15. 15. テストの並列化 ■ テストを並列化する ● t.Parallelを呼び出す func Test1(t *testing.T) { t.Parallel() ... } Datastoreなどへの 書き込みが競合するので注意
  16. 16. Namespaceを使う ■ テストごとに名前空間を変える ● appengine.Namespace()を呼び出す func Test1(t *testing.T) { t.Parallel() ... c, err = appengine.Namespace(c, "namespace1") ... } サービスでNamespaceを 使ってたら使えない手段
  17. 17. 差分テスト ■ 増えていくテスト ● プロジェクト規模と共にテストも増える ● 1/3くらいがテスト ● テスト待ちでマージできない ■ 更新してない部分はテストしたくない ● そんなに更新した箇所は多くない ● gitでバージョン管理しているのに... うまく差分だけ テストできないの?
  18. 18. 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 パッケージ名 テストできるのは パッケージごと
  19. 19. カバレッジの可視化 $ go tool cover -html=profile 参考:https://blog.golang.org/cover
  20. 20. 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 テストで通った箇所
  21. 21. coverprofileで差分テストをする ■ coverprofileの生成 ● すべてのパッケージのcoverprofileを生成する ● coverprofileはコミットしておく ■ テストが必要なパッケージを割り出す ● git diff --name-onlyでファイル一覧を取る ● coverprofile内にファイル名が出てるか? ● 出てたらそのパッケージはテスト対象 ■ 差分テスト ● テスト対象のパッケージのみテスト ● テストの際にcoverprofileを生成 ● coverprofileはコミットしておく 参考:http://qiita.com/tenntenn/items/caafa121b90fc7a53a8a
  22. 22. 差分テストの問題点 ■ パッケージごとにテストが走る ● パッケージが大きいと効果なし ● testeratorの効果が減る ■ なんとなく不安 ● 漏れがないのか?
  23. 23. goappコマンドとgoコマンド ■ GAE/Goではgoappコマンドを使う ● goコマンドと何が違うのか? ● ソースコードレベルで比べてみた if buildContext.InstallSuffix != "" { buildContext.InstallSuffix += "_" } buildContext.InstallSuffix += "appengine" buildContext.BuildTags = append(buildContext.BuildTags, "appengine") InstallSuffixと BuildTagsくらいの差分
  24. 24. appengieタグ ■ goappを使うとappengineタグが付く ● Standard Environment 向けにはappengineタグ ● Flexible Environment 向けにはappengineタグなし ■ goコマンドでも同じか? ● -tags "appengine"でタグが付けれる ● GOPTHとGOROOTが違うの注意 ● GOROOTにappengineパッケージがある ○ google.golang.org/appengineではない
  25. 25. ビルドタグを活用する ■ GAEに依存する部分のテスト ■ GAEに依存しない部分のテスト //+build appengine package mypkg_test ... //+build !appengine package mypkg_test ...
  26. 26. ビルドタグを活用する ■ GAEに依存する部分のテストの実行 ■ GAEに依存しない部分のテストの実行 $ goapp test mypkg $ go test mypkg 重めなGAEに依存するテストと そうでない物は分ける!
  27. 27. 差分テストとビルドタグ ■ GAEに依存する部分のテストの実行 ■ GAEに依存しない部分のテストの実行 $ goapp test -coverprofile=profile_gae mypkg coverprofileをコミットしておけば 更新頻度の低いパッケージのテストは走らない $ go test -coverprofile=profile mypkg
  28. 28. デバッグはどうしてますか?
  29. 29. _人人人人人人人人_ > printデバッグ <  ̄Y^Y^Y^Y^Y^Y^Y ̄
  30. 30. _人人人人人人人人人人人人_ > panic("oh my god") <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
  31. 31. Goで使えるデバッガ ■ GDB ● https://golang.org/doc/gdb ● おなじみのデバッガ ■ godebug ● https://github.com/mailgun/godebug ● コード生成する面白いデバッガ ■ delve ● https://github.com/derekparker/delve ● Go専用デバッガ ● IDEの対応状況がよい
  32. 32. GAEのローカルサーバでのデバッグ ■ GAE/Goのプロセスにattachする必要 ● 複数のプロセスが起動する場合がある ○ --max_module_instances=1で起動 ● プロセスが変わる ○ delveAppengineを使う ○ http://qiita.com/tenntenn/items/0b28f65de054df0 58a0e
  33. 33. GAEのローカルサーバでのデバッグ
  34. 34. delveのIDE・エディタの対応状況 参考 :https://github.com/derekparker/delve/blob/master/Document ation/EditorIntegration.md IntelliJ IDEAは GAEに対応したプラグインがある
  35. 35. Vimではできないの!?
  36. 36. vim-goで対応されないっぽい 参考:https://github.com/fatih/vim-go/issues/233
  37. 37. nvim-goではdelveは対応済 参考:https://asciinema.org/a/92011
  38. 38. delveのconnectも対応して貰えそう 参考:https://twitter.com/_zchee_/status/794928877403455488 ※attachではなくconnectでした
  39. 39. まとめ ■ テスト ● 重いテストは工夫しだいで軽くできる ○ インスタンスの使い回し ○ テストの並列化 ○ 差分テスト ○ ビルドタグ ● 必要なテストは書きましょう ■ デバッグ ● delveでデバッグしよう ● Vimmerはnvim-goの対応を待ちましょう
  40. 40. Thank you! twitter: @tenntenn Qiita: tenntenn connpass: tenntenn

×