[英]Unit Test HKSampleQuery in Swift
When I need to read data from HealthKit
this is how my code looks like: 当我需要从HealthKit
读取数据时,这就是我的代码的样子:
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)
This specific code was extracted from here for demo purpose. 此特定代码是从这里提取的,用于演示目的。
So my question is: 所以我的问题是:
How can I unit test this kind of code ? 我该如何对这种代码进行单元测试?
I encapsulate this code in a function in a model class that knows nothing about the UI. 我将此代码封装在模型类中的函数中,该模型类对UI一无所知。 It works like this: 它的工作原理如下:
At the place the you have your 在你拥有你的地方
// Update some UI
call a completion closure, that was passed to the function using a parameter. 调用一个完成闭包,它使用参数传递给函数。
You call this function from your controller class like this 您可以从控制器类中调用此函数
hkModel.selectSteps() {
[unowned self] (query, results, error) in
// update UI
}
This way you have a clean separation between your query logic in the model class and your UIController code. 这样,您可以清楚地分离模型类中的查询逻辑和UIController代码。
Now you can easily write a unit test calling the same method: 现在,您可以轻松编写调用相同方法的单元测试:
func testSteps() {
hkModel.selectSteps() {
[unowned self] (query, results, error) in
// XCTAssert(...)
}
}
The last thing you need is to respect that your test code is called asynchronously: 您需要的最后一件事是尊重您的测试代码是异步调用的:
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)
}
}
update 更新
Because you asked: 因为你问:
I handle authorization at the test setup. 我在测试设置中处理授权。 looks like this: 看起来像这样:
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)
}
}
}
The first time you run this code in a simulator, you have to approve authorization manually. 第一次在模拟器中运行此代码时,您必须手动批准授权。
After the first run the tests run without manual intervention. 第一次运行后,测试运行无需人工干预。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.