🎉

【テスト_3日目】単体テスト1冊目

2024/09/12に公開

こんにちは投資ロウトです。

背景

チームメンバーに自動テストのレクチャーをしていくことにしました。
※チームメンバーが自動テストができるようになるのがゴールです。
※週一の会議に向けての資料となるため、週一でこちらの単元は更新しようか検討しております。

単体テストのパターン(AAAパターン)

AAAパターンは
A・・・Arrange(準備)
A・・・Act(実行)
A・・・Assert(確認)
の上記で実行していくパターンとのこと。

# 例)
# 準備
first = 5
second = 20
# インスタンスを生成
calculator = Calculator(first, second)

# 実行
result = calculator.add()

# 実行結果を確認する
self.assertEqual(result, 25)  # first(5) + second(20) = 25

また上記のパターンを使うことで、簡潔で統一された構造を持たせられるようになるとのことでした。
※Given When ThenのパターンもAAAパターンとほぼ同じというお話もありました。

注意事項

  1. 複数のフェーズを用意することは避ける
# 準備
# 実行
# 確認
# ...準備や実行、確認が続く

上記のように、一つの単体テストでは1つしか実行しないことを担保すべきというお話もありました。また複数の確認は、統合テストで行うものなので、単体テストでは、そう言ったことをしないようにすべきというお話もありました。

  1. if文は使用しないこと

if文を使うことは、アンチパターンとのことです。理由は分岐のない単純な流れにしないといけないからだそうです。もしif文を使わないといけないような場合は、複数のテストケースに分割をしないといけないと言ったこともありました。

  1. 各フェーズのサイズについて

一番Arrangeの準備がソースコード量が最大になることが多いとのことでした。また実行に関しても、一つの関数のテストのみなどが想定されることから、実行に関しては、1行で終わることも多いとのことです。

  1. 確認はどれくらいあればいいのか?

あくまで1テストで複数のフェーズは入れないと言った決まりがあるそうですが、確認は複数あっても問題ないということがありました。それは1単位のコードではなく、1単位の振る舞いの確認を行うからとのことです。

  1. テストが綺麗になるように、行を開ける

準備、実行、確認の3つはどこからどこまでが準備なのかとわかるように、空行を入れて間隔をあけた方がいいとのことでした。

テストフィクスチャ

各テストでインスタンスの生成など共通して行われる処理については、共通の箇所で定義をし、毎回同一のソースコードを書かなくていいようにする。

import unittest

class Calculator:
    def add(self, first, second):
        return first + second

class TestCalculator(unittest.TestCase):
    
    def setUp(self):
        # インスタンスを共通で生成
        self.calculator = Calculator()
    
    def test_addition_with_default_values(self):
        # 準備
        first = 5
        second = 20
        # ここでインスタンス生成する必要がない
        
        # 実行
        result = self.calculator.add(first, second)
        
        # 実行結果を確認する
        self.assertEqual(result, 25)

単体テストでの命名規則

・命名規則を厳格化しない
→複雑な条件も存在するため、メソッド名はこういった規則で運用するのは難しい上に、ソースコードの可読性が悪くなってしまうことにもつながる。

・単語間は_(アンダースコア)を使って区切るようにする
→読みやすさ向上のため

と一旦以上で学習を区切りたいと思います。チームメンバーのスキルアップが図れるように、焦らずコツコツ自分のペースで頑張っていきたいと思います。ご精読ありがとうございました。

Discussion