2015-12-01 4 views
3

Когда мне нужно прочитать данные из HealthKit это как мой код выглядит следующим образом:Unit Test HKSampleQuery в Swift

let stepsCount = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) 

let stepsSampleQuery = HKSampleQuery(sampleType: stepsCount, 
    predicate: nil, 
    limit: 100, 
    sortDescriptors: nil) 
    { [unowned self] (query, results, error) in 
     if let results = results as? [HKQuantitySample] { 
      self.steps = results 
      // Update some UI 
     } 
     self.activityIndicator.stopAnimating() 
} 

healthStore?.executeQuery(stepsSampleQuery) 

Этот конкретный код был извлечен из here для демонстрационной цели.

Так что мой вопрос:

Как я могу модульного тестирования такого кода?

ответ

2

Я инкапсулирую этот код в функцию класса модели, которая ничего не знает о пользовательском интерфейсе. Вот как это работает:

На месте у вас есть

// Update some UI 

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

Вы называете эту функцию из своего класса контроллера, как этот

hkModel.selectSteps() { 
    [unowned self] (query, results, error) in 
    // update UI 
} 

Таким образом, вы имеете четкое разделение между вашей логики запроса в классе модели и кода UIController.

Теперь вы можете легко написать тест блока вызова тот же метод:

func testSteps() { 
    hkModel.selectSteps() { 
     [unowned self] (query, results, error) in 
     // XCTAssert(...) 
    } 
} 

Последнее, что вам нужно, это уважать, что ваш тестовый код вызывается асинхронно:

let stepExpectationEnd = expectationWithDescription("step Query") 
hkModel.selectSteps() { 
    [unowned self] (query, results, error) in 
    // XCTAssert(...) 
    stepExpectationEnd.fulfill() 
} 
waitForExpectationsWithTimeout(10.0) { 
    (error: NSError?) in 
    if let error = error { 
     XCTFail(error.localizedDescription) 
    } 
} 

обновление

Потому что вы спрашивали:

Я обрабатываю авторизацию в тестовой настройке. выглядит следующим образом:

var healthData: HealthDataManager? 
override func setUp() { 
    super.setUp() 
    healthData = HealthDataManager() 
    XCTAssert(healthData != nil, "healthDadta must be there") 

    let authorizationAndAScheduleExpectation = expectationWithDescription("Wait for authorizatiion. Might be manual the first time") 
    healthData?.authorizeHealthKit({ (success: Bool, error: NSError?) -> Void in 
     print ("success: \(success) error \(error?.localizedDescription)") 
     // fails on iPad 
     XCTAssert(success, "authorization error \(error?.localizedDescription)") 

     self.healthData?.scheduleAll() { 
      (success:Bool, error:ErrorType?) -> Void in 
      XCTAssert(success, "scheduleAll error \(error)") 

      authorizationAndAScheduleExpectation.fulfill() 
     } 
    }) 
    waitForExpectationsWithTimeout(60.0) { 
     error in 
     if let error = error { 
      XCTFail(error.localizedDescription) 
     } 
    } 
} 

Первый раз, когда вы запустите этот код на тренажере, вы должны утвердить разрешение вручную.

После первого запуска испытания проходят без ручного вмешательства.

+0

Этот подход выглядит очень интересным, но у меня есть две основные проблемы: 1- Как цель тестирования связана с авторинтизацией healthkit? , 2- Что именно мы тестируем, поскольку stepCount - это то, что не отслеживается симулятором или целью тестирования? Должен ли я высмеивать некоторые данные? Любые мысли или предложения здесь? –

+0

Часть 1: Я обновил свой официальный ответ. Часть 2. У вас есть приложение для здоровья в вашем симуляторе. Откройте это приложение работоспособности в своем симуляторе и используйте его, чтобы добавить точки данных для шагов: health app -> fitness -> steps -> add data points –

+0

Спасибо, это фантастика. –