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.
単体テストの
パフォーマンスチューニング
株式会社 ビジネスバンクグループ
竹中 翔
• 竹中 翔
• ビジネスバンクグループ CTO
• Twitter/GitHub @shoutakenaka
自己紹介
• 中小企業向けクラウドERPソフト
• 経営を支援する「ビジネス・コックピット」

→ 詳しくはこちらの動画にまとめられていますの
で、是非ご覧ください
• Ruby on Rails
• 2015年7月にファーストリリース
• 鋭意開発中
...
• 壮大なコンセプトのシステム
• 設計 → 開発 → リリース → 検証 → 改善 → …
• 自動テスト大事!
ALL-IN
はじめの一歩
そして今
• (テストコードレベルで)単体テストの全体の実行
時間を短くするために気を付けていること



テストの分散実行とかの話は今日はしません
本日のテーマ
Speed up tests
• rspec
• resque_spec
• factory_girl
• database_cleaner
• faker
主なテスト用gem
• 時間がかかるのは主に外部リソースアクセス(I/
O)。
• DB
• File
• Web API
• ALL-IN の場合、外部の Web API をあまり使ってい
ないので、I/O は DB アクセスがメイン。
スピードアップのポイント
• テストケース数が増えてくると、個々のテストの
ちょっとしたスローダウンが、全体で見ると大きな
影響に…
• 0.1 sec * 20000 = 2000 sec = 33 min
スピードアップのポイント
• プロダクションコードで非効率な I/O を発生させな
いのは当然大切!
• N+1 問題発生してない?
• includes とか eager_load を使う
• 大量のデータをメモリに展開していない?
• find_each、find_in...
• テストのセットアップも大切!
• 不要なテストデータを DB に入れてない?
• 同じようなデータをテストのたびに毎回DBに入れてな
い?
→ 適切なタイミングで、必要なデータを投入する!
スピードアップのポイント
不要なデータ問題
• FactoryGirlを使ってます
テストデータの準備
• テスト用のモデルインスタンス+DBへのデータ登
録が楽にできる
• デフォルト値でよければcreateするだけ
• テストケースに合わせて、柔軟に特定の属性だけ上書き
できる
• create_list(:customer, n) で n個...
でもちょっと待った
• モデルのインスタンスさえあれば、DBにデータが
入っていなくてもいいテストはある
• モデルのバリデーションのテスト
• モデル → JSON のレンダリングのテスト
• DBアクセスを伴わない計算ロジックのテスト
• etc
• これらの...
• DBへの登録は行わず、モデルのインスタンスだけを
作る

→ INSERTにかかるコストを削減できる!
build を使う
• 関連モデル(アソシエーション)はINSERTされて
しまう

→ この例だと customer_status はやっぱりDB登録
されてしまってる…
buildの罠
• アソシエーションにstrategyをつけるか、
build_stubbedでモデルを生成する
関連モデルをDBに入れない
• ブロックを渡すと、必要になったときにブロックの
中身を評価して属性値を作ってくれる

→ ALL-IN ではこの書き方
遅延評価でもOK
• 他の属性を使って属性値を定義することができる
遅延評価のいいところ
頻繁に登録されるデータ問題
• ALL-IN ではビジネスロジック定義用のクラスには
必ずログインユーザーを渡して、「ユーザーがアク
セスできる範囲のデータ」に対して処理をしている
例えばログインユーザー
• 何も考えずにこんなコードを書くと、各テストケー
スのセットアップで毎回 user をDBに登録する処理
が走ってしまってコストが高い
例えばログインユーザー
あらかじめDB登録してしまう
• create するときにオプションで渡せば、関連モデル
を作成するコストを削減できる
関連モデル作成コストの削減も
• use_transactional_fixturesでテストケースごとにト
ランザクションを効かせていても、このデータはテ
スト完了後もDBに残る
• 何がしかの対策が必要
• テスト起動時にDBをクリーンにするとか
• ユーザーIDを固定し...
テスト分けすぎ問題
• 昔ある人に言われたことがあります



