post Image
ユニットテストにも可読性を持たせる (Four Phase Test)

はじめに

ユニットテストを書いていると、
プロダクトコード同様、可読性が悪くなってきますよね。

ユニットテストの「Four Phase Test」という考え方について、
はじめて知ったので簡単にまとめます。

「Four Phase Test」とは、下記のような4つの手順に分けて、
実施する方法です。

No. フェーズ 説明
1. Setup 前処理
2. Exercise 実行
3. Verify 検証
4. TearDown 後処理

可読性が悪くなる原因

テスト毎の前提条件や、後処理など、
検証以外のテストコードが増えてきたときに、
どこが実行部分で、どこが検証部分か分かりづらくなりがちです。

解決策の方針

そこで、「Four Phase Test」の手順に則って、
テストコードを実装してみる。
(他にもあれば、ご教授願います。)

ユニットテスト全体で共通のSetupとTearDownは、意識していましたが、
ExerciseとVerifyは、意識できていませんでした。

リファクタリング対象のテストコード

コード量も長くなり、可読性が落ちています。

WarikanModelTests.swift
import XCTest
@testable import Warikan

class WarikanModelTests: XCTestCase {

    let usecase = WarikanUsecase()
    let delegete = SpyWarikanDelegate()

    override func setUp() {
        super.setUp()
        usecase.delegate = delegete
    }

    override func tearDown() {
        super.tearDown()
        usecase.delegate = nil
    }

    func test10000div3() {

        let exp = expectation(description: "10000円を3人で割り勘したときのテスト")
        delegete.asyncExpectation = exp

        usecase.calc(totalAmountStr: "10000", numberOfPeopleStr: "3")

        waitForExpectations(timeout: 1) { error in
            if let error = error {
                XCTFail("waitForExpectationsエラー: \(error)")
            }

            switch self.delegete.result! {
            case .success(let bugetStr):
                XCTAssertEqual(bugetStr, "1人辺りの支払い額は、3,400円です。")

            case .error(_) :
                XCTFail("テスト失敗")
            }
        }
    }
}

リファクタリング①

コメントで、4つのフェーズに分けます。
一旦、グルーピングは出来ました。
但し、別の前提条件のテストをするときなど、冗長になることもあります。

WarikanModelTests.swift

/* test10000div3は、割り切れないときのテストを実行します。
 * Check: 10000 / 3 = 3400.
 */
    func test10000div3() {

        // 1. Setup
        let exp = expectation(description: "10000円を3人で割り勘したときのテスト")
        delegete.asyncExpectation = exp

        // 2. Exercise
        usecase.calc(totalAmountStr: "10000", numberOfPeopleStr: "3")

        // 3. Verify
        waitForExpectations(timeout: 1) { error in
            if let error = error {
                XCTFail("waitForExpectationsエラー: \(error)")
            }

            switch self.delegete.result! {
            case .success(let bugetStr):
                XCTAssertEqual(bugetStr, "1人辺りの支払い額は、3,400円です。")

            case .error(_) :
                XCTFail("テスト失敗")
            }
        }

        //4. TearDown
    }

リファクタリング②

ヘルパーメソッドで、4つのフェーズに分けます。
ヘルパーメソッドの切り出すと、
リファクタリング①で上げた冗長な記載はなくなりました。
合わせて可読性も上がりましたね。

WarikanModelTests.swift
/* test10000div3は、割り切れないときのテストを実行します。
 * Check: 10000 / 3 = 3400.
 */
    func test10000div3() {

        // 1. Setup
        whenWarikan(description: "10000円を3人で割り勘したときのテスト")

        // 2. Exercise
        usecase.calc(totalAmountStr: "10000", numberOfPeopleStr: "3")

        // 3. Verify
        verifyWarikanResult(bugetStr: "1人辺りの支払い額は、3,400円です。")

        //4. TearDown
    }

    // 1. Setup
    private func whenWarikan(description: String){
        delegete.asyncExpectation = expectation(description: description)
    }

    // 2. Exercise
    private func exerciseWarikan(totalAmountStr: String, numberOfPeopleStr: String) {
        usecase.calc(totalAmountStr: totalAmountStr, numberOfPeopleStr: numberOfPeopleStr)
    }

    // 3. Verify
    private func verifyWarikanResult(bugetStr: String) {

        waitForExpectations(timeout: 1) { error in
            if let error = error {
                XCTFail("waitForExpectationsエラー: \(error)")
            }

            switch self.delegete.result! {
            case .success(let bugetStr):
                XCTAssertEqual(bugetStr, bugetStr)

            case .error(_) :
                XCTFail("テスト失敗")
            }
        }
    }

まとめ

ユニットテストにも可読性が求められますね。
一つの方針として、「Four Phase Test」も推進していきたいです。

その他の語録

用語  説明
Test テストケース
Suite Testをまとめたもの
SUT 「System Under Test」の略で、テスト対象のこと
Fixture 個別の期待結果を生成するためのまとまり。「Setup」を何らかの形で特化させたものになる。

『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。