我今天开始使用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
,则不会创建客户。
我有两个JSON文件,这两个文件都包含我用来测试两种方案的客户信息。
JSON中没有第一个名字:
{
"first_name": null,
"last_name": "Test Name",
}
另一个包含JSON中的名字:
{
"first_name": "Test",
"last_name": "Name",
}
在我的单元测试中,使用Quick和Nimble,当第一个名称不可用时,我处理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
。
当我的代码没有点击else
语句的guard
子句时,如何使用BDD获得此方法的100%代码覆盖率,因为数据可以转换为有效JSON对象?我是否应该添加另一个.json
文件,其中包含无法转换为JSON对象的数据,以确保不会创建Customer
以及包含缺失{{1}的.json
文件确保没有创建last_name
?
我只是过度思考&#34; 100%代码覆盖率&#34;概念?我是否需要测试Customer
语句的else
条款?我是否使用BDD方法采用了适当的方法?
答案 0 :(得分:1)
只需编写您想要的任何JSON - 以您能想到的各种方式表达错误。例子:
guard
。俗话说,你只需要涵盖你想要正确的代码。
TDD和BDD是相关的。在TDD中,您首先要编写一个失败的测试。然后,您可以尽快编写通过该测试的代码。最后,您需要清理代码以使其更好。看起来你在事后添加了测试。
顺便说一句,如果您没有使用外部文件,那么您的测试会更加清晰,但是将JSON直接放入您的测试中。这是一个截屏视频,展示了我如何TDD开始JSON转换。截屏视频是在Objective-C中,但原则是相同的:https://qualitycoding.org/tdd-json-parsing/
答案 1 :(得分:0)
使用 if let 实现 100% 的代码覆盖率。
有时,强制准备格式错误的对象以强制执行命中 return
语句中使用的 return nil
或 guard
是不可行的。
当您集成了 3rd 方 SDK 并且在该方法中创建了相应的 3rd 方对象时,就会出现这种情况。 例如:
func aMethod() {
guard let response = 3rdPartyResponse<3rdPartyInput>.createControl(with: .create(with: .someCase)) as? 3rdPartyResponse<3rdPartyInput> else { return }
}
在这种情况下,它非常困难,有时不可能达到回报。
但是如果代码覆盖率是主要标准,你可以使用 if let 来处理这种情况 Iflets 确实给出了 100%代码覆盖率