Slide 1

Slide 1 text

©MIXI 2024/04/17 Vantageスタジオ みてね事業部 プロダクト開発グループ プロダクト開発Mグループ ⼤倉真⼀希 2024 テスト‧設計研修

Slide 2

Slide 2 text

22 ©MIXI ⾃⼰紹介 ● ⼤倉 真⼀希 (@maiki.okura) ● 22新卒 ● みてね事業部 プロダクト開発Mグループ ○ 物理商品を扱うチーム ○ server が多めでたまに iOS, Android など ● 好きなもの ○ フライドポテト ○ 背脂ラーメン ● 好きな分野 ○ 成果‧⽣産性向上

Slide 3

Slide 3 text

33 ©MIXI ⾃⼰紹介 ● 加藤 修悟 (@shugo.kato) a.k.a. ろぐみ ● 21新卒 ● Vantage スタジオ Romi 事業部 開発グループ ○ サーバ/フロント/インフラ ○ なんでもやさん ● 好きなもの ○ キーボードづくり ○ チャーシューづくり ● 好きな分野 ○ 爆速化

Slide 4

Slide 4 text

44 ©MIXI 本⽇の流れ 1. 講義 2. 演習1 (ペアプログラミング) ○ 実装 ○ 各チーム同⼠でコードレビュー & 修正 3. 演習2、 3 … お昼は13:00頃〜を予定

Slide 5

Slide 5 text

©MIXI 講義

Slide 6

Slide 6 text

66 ©MIXI 本⽇の流れ ● テスト‧ソフトウェアテストとは ○ ソフトウェアの品質の話 ○ TDDの話 ○ テスタビリティの話 ○ テスト技法の話 ○ テストの7原則 ● ペアプログラミング ● コードレビューの仕⽅とされ⽅

Slide 7

Slide 7 text

©MIXI みなさん、テスト書いてますか?

Slide 8

Slide 8 text

©MIXI テストと聞いて、 どのようなことを思い浮かべますか?

Slide 9

Slide 9 text

99 ©MIXI テスト‧ソフトウェアテストとは テスト != デバッグ テスト:不具合があることを⽰すことができるだけ デバッグ:不具合を取り除くまでの⼀連の開発活動のこと

Slide 10

Slide 10 text

10 10 ©MIXI テスト‧ソフトウェアテストとは ソフトウェアテストは ソフトウェアが想定通りの動作をしているか評価‧検証し 運⽤時の不具合を低減するための 1 つの⼿段です

Slide 11

Slide 11 text

©MIXI ソフトウェアの品質の話

Slide 12

Slide 12 text

12 12 ©MIXI ソフトウェアの品質 ソフトウェア品質特性 ● 外部品質特性 ○ システムの利⽤者が触れる、⾒える部分の品質 ● 内部品質特性 ○ システムの利⽤者からは⾒えない内側の部分の品質

Slide 13

Slide 13 text

