如何获得 Guard Statement Fall-through 的测试覆盖率
How to Get Test Coverage for Guard Statement Fall-through
我今天开始使用 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
。
当我的代码没有命中 guard
语句的 else
子句时,我如何使用 BDD 达到此方法的 100% 代码覆盖率,因为数据可以转换进入有效的 JSON 对象?我是否应该只添加另一个 .json
文件,其中包含无法转换为 JSON 对象的数据,以确保不创建 Customer
以及包含 .json
的文件缺少 last_name
以确保未创建 Customer
?
我是不是想多了“100% 代码覆盖率”的概念?我什至需要测试 guard
语句的 else
子句吗?我什至有使用 BDD 方法的适当方法吗?
想写什么就写什么 JSON——你能想到的任何形式都是畸形的。示例:
- 您可以使用不正确的内容来触发异常处理 JSON。
- 您可以使用 JSON 数组而不是字典来实现您的第一个
guard
。
俗话说,你只需要覆盖你想要正确的代码。
TDD 和 BDD 是相关的。在 TDD 中,您会先编写一个失败的测试。然后,您将编写尽可能快地通过该测试的代码。最后,您将清理代码以使其更好。看来您是在事后添加测试。
顺便说一句,如果您不使用外部文件,而是将 JSON 直接放入您的测试中,您的测试会更加清晰。这是一个截屏视频,展示了我如何在 JSON 转换开始时进行 TDD。截屏视频在 Objective-C 但原理是相同的:https://qualitycoding.org/tdd-json-parsing/
100% 代码覆盖率 if let.
有时,强制准备格式错误的对象以强制执行命中 guard
语句中使用的 return
或 return nil
是不可行的。
当您集成了第 3 方 SDK 并且相应的第 3 方对象在方法中创建运行时时就是这种情况。
例如:
func aMethod() {
guard let response = 3rdPartyResponse<3rdPartyInput>.createControl(with: .create(with: .someCase)) as? 3rdPartyResponse<3rdPartyInput> else { return }
}
在这种情况下,很难,有时无法击中return。
但是如果代码覆盖率是主要标准,您可以在这种情况下使用 if let 如果让我们给出 100% 的代码覆盖率
我今天开始使用 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
。
当我的代码没有命中 guard
语句的 else
子句时,我如何使用 BDD 达到此方法的 100% 代码覆盖率,因为数据可以转换进入有效的 JSON 对象?我是否应该只添加另一个 .json
文件,其中包含无法转换为 JSON 对象的数据,以确保不创建 Customer
以及包含 .json
的文件缺少 last_name
以确保未创建 Customer
?
我是不是想多了“100% 代码覆盖率”的概念?我什至需要测试 guard
语句的 else
子句吗?我什至有使用 BDD 方法的适当方法吗?
想写什么就写什么 JSON——你能想到的任何形式都是畸形的。示例:
- 您可以使用不正确的内容来触发异常处理 JSON。
- 您可以使用 JSON 数组而不是字典来实现您的第一个
guard
。
俗话说,你只需要覆盖你想要正确的代码。
TDD 和 BDD 是相关的。在 TDD 中,您会先编写一个失败的测试。然后,您将编写尽可能快地通过该测试的代码。最后,您将清理代码以使其更好。看来您是在事后添加测试。
顺便说一句,如果您不使用外部文件,而是将 JSON 直接放入您的测试中,您的测试会更加清晰。这是一个截屏视频,展示了我如何在 JSON 转换开始时进行 TDD。截屏视频在 Objective-C 但原理是相同的:https://qualitycoding.org/tdd-json-parsing/
100% 代码覆盖率 if let.
有时,强制准备格式错误的对象以强制执行命中 guard
语句中使用的 return
或 return nil
是不可行的。
当您集成了第 3 方 SDK 并且相应的第 3 方对象在方法中创建运行时时就是这种情况。 例如:
func aMethod() {
guard let response = 3rdPartyResponse<3rdPartyInput>.createControl(with: .create(with: .someCase)) as? 3rdPartyResponse<3rdPartyInput> else { return }
}
在这种情况下,很难,有时无法击中return。
但是如果代码覆盖率是主要标准,您可以在这种情况下使用 if let 如果让我们给出 100% 的代码覆盖率