Я начал писать модульные тесты iOS сегодня с помощью подхода BDD. У меня есть вопрос относительно заявлений guard
и получения покрытия 100% кода.Как получить тестовое покрытие для отчета об удержании Fall-through
У меня есть следующий код, который обрабатывает преобразование 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())
}
}
}
}
Это гарантирует, что я создаю Customer
, когда первое имя отсутствует или присутствует в возвращенном JSON.
Как я могу получить 100% -ное покрытие кода этого метода, используя BDD, когда мой код не удаляет предложения else
операторов guard
, поскольку данные могут быть превращены в действительные объекты JSON? Должен ли я просто добавить еще один файл .json
с данными, которые нельзя преобразовать в объект JSON, чтобы не создавать Customer
, а также файл .json
, содержащий недостающий last_name
, чтобы гарантировать, что Customer
не создан?
Я просто передумал концепцию покрытия 100% кода? Мне даже нужно, чтобы были проверены предложения else
утвержденных заявлений guard
? Есть ли у меня подходящий подход, используя метод BDD?
@ JonRein Я ценю ваше понимание! Могу ли я спросить, как вы пришли к выводу, что я написал свои тесты после факта? Это именно то, что я сделал, но мне любопытно, почему вы пришли к такому выводу. Я определенно изучаю ваши концепции и надеюсь лучше понять. –
@NickKohrn Поскольку, когда код управляется с помощью теста, вы не можете писать код, который не удовлетворяет тесту. Поэтому вы не спрашиваете: «У меня есть код, как я могу его покрыть?» –