2017-01-01 42 views
1

我開始用BDD方法編寫iOS單元測試。我有一個關於guard聲明並獲得100%代碼覆蓋率的問題。如何獲得Guard守護進程的測試覆蓋率落後

我有以下代碼,該代碼處理將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,則不會創建客戶。

我有兩個JSON文件,它們都包含用於測試這兩種情況的客戶信息。

一個包含了JSON沒有名字:

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

其他包含在JSON第一個名字:

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

在我的單元測試,使用快速和靈活,我處理創建一個Customer時,第一個名稱不可用,當它是:

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()) 
      } 
     } 
    } 
} 

這可確保在第一個名稱丟失或存在於返回的JSON中時創建Customer

由於數據能夠轉換爲有效的JSON對象,因此當我的代碼未碰到guard語句的else子句時,如何使用BDD獲得此方法的100%代碼覆蓋率?我應該只添加另一個.json文件,其中包含無法轉換爲JSON對象的數據以確保沒有創建Customer以及包含缺少last_name.json文件以確保未創建Customer

我是否只是過度思考「100%代碼覆蓋率」概念?我甚至需要測試guard語句的else條款嗎?我是否有使用BDD方法的適當方法?

回答

1

只要寫下你想要的任何JSON - 在你想到的每一種方式上都是畸形的。示例:

  • 您可以用不正確的JSON來處理異常處理。
  • 你可以用你的第一個guard,這是一個JSON數組,而不是字典。

俗話說,你只需要覆蓋你想要正確的代碼。

TDD和BDD有關。在TDD中,你會先寫一個失敗的測試。然後,您會盡可能快地編寫通過該測試的代碼。最後,你會清理你的代碼,使其更好。它看起來像是在事後添加測試。

順便說一句,如果您沒有使用外部文件,那麼測試會更清晰,但將JSON直接放入測試中。以下是截屏視頻,展示了我如何TDD JSON轉換的開始。截屏視頻採用Objective-C,但原理相同:http://qualitycoding.org/tdd-json-parsing/

+0

@JonRein我很感謝您的見解!我可以問,你是如何得出結論的:我事後寫了我的測試?這正是我所做的,但我很好奇你是怎麼得出這個結論的。我肯定在研究你的概念,希望能夠更好地理解。 –

+0

@NickKohrn因爲當代碼是測試驅動的時候,你不會寫任何不滿足測試的代碼。所以你最終不會問:「我有一些代碼,現在我該如何覆蓋它?」 –