「1テストメソッド1Assertionであるべきだ」



と。
テストの最小単位とは?
• 本当に1テスト1Assertにすべきか?
テストの最小単位とは?
• 本当に1テスト1Assertにすべきか?
テストの最小単位とは?
• 本当に1テスト1Assertにすべきか?

→ 意味的に同じことをテストしているのであれ
ば、そこまで原理主義的にテストを分割しなくてい
い



→ DBアクセスが発生するテストは、テストメソッ
ド数を減らすことでコストが下がる
テストの...
• ある処理をした時、DBに期待通りの数のデータが
登録されるか、というテスト。
こういうテストはどうする?
• and で繋げてまとめて確認

→ RegistrationService.setup の評価は一回だけ
こういうテストはどうする?
ということで
• 無駄なデータを作らない
• FactoryGirlを上手に使う
• 同じようなデータを登録しない
• テストスィートセットアップ時に登録してしまう
• まとめられるテストケースはまとめる
• 分割しすぎず意味ある単位で1つにまとめる
スピー...
で、全テスト回すのに
どのくらいかかるの?
どなたか m(_ _)m
Thank you !!
自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips
自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips
自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips
自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips
Upcoming SlideShare
Loading in …5
×

自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips

3,640 views

Published on

「Matzから、Rubyパフォーマンスのポイントを教えてもらおう!会議」でのプレゼン資料です。
ビジネスバンクグループで自社開発しているプロダクト「ALL-IN」の開発における、単体テストのパフォーマンスチューニングのTipsについて発表しました。

Published in: Technology
  • Dating direct: ♥♥♥ http://bit.ly/36cXjBY ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area is here: ❶❶❶ http://bit.ly/36cXjBY ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

