Как протестировать функцию/вычисляемое свойство, для которого требуется информация об устройстве?

Я разрабатываю приложение календаря, в котором пытаюсь создать тесты для функций, использующих календари на пользовательском устройстве. Переменная calendar: EKCalendar берется из хранилища событий пользователей, поэтому, когда модульные тесты запускаются на эмуляторе XCode, они терпят неудачу, поскольку календаря не существует. Использование моего личного устройства работает, но тогда тесты не пройдут на нашем сервере сборки.

Каковы хорошие подходы к тестированию функции/вычисляемого свойства, использующего календарь/хранилище событий пользователя?

    ///Return the user's name. If this hasn't been saved extract their name from their Enterprise calendar and save it.
static var name: String? {
    if let savedName = defaults.string(forKey: "name") {
        return savedName
    }

    // calendar is a specific EKCalendar members of my company will have.
    guard let calendar = MeetingsFetcher().getUserEnterpriseCalendars().first,
        let parsedName = calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar) else {
            return nil
    }
    defaults.set(parsedName, forKey: "name")
    return parsedName
}


func getEnterpriseCalendars() -> [EKCalendar]{
    guard EKEventStore.authorizationStatus(for: .event) == .authorized else { return [EKCalendar]() }
    for calendar in MeetingsFetcher.eventStoreClass.calendars(for: .event) {
        if calendar.source.title.range(of: "IBM") != nil{
            return [calendar]
        }
    }
    return [EKCalendar]()
}

Не обращайте внимания на то, что он возвращает массив, я не совсем понимаю, почему он это делает: p


person Declan McKenna    schedule 13.02.2018    source источник
comment
Обычно для этих целей вы можете использовать Mock-объект, который имитирует поведение вашего реального устройства. Чтобы он работал только для симулятора, вы можете использовать один из следующих вариантов: -or-simulator-in-swift" title="определить, создается ли приложение для устройства или симулятора в swift"> stackoverflow.com/questions/24869481/   -  person Dmitry A.    schedule 13.02.2018


Ответы (1)


Итак, позвольте уточнить, что вам действительно нужно проверить в своей функции.

  1. MeetingsFetcher().getUserEnterpriseCalendar()

  2. calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar)

Я предполагаю, что вы хотите проверить их обоих. Но что касается упомянутой вами проблемы, я думаю, что невозможно на самом деле проверить, действительно ли ваша функция getUserEnterpriseCalendar работает правильно на симуляторе, потому что она ничего нигде не возвращает (за исключением того, что вы создаете скрипт на своем сервере сборки, чтобы позволить симулятору подписаться или добавить ваш календарь на нем)

Однако я могу предложить вам смоделировать функцию getUserEnterpriseCalendar и сделать предположение в вашем модульном тесте, что getUserEnterpriseCalendar вернет правильное значение в любой среде. Возможно, вам потребуется изменить вычисляемое свойство, чтобы оно функционировало, и передать для этого параметр MeetingFetcher.

// function modification
static func name(from meetingFetcher: MeetingFetcher) -> String {
    if let savedName = defaults.string(forKey: "name") {
        return savedName
    }

    // calendar is a specific EKCalendar members of my company will have.
    guard let calendar = meetingFetcher.getUserEnterpriseCalendar().first,
        let parsedName = calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar) else {
            return nil
    }
    defaults.set(parsedName, forKey: "name")
    return parsedName
}

// In testing code.
func testOrganizationCalendar() {

    class MockedMeetingFetcher: MeetingFetcher {
        override func getUserEnterpriseCalendars() -> [EKCalendar] {
            let calendar1 = EKCalendar()
            calendar1.title = "ExpectedToMatchRegexTitle"
            return [calendar1]
        }
    }

    XCTestAssertEqual(YourClass.name(from: MockedMeetingFetcher()), "Hure!!!")

}

Я надеюсь, что это может помочь даже просто дать вам некоторые идеи.

person tpeodndyy    schedule 06.03.2018
comment
В основном я хочу проверить, есть ли в EKEventStore календари. Оказывается, EKEventStore.calendars всегда пуст, если вы попытаетесь получить доступ к хранилищу событий до получения разрешения пользователя. Модульный тест, чтобы предупредить меня, когда это произошло, было бы неплохо предотвратить это в будущем, но, судя по всему, это невозможно. Вы когда-нибудь слышали о том, чтобы кто-то программно вставлял календари в эмулятор своего сервера сборки? Я подозреваю, что Apple не позволит этого. - person Declan McKenna; 10.03.2018
comment
Можно выполнить глубокую ссылку в приложение «Календарь» (используя схему webcal://), чтобы подписаться или добавить календарь. Однако вам все равно нужно найти способ выполнить кнопку «Подписаться», когда открыто приложение календаря, что возможно. - person tpeodndyy; 11.03.2018