关于iOS测试

Posted 颐和园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于iOS测试相关的知识,希望对你有一定的参考价值。

  1. 如何 Update snapshot image

如果修改了 UI,那么当你提 PR 时很可能 UITest 会测试失败,因为 UI 有了改变。
你会看到测试代码在哪里失败,比如 OnboardLandingViewControllerTests 类的某 某方法等。
找到这个类的 setUp 方法添加: recordMode = true
然后运行 snapshot test,然后 snapshot test 会录制一张图片并打印出图片路径 (有 时候可能需要将这张图片复制一份到 cosmos-ios-lib/TestSupport/ ReferenceImages_64 下面对应子目录),然后将 recordMode 一句删除,push,注 意应该勾选上那张图片一起提交。
回去 Jenkins ⻚面,点击 reRun failed testing

注意,需要选择 iPhone XR 13.3 模拟器并关闭 Dynamic font

2、无论用哪个模拟器,上传的 snapshots 总是无法通过测试

遇到个问题,snapshot test 要求 iPhone XR 13.3,但上传图片后还是失败。将模拟 器换成 iPhone XR 12.4 /13.3, iPhone 11 10.3-13.3 都试过了,还是不行。

先后提交了十多次代码,最后发现,需要将 Larger Accessibility Sizes 关闭, 然后 把字号大小恰好调到中间呢。因为之前为了测试 accessibility,已经改变了默认的 字体大小,导致截图和原来始终有区别。

4、‘xxx’ is inaccessible due to ‘private’ protection level

将这个属性标记为 private(set), 这样可以允许外部读取,但不能修改这个属性。
如果这是一个函数,则只能将它改成非 private。

5、单元测试中如何进行异步测试

// Create an expectation
let expectation = XCTestExpectation(description: "wait") let dispatchTime = DispatchTime.now()+1 DispatchQueue.main.asyncAfter(deadline: dispatchTime){ 
// Fullfil the expectation to let the test runner // know that it's OK to proceed expectation.fulfill() 
}
// Wait for the expectation to be fullfilled, or time out
// after 1 seconds. This is where the test runner will pause. wait(for: [expectation], timeout: 2) XCTAssertTrue(mockNavigationController.navigationDidPop) XCTAssertTrue(mockNavigationController.navigationDidDismiss) 

上面的方法可以用于单个文件的测试,但是整个 UT 和 jekins 将无法通过,所以还 是得用下面的方法。这个方法单个文件无法通过,但 UT 和 jenkins 都没问题:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) { XCTAssertTrue(interactor.requestCardLostStolenCalled) 
} 

注意,timeout 的时间最好设置得比 dispatchtime 多一些,否则又可能 expectiation 还没有 fullfill 就超时了。具体多多少不好说,这里多加 1 秒只是一个 经验值。

11、如何测试 tableview // Test for tableview

func testTableView() { 
viewModel = SetupViewViewModel( title: "title", 
sectionModels: [ SectionModel( 
title: "title", cellModels: [ 
DetailsTableViewCell.ViewData( reviewItem: ReviewItem.ViewModel( 
title: AccessibleValue("title"), value: AccessibleValue("value"), subValue: nil, 
hasBottomDivider: false ), 
valueAccessibilityLabel: nil, subValueAccessibilityLabel: nil, hasBottomDivider: false 
) ] 
) ], 
confirmButtonTitle: "confirmButtonTitle" ) 
viewController.reviewCellConfig = viewModel.sectionModels viewController.tableView.reloadData() 
debugPrint(viewController.reviewCellConfig)
// Test for headerInsection
let header = viewController.tableView(viewController.tableView, 
viewForHeaderInSection: 1) XCTAssertNotNil(header) 
// Test for heightForHeaderInSection 
let height = viewController.tableView(viewController.tableView, heightForHeaderInSection: 0) 
XCTAssertNotEqual(0, height) 
// Test for cellForRowAtIndexPath 
let cell = viewController.tableView(viewController.tableView, cellForRowAt: IndexPath(row: 0, section: 0)) 
} 

13、不要用单个文件测试代替整个 UT 测试
因为有时候,单个文件测试通过,不表示整个 UT 通过,而且这样的测试代码在 Jekins 上是通不过的。

14、测试 presenter 时出现的一个问题

测试 presentSetupView 时,发现单个文件测试通过,但是整个 UT 报错,同时提
交代码后 jenkiins 测试失败。
最后发现是 presenter 的 presentSetupView 写的有问题。
因为 presentSetupView 中有一个判断,只有满足条件才调用 viewController 的 displaySetupView 方法。测试的时候条件不满足,所以没有调用,导致测试不通 过。

15、NSMutableAttributedString 导致 UT crash 的问题

比如这行代码在 UT 中会通不过:

let message = try? NSMutableAttributedString( data: data, 
options: [
.documentType: NSAttributedString.DocumentType.html, 
], 
documentAttributes: nil ) 

这是一个 known bug,https://developer.apple.com/forums/thread/115405
由于这个方法在解析含有 html 标签 data 时导致主线程阻塞过⻓,由于 App 中多线 程执行的场景不多,所以不会有问题。但是在 UT 中,由于有大量 asyncAfter 调 用,所以会出现 crash。
如果将 option 参数改为:

options: [ 
.documentType: NSAttributedString.DocumentType.plain, ], 

则不会导致此问题。尝试过将 html 设置为空字符串,但是仍然不行,只有改 option。

以上是关于关于iOS测试的主要内容,如果未能解决你的问题,请参考以下文章

关于android导航架构组件的问题

关于iOS测试

iOS代码片段CodeSnippets

IOS开发-OC学习-常用功能代码片段整理

如何通过 CI 处理 Firebase 测试实验室 ios 测试的代码签名?

关于片段生命周期