自社開発プロダクト ALL-IN で行っている単体テストのパフォーマンスチューニングTips

  1. 1. 単体テストの パフォーマンスチューニング 株式会社 ビジネスバンクグループ 竹中 翔
  2. 2. • 竹中 翔 • ビジネスバンクグループ CTO • Twitter/GitHub @shoutakenaka 自己紹介
  3. 3. • 中小企業向けクラウドERPソフト • 経営を支援する「ビジネス・コックピット」
 → 詳しくはこちらの動画にまとめられていますの で、是非ご覧ください • Ruby on Rails • 2015年7月にファーストリリース • 鋭意開発中 ALL-IN
  4. 4. • 壮大なコンセプトのシステム • 設計 → 開発 → リリース → 検証 → 改善 → … • 自動テスト大事! ALL-IN
  5. 5. はじめの一歩
  6. 6. そして今
  7. 7. • (テストコードレベルで)単体テストの全体の実行 時間を短くするために気を付けていること
 
 テストの分散実行とかの話は今日はしません 本日のテーマ Speed up tests
  8. 8. • rspec • resque_spec • factory_girl • database_cleaner • faker 主なテスト用gem
  9. 9. • 時間がかかるのは主に外部リソースアクセス(I/ O)。 • DB • File • Web API • ALL-IN の場合、外部の Web API をあまり使ってい ないので、I/O は DB アクセスがメイン。 スピードアップのポイント
  10. 10. • テストケース数が増えてくると、個々のテストの ちょっとしたスローダウンが、全体で見ると大きな 影響に… • 0.1 sec * 20000 = 2000 sec = 33 min スピードアップのポイント
  11. 11. • プロダクションコードで非効率な I/O を発生させな いのは当然大切! • N+1 問題発生してない? • includes とか eager_load を使う • 大量のデータをメモリに展開していない? • find_each、find_in_batches を使う • kaminari gemとか offset、limit でページングする スピードアップのポイント
  12. 12. • テストのセットアップも大切! • 不要なテストデータを DB に入れてない? • 同じようなデータをテストのたびに毎回DBに入れてな い? → 適切なタイミングで、必要なデータを投入する! スピードアップのポイント
  13. 13. 不要なデータ問題
  14. 14. • FactoryGirlを使ってます テストデータの準備
  15. 15. • テスト用のモデルインスタンス+DBへのデータ登 録が楽にできる • デフォルト値でよければcreateするだけ • テストケースに合わせて、柔軟に特定の属性だけ上書き できる • create_list(:customer, n) で n個まとめてインスタンス生 成+DB登録できる FactoryGirlを使うと
  16. 16. でもちょっと待った
  17. 17. • モデルのインスタンスさえあれば、DBにデータが 入っていなくてもいいテストはある • モデルのバリデーションのテスト • モデル → JSON のレンダリングのテスト • DBアクセスを伴わない計算ロジックのテスト • etc • これらのテストケースまで create でインスタンス を作るのは無駄 DB登録は本当に必要?
  18. 18. • DBへの登録は行わず、モデルのインスタンスだけを 作る
 → INSERTにかかるコストを削減できる! build を使う
  19. 19. • 関連モデル(アソシエーション)はINSERTされて しまう
 → この例だと customer_status はやっぱりDB登録 されてしまってる… buildの罠
  20. 20. • アソシエーションにstrategyをつけるか、 build_stubbedでモデルを生成する 関連モデルをDBに入れない
  21. 21. • ブロックを渡すと、必要になったときにブロックの 中身を評価して属性値を作ってくれる
 → ALL-IN ではこの書き方 遅延評価でもOK
  22. 22. • 他の属性を使って属性値を定義することができる 遅延評価のいいところ
  23. 23. 頻繁に登録されるデータ問題
  24. 24. • ALL-IN ではビジネスロジック定義用のクラスには 必ずログインユーザーを渡して、「ユーザーがアク セスできる範囲のデータ」に対して処理をしている 例えばログインユーザー
  25. 25. • 何も考えずにこんなコードを書くと、各テストケー スのセットアップで毎回 user をDBに登録する処理 が走ってしまってコストが高い 例えばログインユーザー
  26. 26. あらかじめDB登録してしまう
  27. 27. • create するときにオプションで渡せば、関連モデル を作成するコストを削減できる 関連モデル作成コストの削減も
  28. 28. • use_transactional_fixturesでテストケースごとにト ランザクションを効かせていても、このデータはテ スト完了後もDBに残る • 何がしかの対策が必要 • テスト起動時にDBをクリーンにするとか • ユーザーIDを固定して、すでにあったら作らないとか • やりすぎ注意 • セットアップ時に色々登録すると、デフォルトで何が入っ てるのか分からなくなる デメリットもある
  29. 29. テスト分けすぎ問題
  30. 30. • 昔ある人に言われたことがあります
 
 「1テストメソッド1Assertionであるべきだ」
 
 と。 テストの最小単位とは?
  31. 31. • 本当に1テスト1Assertにすべきか? テストの最小単位とは?
  32. 32. • 本当に1テスト1Assertにすべきか? テストの最小単位とは?
  33. 33. • 本当に1テスト1Assertにすべきか?
 → 意味的に同じことをテストしているのであれ ば、そこまで原理主義的にテストを分割しなくてい い
 
 → DBアクセスが発生するテストは、テストメソッ ド数を減らすことでコストが下がる テストの最小単位とは?
  34. 34. • ある処理をした時、DBに期待通りの数のデータが 登録されるか、というテスト。 こういうテストはどうする?
  35. 35. • and で繋げてまとめて確認
 → RegistrationService.setup の評価は一回だけ こういうテストはどうする?
  36. 36. ということで
  37. 37. • 無駄なデータを作らない • FactoryGirlを上手に使う • 同じようなデータを登録しない • テストスィートセットアップ時に登録してしまう • まとめられるテストケースはまとめる • 分割しすぎず意味ある単位で1つにまとめる スピードアップの施策まとめ
  38. 38. で、全テスト回すのに どのくらいかかるの?
  39. 39. どなたか m(_ _)m
  40. 40. Thank you !!

×