diff --git a/Chapter1 - iOS/1.75.md b/Chapter1 - iOS/1.75.md index dd0e4da..f797ead 100644 --- a/Chapter1 - iOS/1.75.md +++ b/Chapter1 - iOS/1.75.md @@ -248,7 +248,7 @@ TDD 强调不断的测试推动代码的开发,这样`简化了`代码,保 TDD 开发过程类似下图: -![](./../assets/2020-07-13-TDDStructure.png) +![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-13-TDDStructure.png) - 先编写该功能的测试用例,实现测试代码。这时候去跑测试,是不通过的,也就是到了红色的状态 - 然后编写真正的功能实现代码。这时候去跑测试,测试通过,也就是到了绿色的状态 @@ -266,11 +266,11 @@ TDD 开发过程类似下图: 1. 新建一个工程,确保 “Include Unit Tests” 选项是选中的状态 - ![TDD Step 1](./../assets/2020-07-13-TDDStep1.png) + ![TDD Step 1](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-13-TDDStep1.png) 2. 创建后的工程目录如下 - ![TDD step2](./../assets/2020-07-13-TDDStep2.png) + ![TDD step2](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-13-TDDStep2.png) 3. 删除 Xcode 创建的测试模版文件 `TDDDemoTests.m` @@ -284,7 +284,7 @@ TDD 开发过程类似下图: 6. 实现测试用例代码。创建继承自 Unit Test Case class 的测试类,命名为 `工程前缀+测试类名+Test`,也就是 `TDDPersonTest.m`。 - ![TDD step 3](./../assets/2020-07-13-TDDStep3.png) + ![TDD step 3](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-13-TDDStep3.png) 7. 因为要测试 Person 类,所以在主工程中创建 Person 类 @@ -986,67 +986,158 @@ SPEC_END 很多 UI 自动化测试框架的底层实现都依赖于 `Accessibility`,也就是 App 可用性。`UI Accessibility` 是 iOS 3.0 引入的一个人性化功能,帮助身体不便的人士方便使用 App。 +Accessibility 通过对 UI 元素进行分类和标记。分类成类似按钮、文本框、文本等类型,使用 identifier 来区分不同 UI 元素。[无痕埋点的设计与实现](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.55.md)里面也使用 `accessibilityIdentifier` 来绑定业务数据。 + +1. 使用 Xcode 自带的 UI测试则在创建工程的时候需要勾选 “Include UI Tests”。 +2. 像单元测试意义,UI 测试方法命名以 test 开头。将鼠标光标移到方法内,点击 Xcode 左下方的红色按钮,开始录制 UI 脚本。 + +![UI 脚本录制](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-15-XcodeUITesting.png) + +解释说明: + +```objective-c +/*! Proxy for an application that may or may not be running. */ +@interface XCUIApplication : XCUIElement +// ... +@end +``` + +- `XCUIApplication launch` 来启动测试。`XCUIApplication` 是 UIApplication 在测试进程中的代理,用来和 App 进行一些交互。 + +- 使用 `staticTexts`来获取当前屏幕上的静态文本(UILabel)元素的代理。等价于 `[app descendantsMatchingType:XCUIElementTypeStaticText]`。XCUIElementTypeStaticText 参数是枚举类型。 + + ```objective-c + typedef NS_ENUM(NSUInteger, XCUIElementType) { + XCUIElementTypeAny = 0, + XCUIElementTypeOther = 1, + XCUIElementTypeApplication = 2, + XCUIElementTypeGroup = 3, + XCUIElementTypeWindow = 4, + XCUIElementTypeSheet = 5, + XCUIElementTypeDrawer = 6, + XCUIElementTypeAlert = 7, + XCUIElementTypeDialog = 8, + XCUIElementTypeButton = 9, + XCUIElementTypeRadioButton = 10, + XCUIElementTypeRadioGroup = 11, + XCUIElementTypeCheckBox = 12, + XCUIElementTypeDisclosureTriangle = 13, + XCUIElementTypePopUpButton = 14, + XCUIElementTypeComboBox = 15, + XCUIElementTypeMenuButton = 16, + XCUIElementTypeToolbarButton = 17, + XCUIElementTypePopover = 18, + XCUIElementTypeKeyboard = 19, + XCUIElementTypeKey = 20, + XCUIElementTypeNavigationBar = 21, + XCUIElementTypeTabBar = 22, + XCUIElementTypeTabGroup = 23, + XCUIElementTypeToolbar = 24, + XCUIElementTypeStatusBar = 25, + XCUIElementTypeTable = 26, + XCUIElementTypeTableRow = 27, + XCUIElementTypeTableColumn = 28, + XCUIElementTypeOutline = 29, + XCUIElementTypeOutlineRow = 30, + XCUIElementTypeBrowser = 31, + XCUIElementTypeCollectionView = 32, + XCUIElementTypeSlider = 33, + XCUIElementTypePageIndicator = 34, + XCUIElementTypeProgressIndicator = 35, + XCUIElementTypeActivityIndicator = 36, + XCUIElementTypeSegmentedControl = 37, + XCUIElementTypePicker = 38, + XCUIElementTypePickerWheel = 39, + XCUIElementTypeSwitch = 40, + XCUIElementTypeToggle = 41, + XCUIElementTypeLink = 42, + XCUIElementTypeImage = 43, + XCUIElementTypeIcon = 44, + XCUIElementTypeSearchField = 45, + XCUIElementTypeScrollView = 46, + XCUIElementTypeScrollBar = 47, + XCUIElementTypeStaticText = 48, + XCUIElementTypeTextField = 49, + XCUIElementTypeSecureTextField = 50, + XCUIElementTypeDatePicker = 51, + XCUIElementTypeTextView = 52, + XCUIElementTypeMenu = 53, + XCUIElementTypeMenuItem = 54, + XCUIElementTypeMenuBar = 55, + XCUIElementTypeMenuBarItem = 56, + XCUIElementTypeMap = 57, + XCUIElementTypeWebView = 58, + XCUIElementTypeIncrementArrow = 59, + XCUIElementTypeDecrementArrow = 60, + XCUIElementTypeTimeline = 61, + XCUIElementTypeRatingIndicator = 62, + XCUIElementTypeValueIndicator = 63, + XCUIElementTypeSplitGroup = 64, + XCUIElementTypeSplitter = 65, + XCUIElementTypeRelevanceIndicator = 66, + XCUIElementTypeColorWell = 67, + XCUIElementTypeHelpTag = 68, + XCUIElementTypeMatte = 69, + XCUIElementTypeDockItem = 70, + XCUIElementTypeRuler = 71, + XCUIElementTypeRulerMarker = 72, + XCUIElementTypeGrid = 73, + XCUIElementTypeLevelIndicator = 74, + XCUIElementTypeCell = 75, + XCUIElementTypeLayoutArea = 76, + XCUIElementTypeLayoutItem = 77, + XCUIElementTypeHandle = 78, + XCUIElementTypeStepper = 79, + XCUIElementTypeTab = 80, + XCUIElementTypeTouchBar = 81, + XCUIElementTypeStatusItem = 82, + }; + ``` + +- 通过 `XCUIApplication` 实例化对象调用 `descendantsMatchingType:` 方法得到的是 `XCUIElementQuery` 类型。比如 `@property (readonly, copy*) XCUIElementQuery *staticTexts;` + + ```objective-c + /*! Returns a query for all descendants of the element matching the specified type. */ + - (XCUIElementQuery *)descendantsMatchingType:(XCUIElementType)type; + ``` + +- `descendantsMatchingType` 返回所有后代的类型匹配对象。`childrenMatchingType` 返回当前层级子元素的类型匹配对象 + + ```objective-c + /*! Returns a query for direct children of the element matching the specified type. */ + - (XCUIElementQuery *)childrenMatchingType:(XCUIElementType)type; + + ``` + +- 拿到 `XCUIElementQuery` 后不能直接拿到 `XCUIElement`。和 `XCUIApplication` 类似,`XCUIElement` 不能直接访问 UI 元素,它是 UI 元素在测试框架中的代理。可以通过 `Accessibility` 中的 `frame`、`identifier` 来获取。 + + + +对比很多自动化测试框架都需要找出 UI 元素,也就是借助于 `Accessibility` 的 `identifier`。这里的唯一标识生成对比[为 UIAutomation 添加自动化测试标签的探索](http://yulingtianxia.com/blog/2016/03/28/Add-UITest-Label-for-UIAutomation/)] + + + +第三方 UI 自动化测试框架挺多的,可以查看下典型的 [appium](https://github.com/appium/appium)、[macaca](https://github.com/alibaba/macaca)。 + ## 七、 测试经验总结 - - - - -1. 背景 -2. 软件测试的概念、分类 -3. 本文主要想讲的测试划分。 - -- 每个类具有什么属性、具有什么方法都是确定的,所以拿 Objective-C 举例子,`.h` 中会有公有的属性以及方法,`.m` 中一般是私有属性和私有方法、公有方法。类的行为设计为方法,写代码之前我们一般需要做到心中有数,一个功能需要几个类、每个类的属性和方法分别是什么,需要暴露什么属性和接口。**UML图** 不是必须要画,但是需要胸有成竹。针对一个类在测试的时候 `.m` 文件中的私有方法没有办法在 Unit Test 类中访问,一般可以将需要测试的类增加分类。在分类的 `.h` 文件中将方法进行声明。在测试的 Uint Test 中引入分类头文件。下面举例子 - -```Objective-C -// Person.h - -- (void)eat; - -// Person.m - -- (void)eat -{ - NSLog(@"eat"); -} - -- (vood)sleep -{ - NSLog(@"sleep"); -} - -// Person+UnitTestHelper.h - -- (void)sleep; -``` - -另一种思路是没必要针对每个类的私有方法或者每个方法进行测试,因为等全部功能做完后针对每个类的接口测试,一般会覆盖据大多数的方法。等测试完看如果方法未被覆盖,则针对性的补充 Unit Test +TDD 写好测试再写业务代码,BDD 先写实现代码,再写基于行为的测试代码。另一种思路是没必要针对每个类的私有方法或者每个方法进行测试,因为等全部功能做完后针对每个类的接口测试,一般会覆盖据大多数的方法。等测试完看如果方法未被覆盖,则针对性的补充 `Unit Test`。 目前,UI 测试(appium) 还是建议在核心逻辑且长时间没有改动的情况下去做,这样子每次发版本的时候可以当作核心逻辑回归了,目前来看价值是方便后续的迭代和维护上有一些便利性。其他的功能性测试还是走 BDD。 -对于类、函数、方法的走 TDD,老老实实写 UT、走 UT 覆盖率的把控 +对于类、函数、方法的走 TDD,老老实实写 UT、走 UT 覆盖率的把控。 -> 目前,UITesting 还是建议在核心逻辑且长时间没有改动的情况下去做,这样子每次发版本的时候可以当作核心逻辑回归了,目前来看价值是方便后续的迭代和维护上有一些便利性。例如之前我们分享SDK升级微信和QQSDK,以便支持 universal link 功能,当时有了UITesing,基本上免去了测试人员介入。 +UITesting 还是建议在核心逻辑且长时间没有改动的情况下去做,这样子每次发版本的时候可以当作核心逻辑回归,目前来看价值是方便后续的迭代和维护上有一些便利性。例如用户中心 SDK 升级后,当时有了UITesing,基本上免去了测试人员介入。 -> 如果是一些活动页和逻辑经常变动的,老老实实走测试黑盒... +如果是一些活动页和逻辑经常变动的,老老实实走测试黑盒... -> 我觉得一直有个误区,就是觉得自动测试是为了质量,其实质量都是附送的,测试先行是让开发更快更爽的 +我觉得一直有个误区,就是觉得自动测试是为了质量,其实质量都是附送的,测试先行是让开发更快更爽的 -> appium 但是后来他自己也说 在iOS平台好像不是很好搞 能做的事情挺少的 +![测试占比](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-07-14-TestingPercentage.png) -> 投入产出比是不高 那你试试monkey test - -> wwdc上这张图也很清楚,UI其实需要的占比很小的,还是要靠单测驱动 - -> 当时我找个UITest的bug都花了不少力气 - -> UTTest主要测逻辑的 - -> UITest可以测你页面渲染的对不对、按钮点击是否有问题 - -不过 macaca appium 都可以做到iOS自动化 +WWDC 这张图也很清楚,UI 其实需要的占比较小,还是要靠单测驱动。 diff --git a/Chapter1 - iOS/1.80.md b/Chapter1 - iOS/1.80.md index c8347eb..e69de29 100644 --- a/Chapter1 - iOS/1.80.md +++ b/Chapter1 - iOS/1.80.md @@ -1,2 +0,0 @@ -# 打造一个通用、可配置、多句柄的数据上报 SDK - diff --git a/assets/2020-07-14-TestingPercentage.png b/assets/2020-07-14-TestingPercentage.png new file mode 100644 index 0000000..d5c83d6 Binary files /dev/null and b/assets/2020-07-14-TestingPercentage.png differ diff --git a/assets/2020-07-15-XcodeUITesting.png b/assets/2020-07-15-XcodeUITesting.png new file mode 100644 index 0000000..35e36a2 Binary files /dev/null and b/assets/2020-07-15-XcodeUITesting.png differ