Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

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

8.584 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

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

×