1

私は今日、BDD アプローチを使用して iOS 単体テストを書き始めました。guardステートメントと 100% のコード カバレッジを得ることに関して質問があります。

Dataオブジェクトへの変換を処理する次のコードがありCustomerます。

internal final class func customer(from data: Data) -> Customer? {
    do {
        guard let jsonDictionary = try JSONSerialization.jsonObject(with: data, options: []) as? Dictionary<String, Any> else {
            return nil
        }
        var customerFirstName: String? = nil
        var customerLastName: String
        if let firstName = jsonDictionary["first_name"] as? String {
            customerFirstName = firstName
        }
        guard let lastName = jsonDictionary["last_name"] as? String else {
            return nil
        }
        customerLastName = lastName
        return Customer(firstName: customerFirstName, lastName: customerLastName)
    } catch {
        return nil
    }
}

バックエンドが作成されたとき、一部の顧客には苗字だけが与えられ、姓名が含まれていました。そのため、顧客の名前はオプションです。フルネームが の値になる場合がありますlast_name

私のコードでは、顧客の名はオプションですが、姓は必須です。ネットワーク リクエストから受信した JSON で姓が返されない場合は、顧客を作成しません。また、Dataを にシリアル化できない場合Dictionary、顧客は作成されません。

2 つの JSON ファイルがあり、どちらにも、両方のシナリオをテストするために使用している顧客情報が含まれています。

1 つは、JSON に名が含まれていません。

{
    "first_name": null,
    "last_name": "Test Name",
}

もう 1 つは、JSON に名が含まれています。

{
    "first_name": "Test",
    "last_name": "Name",
}

私の単体テストでは、Quick と Nimble を使用してCustomer、最初の名前が利用できない場合と次の場合に a の作成を処理します。

override func spec() {
    super.spec()
    let bundle = Bundle(for: type(of: self))
    describe("customer") {
        context("whenAllDataAvailable") {
            it("createsSuccessfully") {
                let path = bundle.path(forResource: "CustomerValidFullName", ofType: "json", inDirectory: "ResponseStubs")!
                let url = URL(fileURLWithPath: path)
                let data = try! Data(contentsOf: url)
                let customer = DataTransformer.customer(from: data)
                expect(customer).toNot(beNil())
            }
        }
        context("whenMissingLastName") {
            it("createsUnsuccessfully") {
                let path = bundle.path(forResource: "CustomerMissingLastName", ofType: "json", inDirectory: "ResponseStubs")!
                let url = URL(fileURLWithPath: path)
                let data = try! Data(contentsOf: url)
                let customer = DataTransformer.customer(from: data)
                expect(customer).to(beNil())
            }
        }
    }
}

これによりCustomer、返された JSON に最初の名前がないか存在する場合に を作成することが保証されます。

データを有効な JSON オブジェクトに変換できるため、コードがステートメントのelse句にヒットしない場合、BDD を使用してこのメ​​ソッドの 100% のコード カバレッジを得るにはどうすればよいでしょうか? JSON オブジェクトに変換できないデータを含むguard別のファイルを追加して、aが作成されないようにするだけでなく、欠落している を含むファイルを追加して、a が作成されないようにする必要がありますか?.jsonCustomer.jsonlast_nameCustomer

「100% コード カバレッジ」という概念を考えすぎているだけですか? elseステートメントの節をguardテストする必要さえありますか? BDDメソッドを使用した適切なアプローチさえありますか?

4

2 に答える 2

1

考えられるあらゆる方法で不正な形式の JSON を記述してください。例:

  • 正しくない JSON で例外処理を実行できます。
  • guard辞書ではなく、JSON 配列である何かを最初にヒットすることができます。

ことわざにあるように、正しくしたいコードだけをカバーする必要があります。

TDD と BDD は関連しています。TDD では、失敗するテストを最初に記述します。次に、そのテストに合格するコードをできるだけ早く記述します。最後に、コードをクリーンアップして改善します。事後的にテストを追加しているようです。

ところで、外部ファイルを使用せず、JSON を直接テストに入れれば、テストはより明確になります。これは、JSON 変換の始まりをどのように TDD したかを示すスクリーンキャストです。スクリーンキャストは Objective-C ですが、原則は同じです: https://qualitycoding.org/tdd-json-parsing/

于 2017-01-02T03:29:52.593 に答える