13 13 ©MIXI ソフトウェアの品質 引⽤: 『つながる世界のソフトウェア品質ガイド あたらしい価値提供のための品質モデル活⽤のすすめ 』    P30 図2.3-3 (https://www.ipa.go.jp/publish/qv6pgp0000000wkj-att/000055008.pdf)

Slide 14

Slide 14 text

©MIXI テスト駆動開発(TDD)

Slide 15

Slide 15 text

15 15 ©MIXI テスト駆動開発(Test-Driven Development / TDD)とは? TDDとは、プログラミングのワークフローの⼀つ 以下のステップで開発を⾏う 1. テストリストを作成する a. 挙動の要件を書き出す 2. テストを書く (Red) a. 実装はないのでもちろんテストは落ちる 3. テストを通すために、実装をする (Green) a. まずはテストを通すことを考えてみる 4. リファクタリングする (Refactor) 5. テストリストが完了するまで2〜4を繰り返す Red Green Refactor 参考:Kent Beck 著 / 和田卓人 訳, テスト駆動開発, https://shop.ohmsha.co.jp/shopdetail/000000004967/ 和田卓人, 【翻訳】テスト駆動開発の定義, https://t-wada.hatenablog.jp/entry/canon-tdd-by-kent-beck

Slide 16

Slide 16 text

16 16 ©MIXI TDD に関するありがちな勘違い Q. テストコードを書くこと⾃体がTDD? A. それは⾃動テストです!   ⾃動テストがあるだけでもとても⽣産性が上がりますが TDD とは別です。 Q. テストを先に書いていればTDD? A. それはテストファーストです!   全テストを先に書くと仕様が把握できるなどのメリットがあります。   ⼀⽅で後戻りのリスクが上がったりします。

Slide 17

Slide 17 text

17 17 ©MIXI TDDの実例|動物の鳴き声を返す関数を実装する 以下のお題で実装をするとします。 呼び出すと⽝の鳴き声を返す関数を実装してください 別の動物(⽜、猫)を指定したらその動物の鳴き声を返して欲しいです 複数の動物を渡したら鳴き声を連結させて返してください

Slide 18

Slide 18 text

18 18 ©MIXI TDDの実例|テストリストの作成 先程のリストから実現すべき挙動を列挙します。 ❏ 引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す ❏ 引数で猫(cat)を渡した時に、猫の鳴き声 ʻmeow!’を返す ❏ 引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す ❏ 複数の動物を渡した時、鳴き声を連結して返す

Slide 19

Slide 19 text

19 19 ©MIXI TDDの実例|1つめの要件のテストを実装 まずは以下のテストを実装 ❏ 引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す import pytest from app.bark import bark def test_bark(): assert bark() == 'bowwow!'

Slide 20

Slide 20 text

20 20 ©MIXI TDDの実例|1つめの要件のテストを実装 メソッドの本体がないのでテストが落ちる!! ImportError while importing test module '/app/tests/app/test_bark.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: ... from app.bark import bark E ImportError: cannot import name 'bark' from 'app.bark' (/app/app/bark.py)

Slide 21

Slide 21 text

21 21 ©MIXI TDDの実例|1件⽬のテストに対するメソッドを実装する テストが通る最低限のメソッドを実装 ❏ 引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す def bark() -> str: return 'bowwow!'

Slide 22

Slide 22 text

22 22 ©MIXI TDDの実例|1件⽬のテストが通る テストが通ったので1つ⽬完了!   引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す tests/app/test_bark.py . [100%] ===================================== 1 passed in 0.03s ====================================

Slide 23

Slide 23 text

23 23 ©MIXI TDDの実例|2つめの要件のテストを実装 以下のテスト assert を追加 ❏ 引数で猫(cat)を渡した時に、猫の鳴き声 ʻmeow!’を返す import pytest from app.bark import bark def test_bark(): assert bark() == 'bowwow!' assert bark('cat') == 'meow!' # 追加

Slide 24

Slide 24 text

24 24 ©MIXI TDDの実例|2つめの要件のテストのテストを実⾏ 元々のメソッドは引数を取っていないのでテストが落ちる E TypeError: bark() takes 0 positional arguments but 1 was given tests/app/test_bark.py:6: TypeError ============================= short test summary info ======================================== FAILED tests/app/test_bark.py::test_bark - TypeError: bark() takes 0 positional arguments but 1 was given ============================== 1 failed in 0.05s =============================================

Slide 25

Slide 25 text

25 25 ©MIXI TDDの実例|2つめの要件のメソッドを実装 テストが通るよう、引数とそれによる分岐を追加 def bark(name: str = 'dog') -> str: if name == 'cat': return 'meow!' return 'bowwow!'

Slide 26

Slide 26 text

26 26 ©MIXI TDDの実例|2つめの要件のテストが通る 2つ⽬のタスクも完了!   引数で猫(cat)を渡した時に、猫の鳴き声 ʻmeow!’を返す tests/app/test_bark.py . [100%] =========================== 1 passed in 0.06s ================================

Slide 27

Slide 27 text

27 27 ©MIXI TDDの実例|3つめの要件のメソッドを実装 同じ形で実装し、3つ⽬の要件も完了! ❏ 引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す import pytest from app.bark import bark def test_bark(): assert bark() == 'bowwow!' assert bark('cat') == 'meow!' assert bark('cow') == 'mow!' # 追加

Slide 28

Slide 28 text

28 28 ©MIXI TDDの実例|3つめの要件のメソッドを実装 同じ形で実装し、3つ⽬の要件も完了!   引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す def bark(name: str = 'dog') -> str: if name == 'cat': return 'meow!' elif name == 'cow': return 'mow!' return 'bowwow!'

Slide 29

Slide 29 text

29 29 ©MIXI TDDの実例|リファクタ出来そうな箇所を発⾒   引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す def bark(name: str = 'dog') -> str: if name == 'cat': return 'meow!' elif name == 'cow': return 'mow!' return 'bowwow!' 動物が増えたらifが連なって大変 もっと見通しがよく出来そう?

Slide 30

Slide 30 text

30 30 ©MIXI TDDの実例|鳴き声の持ち⽅をリファクタする 動物の名前と鳴き声を if で管理するのは微妙なので、辞書で管理するようにする テストがあるので、安全にリファクタできる! ANIMAL_SOUNDS = { 'dog': 'bowwow!', 'cat': 'meow!', 'cow': 'mow!', } def bark(name: str = 'dog') -> str: return ANIMAL_SOUNDS[name]

Slide 31

Slide 31 text

31 31 ©MIXI TDDの実例|鳴き声の持ち⽅をリファクタする 動物の名前と鳴き声を if で管理するのは微妙なので、辞書で管理するようにする テストがあるので、安全にリファクタできる! ANIMAL_SOUNDS = { 'dog': 'bowwow!', 'cat': 'meow!', 'cow': 'mow!', } def bark(name: str = 'dog') -> str: return ANIMAL_SOUNDS[name] 知らない動物が来た時の対応も必要で は?

Slide 32

Slide 32 text

32 32 ©MIXI TDDの実例|テストリストに例外時の挙動を追加 引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す 引数で猫(cat)を渡した時に、猫の鳴き声 ʻmeow!’を返す 引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す ❏ 複数の動物を渡した時、鳴き声を連結して返す ❏ 知らない動物が渡された時はエラーを返す New!

Slide 33

Slide 33 text

©MIXI 同じ流れで 1. テストを書く (Red) 2. テストを通すために、実装をする (Green) 3. 必要に応じてリファクタリングする (Refactor) をテストリストが全て完了するまで繰り返すと...

Slide 34

Slide 34 text

34 34 ©MIXI TDDの実例|テストリストが完了し、⽬的を達成 ANIMAL_SOUNDS = { 'dog': 'bowwow!', 'cat': 'meow!', 'cow': 'mow!', } class ArgumentError(Exception): pass def bark(names: str = ['dog']) -> str: for name in names: if name not in ANIMAL_SOUNDS: raise ArgumentError('Invalid animal name') return ''.join([ANIMAL_SOUNDS[name] for name in names]) import pytest from app.bark import bark, ArgumentError def test_bark(): assert bark() == 'bowwow!' assert bark(['cat']) == 'meow!' assert bark(['cow']) == 'mow!' assert bark(['cow', 'cat']) == 'mow!meow!' with pytest.raises(ArgumentError) as e: bark('pig') assert str(e.value) == 'Invalid animal name' 本実装 テスト

Slide 35

Slide 35 text

35 35 ©MIXI TDDの実例|テストリストが完了し、⽬的を達成 引数なしで呼び出した時に、⽝の鳴き声 ʻbowwow!’を返す 引数で猫(cat)を渡した時に、猫の鳴き声 ʻmeow!’を返す 引数で⽜(cow)を渡した時に、⽜の鳴き声 ʻmow!’を返す 複数の動物を渡した時、鳴き声を連結して返す 知らない動物が渡された時はエラーを返す

Slide 36

Slide 36 text

36 36 ©MIXI TDDの注意点 ● 最初はリストのうちの1つを満たすテストからはじめる ○ 全部のテストを書くと、通すのにも、再設計にも時間がかかる。 ● テストを通すとき(Greenステップ)にリファクタリングはしない ○ 設計に関する判断はリファクタリングのステップで。⽬の前に集中。 ● ⼀度に必要以上のリファクタリングをしない ○ フローを回す速度が遅くなってしまう。

Slide 37

Slide 37 text

37 37 ©MIXI TDDのメリット TDDは⽬の前の⼩さいステップに取り組んで⾏くので 開発に対する不安をコントロールしやすい その時々に必要となる設計に向き合えるため、早すぎる抽象化が起きづらい 最初に全体を考えて実装‧設計などをするのは不確実性が⼤きい...

Slide 38

Slide 38 text

©MIXI テスト容易性 (テスタビリティ, Testability)

Slide 39

Slide 39 text

39 39 ©MIXI テストが書きづらい... def get_active_user_x_acounts (): from_time = datetime.now() - timedelta(days=3) # アクティブなユーザーを取ってくる処理 users = query(User).filter(user.updated_at > from_time).all() active_users = [] for user in users: # user が active かどうかのスコアを得る複雑な処理 active_score = # ... # 設定値を元にアクティブユーザーかどうかを判定 if active_score > Config.ACTIVE_USER_THRESHOLD: active_users.append(user) # ユーザーの X アカウント情報を取ってくる処理 result = [] for user in active_users: # 外部サイトへのリクエストをして X アカウント情報を取得 user_x_account = request( 'GET', 'https://x.com/users/~~~' ) result.append(user_x_account) return result

Slide 40

Slide 40 text

40 40 ©MIXI テストが書きづらい... def get_active_user_x_acounts (): from_time = datetime.now() - timedelta(days=3) # アクティブなユーザーを取ってくる処理 users = query(User).filter(user.updated_at > from_time).all() active_users = [] for user in users: # user が active かどうかのスコアを得る複雑な処理 active_score = # ... # 設定値を元にアクティブユーザーかどうかを判定 if active_score > Config.ACTIVE_USER_THRESHOLD: active_users.append(user) # ユーザーの X アカウント情報を取ってくる処理 result = [] for user in active_users: # 外部サイトへのリクエストをして X アカウント情報を取得 user_x_account = request( 'GET', 'https://x.com/users/~~~' ) result.append(user_x_account) return result 現在時刻、DBのレコードに依存 複雑なロジック 関数外の設定で挙動が変わる 外部リクエストに依存 テストパターン多くて重い、見づらい

Slide 41

Slide 41 text

41 41 ©MIXI テストを書きやすくするには?|テスタビリティを構成する特性 ● 実⾏円滑性(Operability) ○ テスト実⾏の際の⽀障のなさ。実⾏速度、バグの総数など。 ● 観測容易性(Observability) ○ テスト対象の出⼒、エラー、内部状態を確認しやすいか? ● 制御容易性(Controllability) ○ テスト対象はテストを⾏うための操作がしやすいか?(テスト⽤に内部の挙動を操作できるか?) ● 分解容易性(Decomposability) ○ 実⾏するテストの範囲を分離しやすいか?(依存をモックしたりして対象範囲のみテスト可能か?) ● 単純性(Simplicity) ○ テスト対象のコードや仕様はシンプルか? ● 安定性(Stability) ○ テスト対象はテスト負担を増やすような変更が少ないか?(仕様変更やそれによる影響が少ないか) ● 理解容易性(Understandability) ○ テストを⾏うための情報を得やすいか?(仕様書があるかなど)

Slide 42

Slide 42 text

42 42 ©MIXI テスタビリティの特性の観点で⾒てみる def get_active_user_x_acounts (): from_time = datetime.now() - timedelta(days=3) # アクティブなユーザーを取ってくる処理 users = query(User).filter(user.updated_at > from_time).all() active_users = [] for user in users: # user が active かどうかのスコアを得る複雑な処理 active_score = # ... # 設定値を元にアクティブユーザーかどうかを判定 if active_score > Config.ACTIVE_USER_THRESHOLD: active_users.append(user) # ユーザーの X アカウント情報を取ってくる処理 result = [] for user in active_users: # 外部サイトへのリクエストをして X アカウント情報を取得 user_x_account = request( 'GET', 'https://x.com/users/~~~' ) result.append(user_x_account) return result 現在時刻、DBのレコードに依存 → 内部挙動を制御しづらい (制御容易性が低い)

Slide 43

Slide 43 text

43 43 ©MIXI テスタビリティの特性の観点で⾒てみる def get_active_user_x_acounts (): from_time = datetime.now() - timedelta(days=3) # アクティブなユーザーを取ってくる処理 users = query(User).filter(user.updated_at > from_time).all() active_users = [] for user in users: # user が active かどうかのスコアを得る複雑な処理 active_score = # ... # 設定値を元にアクティブユーザーかどうかを判定 if active_score > Config.ACTIVE_USER_THRESHOLD: active_users.append(user) # ユーザーの X アカウント情報を取ってくる処理 result = [] for user in active_users: # 外部サイトへのリクエストをして X アカウント情報を取得 user_x_account = request( 'GET', 'https://x.com/users/~~~' ) result.append(user_x_account) return result 複雑なロジック → 仕様が難しい&変更があるとテストも 大幅に変わる... 処理ベタ書きでモックもできない... (分解容易性、単純性、安定性が低い)

Slide 44

Slide 44 text

44 44 ©MIXI テスタビリティが上がるようにリファクタしてみる def get_active_user_x_acounts (from_time): # アクティブなユーザーを取ってくる処理 users = get_users_recently_updated(from_time) active_users = select_active_users(users, Config.ACTIVE_USER_THRESHOLD) result = [] for user in active_users: user_x_account = get_user_x_acounts(user) result.append(user_x_account) return result def get_users_recently_updated (from_time): return query(User).filter(user.updated_at > from_time).all() def select_active_users (users, active_score_threshold ): return list(filter(None, [user for user in users if calc_active_score(user) > active_score_threshold else None])) def calc_active_score (user): # user が active かどうかのスコアを得る複雑な処理 return active_score def get_user_x_account (user): # 外部サイトへのリクエストをして X アカウント情報を取得 return request('GET', f'https://x.com/users/~~~' )

Slide 45

Slide 45 text

45 45 ©MIXI テスタビリティが上がるようにリファクタしてみる def get_active_user_x_acounts (from_time): # アクティブなユーザーを取ってくる処理 users = get_users_recently_updated(from_time) active_users = select_active_users(users, Config.ACTIVE_USER_THRESHOLD) result = [] for user in active_users: user_x_account = get_user_x_acounts(user) result.append(user_x_account) return result def get_users_recently_updated (from_time): return query(User).filter(user.updated_at > from_time).all() def select_active_users (users, active_score_threshold ): return list(filter(None, [user for user in users if calc_active_score(user) > active_score_threshold else None])) def calc_active_score (user): # user が active かどうかのスコアを得る複雑な処理 return active_score def get_user_x_account (user): # 外部サイトへのリクエストをして X アカウント情報を取得 return request('GET', f'https://x.com/users/~~~' ) 現在時刻を外部から指定できる! = 制御容易性 DBから取得する処理をモックしやすい! = 分解容易性

Slide 46

Slide 46 text

46 46 ©MIXI テスタビリティが上がるようにリファクタしてみる def get_active_user_x_acounts (from_time): # アクティブなユーザーを取ってくる処理 users = get_users_recently_updated(from_time) active_users = select_active_users(users, Config.ACTIVE_USER_THRESHOLD) result = [] for user in active_users: user_x_account = get_user_x_acounts(user) result.append(user_x_account) return result def get_users_recently_updated (from_time): return query(User).filter(user.updated_at > from_time).all() def select_active_users (users, active_score_threshold ): return list(filter(None, [user for user in users if calc_active_score(user) > active_score_threshold else None])) def calc_active_score (user): # user が active かどうかのスコアを得る複雑な処理 return active_score def get_user_x_account (user): # 外部サイトへのリクエストをして X アカウント情報を取得 return request('GET', f'https://x.com/users/~~~' ) 仕様が複雑な部分を個別テストできる! 本体のメソッドへの影響が減った! = 分解容易性, 単純性, 安定性

Slide 47

Slide 47 text

©MIXI テスト技法の話

Slide 48

Slide 48 text

©MIXI Q. どんなテストケースを設計するのが良いのか?

Slide 49

Slide 49 text

©MIXI A. ʻ最⼩の時間と労⼒でほとんどのエラーを 検出する可能性が最も⾼くなるように、 テストケースを設計しなければならない’ リー・コープランド 著 / 宗雅彦 訳, はじめて学ぶソフトウェアのテスト技法, https://bookplus.nikkei.com/atcl/catalog/05/P82510/

Slide 50

Slide 50 text

50 50 ©MIXI テスト技法 ● テストのレベル ○ 単体テスト (Unit testing) ■ もっとも⼩さなテスト ■ クラス、メソッド単位 (⾔語‧テストライブラリ等で異なる) ○ 統合テスト (Integration testing) ■ 単体テストよりも⼤きな範囲のテスト ○ システムテスト (System testing) ■ ソフトウェア全体のテスト ○ 受け⼊れテスト (User Acceptance Testing) ■ 顧客がソフトウェアを受け⼊れる時のテスト

Slide 51

Slide 51 text

51 51 ©MIXI テスト技法 ● テストの種別 ○ ブラックボックステスト ■ 仕様や要件に基づいてテストを実施するテスト ■ 実装レベルの知識は必要としない ○ ホワイトボックステスト ■ 実装レベルの知識に基づいて実施するテスト ■ ソフトウェアの内部パス、構造、実装 ... ○ グレーボックステスト ■ 実装をある程度調べた上で、ブラックボックステストのテストケースを効 率的に選択していく

Slide 52

Slide 52 text

52 52 ©MIXI テスト技法 ● ブラックボックステスト ○ 同値クラステスト ○ 境界値テスト ○ デシジョンテーブルテスト ○ ペア構成テスト ○ …. ● ホワイトボックステスト ○ 制御フローテスト ○ データフローテスト

Slide 53

Slide 53 text

53 53 ©MIXI テスト技法 同値クラステスト ○ 同値クラスに分け、代表値を選んでテストケースを作る ○ 例 ■ ⼊⼒値は0~100 ■ 0~19は未成年、20~100は成⼈ と返すプログラムを考える

Slide 54

Slide 54 text

54 54 ©MIXI テスト技法 境界値テスト ● 同値クラステストを元に、境界値に注⽬したテスト ● パーティションの最⼩値と最⼤値、または最初の値と最後の値を選んでテストする ● -1, 0, 19, 20, 100, 101

Slide 55

Slide 55 text

55 55 ©MIXI テストの7原則 1. テストは⽋陥があることは⽰せるが、⽋陥がないことは⽰せない 2. 全数テストは不可能 3. 早期テストで時間とコストを節約 4. ⽋陥の偏在 5. 殺⾍剤のパラドックスにご⽤⼼ 6. テストは状況次第 7. 「バグゼロ」の落とし⽳

Slide 56

Slide 56 text

56 56 ©MIXI その他テストに関するTIPS ● テストを書くのは⼤事だが、なるべく数を減らしましょう ○ 特に重いテストが多いと実⾏時間が伸びて⽣産性が下がる ● 確率的に落ちるテスト(Flaky Test)に対処していく ○ ⾃動テストの再実⾏が何度も必要だと、⽣産性は下がるし、CIのコストも上がる ○ テスト成功率などを監視して、よく落ちるものは早めに対処する ● QAエンジニアの⽅とはなるべく仕様設計の段階からコミュニケーションを取る ○ 早い段階で仕様の擦り合わせをすることで、擦り合わせのコストを減らしつつ、異常ケー スやQA実⾏の効率化について早めに対処ができる ● 重要なのは成果‧⽣産性が上がること ○ ⾃分が⼀⼈で頑張る以上に⽂化を作るのを頑張る ○ ⽅法論は重要だが、それに縛られず常に最善を⽬指すのが重要と考えています

Slide 57

Slide 57 text

©MIXI ペアプログラミング

Slide 58

Slide 58 text

58 58 ©MIXI ペアプログラミング ● ドライバー ○ 実際に操作する⼈ ● ナビゲーター ○ ドライバーの操作を眺めつつ、助ける⼈ ● 定期的に役割を⼊れ替えながら進める

Slide 59

Slide 59 text

59 59 ©MIXI ペアプログラミング うまくやるコツ ● ドライバー ○ 今、何をやろうとしているか、やっているかを明確にする (発⾔する) ● ナビゲーター ○ 良い⽅法を思いついたり、ミスに気づいたりしたときに、積極的に発⾔する ○ ドライバーが何をやろうとしていることが良くわからなくなったら、すぐに聞く commit & push してれば、役割交代はしやすいはず‧‧‧?

Slide 60

Slide 60 text

60 60 ©MIXI ペアプログラミング (敬称略) チューター: A 加藤、B, C ⼤倉(⼿が空いていそうな⽅に話しかけていただければ!)

Slide 61

Slide 61 text

©MIXI コードレビューをしよう

Slide 62

Slide 62 text

62 62 ©MIXI コードレビューをしよう ● チームごとにteam-A,B,C ブランチ向きにPRを作ってください ● レビューするチーム ● 演習1: A → B、 B → C、 C → A ● 演習2: A → C、 B → A、 C → B ● 時間が余ったら他のチームをレビューしてもOK

Slide 63

Slide 63 text

63 63 ©MIXI コードレビューをしよう ● コードレビューの⽬的 ○ コードの品質の保証 ○ コードの共有 ■ 設計や作戦の共有

Slide 64

Slide 64 text

64 64 ©MIXI コードレビューをしよう ● どうすれば、レビューが通りやすいかを考えよう ● PR の説明をしっかり書こう ○ どういう背景、理由で、どういうものを作った、など ○ 重点的にレビューして欲しいところや、実装していてよく分からなかったところ、など ○ ⾏単位でコメント/会話ができるのでそれも活⽤しよう ● JIRA のチケットや、関連 PR, issue など ○ 背景の詳細や、仕様などを追いやすい ○ 監査などのときに、追いやすい、など ● どういうタイミングでマージして欲しい、など (QA終わるまで待って、など)

Slide 65

Slide 65 text

65 65 ©MIXI コードレビューをしよう ● レビューは⼈格攻撃ではない (⼼理的安全性) ○ レビューする側もされる側も攻撃ではないことを意識する ● わからないところは聞こう ● 褒めよう! ● この⼈はこういうところをレビューしてくるだろうなぁと考えてみる

Slide 66

Slide 66 text

66 66 ©MIXI 参考⽂献 ● SQuBOK Guide V3 ● テスト駆動開発 ● 【翻訳】テスト駆動開発の定義 ● 保守しやすく変化に強いソフトウェアを⽀える柱 ⾃動テストとテスト駆動開 発 、その全体像 ● はじめて学ぶソフトウェアのテスト技法 ● ソフトウェアテスト技法 ● 「テスタビリティ」への投資で⽣産性向上!評価の指標と向上させるポイント

Slide 67

Slide 67 text

©MIXI