😎

複雑な内部状態に依存しない という言葉の理解をする【サンプルコードあり】

2023/05/18に公開

間違えた理解をしている部分もあると思いますが、記事を投稿します。

参考書籍

https://peaks.cc/books/iOS_architecture

こちらの本に、
テストのしやすさを実現するためには、複雑な内部状態に依存しない ことが重要だと記載されていた。
だが、その意味が理解できなかったため、意味を調べて、サンプルコードを用いて説明していく。

複雑な内部状態に依存しない の言葉の意味

複雑な内部状態に依存しないという言葉の意味は、テストの際にテスト対象のコードや機能をテストするために、その内部で保持しているデータや状態に依存しないことを指します。つまり、テストケースを作成する際に、テスト対象の内部状態やデータを直接的に操作するのではなく、外部からの入力や出力に焦点を当てることです。

このようなアプローチを取ることで、テストはより予測可能で安定したものになります。テストケースは外部のインターフェースを通じてテスト対象のコードとやり取りし、その振る舞いや結果を検証することが重要です。

悪い例

サンプルコード
class Calculator {
    private var result: Int = 0
    
    func add(_ a: Int, _ b: Int) {
        result = a + b
    }
    
    func subtract(_ a: Int, _ b: Int) {
        result = a - b
    }
    
    func getResult() -> Int {
        return result
    }
}

// テストケース
class CalculatorTests: XCTestCase {
    func testAdd() {
        let calculator = Calculator()
        calculator.add(2, 3)
        
        let result = calculator.getResult()
        XCTAssertEqual(result, 5, "Addition should return the correct result.")
    }
    
    func testSubtract() {
        let calculator = Calculator()
        calculator.subtract(5, 2)
        
        let result = calculator.getResult()
        XCTAssertEqual(result, 3, "Subtraction should return the correct result.")
    }
}

上記の例では、Calculator クラスが結果を内部状態(result)として保持し、getResult() メソッドを介して結果を取得します。テストケースでは、直接 getResult() メソッドを呼び出して内部状態の結果を検証しています。

この例では、テストケースが Calculator クラスの内部状態に直接依存しており、内部状態が変更されるとテストの結果に影響を与える可能性があります。このような内部状態に依存したテストでは、内部状態の変更やテストの順序によって結果が異なる場合があり、テストの安定性や保守性が低下する可能性があります。

良い例

サンプルコード
class Calculator {
    func add(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
    
    func subtract(_ a: Int, _ b: Int) -> Int {
        return a - b
    }
}

// テストケース
class CalculatorTests: XCTestCase {
    var calculator: Calculator!
    
    override func setUp() {
        super.setUp()
        calculator = Calculator()
    }
    
    override func tearDown() {
        calculator = nil
        super.tearDown()
    }
    
    func testAdd() {
        let result = calculator.add(2, 3)
        XCTAssertEqual(result, 5, "Addition should return the correct result.")
    }
    
    func testSubtract() {
        let result = calculator.subtract(5, 2)
        XCTAssertEqual(result, 3, "Subtraction should return the correct result.")
    }
}

resultとして、内部状態に依存せずに、Calculatorクラスの機能をテストしています。テストケースでは外部の入力と出力に焦点を当て、メソッドの結果を検証することで、複雑な内部状態に依存せずにテストを行っています。


以上です。
他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします!

https://sites.google.com/view/muranakar
個人でアプリを作成しているので、良かったら覗いてみてください!

Discussion