胡锦涛_Steven 阅读(15) 评论(0)

一般来说,测试是发布之前的最后一道关卡。如果代码不能在测试中发现,那么BUG就会抵达用户,所以测试的完整性和可靠想十分重要。目前,大多数App 还停留在人工测试的阶段,但测试人员不会写代码,在很多测试场景下,人工测试的效率太低,容易出错。例如:

1>一个App的核心功能,在每一次发布版本前的测试必定会跑一边所有到测试用例,不管对应的版本在当前版本有没有变化,如果这次测出新的BUG,测试人员在下一次发版本测试的时候,又不得不做这些重复的操作。

2>开发在写API请求相关代码的时候没有做数据容错,测试在人工测试的时候都是正常的数据,所以测试通过。上线了之后,后台配置数据的时候出了点小问题,导致大面积崩溃,Crash

 

自动化测试

自动化测试就是写一些测试代码,用代码代替人工去完成模块和业务的测试。(自动编译代码TDD测试驱动代码)

自动化测试有很多优点:

     测试速度快,避免重复性的工作。

     避免regression(回归),让开发更有信心去修改和重构代码

     有了自动化测试,持续集成(CI)会变得更可可靠

     迫使开发人员写出更高质量的代码。(自动化测试不通过,代码不允许合并)

自动化测试也有一些缺点:

      开发和维护成本高;

      不能完全替代人工测试;

      无法完全保证测试的准确性 - 让代码去判断一段逻辑是否正确很容易,但是,让代码判断一个控件显示是否正确却没那么容易。

/*
在做自动化测试之前,首先要问自己几个问题?
这个测试业务的变动是否频繁?
这个测试业务是否属于核心功能?
编写测试代码的成本有多少?
自动化测试能保证测试结果的准确么?
通常,我们会选择那些业务稳定,需要频繁测试的部分来编写自动化测试脚本,其余的采用人工测试,人工测试仍然是iOS App开发中不可缺少的一部分。
*/

UI测试:UI测试是模拟用户操作,进而从业务处层面测试。

关于UI测试,有几个核心类需要掌握

XCUIApplication :测试应用代理  https://developer.apple.com/documentation/xctest/xcuiapplication

XCUIElement :一个UI上课件的视图对象 https://developer.apple.com/documentation/xctest/xcuielement

XCUIElementQuery:查找XCUIElement https://developer.apple.com/documentation/xctest/xcuielementquery

UI测试还有一个核心功能是UI Recording

选中一个UI测试用例,然后点击图中的小红点既可以开始UI Recoding。你会发现

随着点击模拟器,自动合成了测试代码。(通常自动合成代码后,还需要手动的去调整)

点击小红点即可自动编译-生成代码

 

在写UI测试用例的时候要注意:测试行为而不是测试代码.

对应测试代码如下:

- (void)setUp {
    [super setUp];
    self.continueAfterFailure = NO;
    [[[XCUIApplication alloc] init] launch];
}
- (void)tearDown {
    [super tearDown];
}
- (void)testLogin{

    //XCUIApplication --> application
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [[[XCUIApplication alloc] init].buttons[@"Login"] tap];
    XCUIElement *selfElement = [[[[app.otherElements containingType:XCUIElementTypeNavigationBar identifier:@"login"] childrenMatchingType:XCUIElementTypeOther].element childrenMatchingType:XCUIElementTypeOther].element childrenMatchingType:XCUIElementTypeOther].element;
    
    //XCUIElementTypeTextField
    XCUIElementQuery *textFiledQ = [selfElement childrenMatchingType:XCUIElementTypeTextField];
    //UI 元素
    XCUIElement *accountE = [textFiledQ elementBoundByIndex:0];
    XCUIElement *passwordE = [textFiledQ elementBoundByIndex:1];

    //Query -> 元素
    //XCUIElementTypeButton
    XCUIElementQuery *buttonQ = [selfElement childrenMatchingType:XCUIElementTypeButton];
    XCUIElement *loginE = [buttonQ elementBoundByIndex:0];

    //输入账号
    [accountE tap];
    // value attribute
    [accountE typeText:@"123456"];
    //输入密码
    [passwordE tap];
    [passwordE typeText:@"12345"];
    //删除
    XCUIElement *key_delete = app.keys[@"delete"];
    [key_delete doubleTap];
    //点击登录
    [loginE tap];
    

}

运行效果如下图所示:

补充列举一些常用的断言

XCTFail(format…) 生成一个失败的测试;

XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;

XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;

XCTAssert(expression, format...)当expression求值为TRUE时通过;

XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;

XCTAssertFalse(expression, format...)当expression求值为False时通过;

XCTAssertEqualObjects(a1, a2, format...)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;

XCTAssertNotEqualObjects(a1, a2, format...)判断不等,[a1 isEqual:a2]值为False时通过,

XCTAssertEqual(a1, a2, format...)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用,实际测试发现NSString也可以);

XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;

XCTAssertThrows(expression, format...)异常测试,当expression发生异常时通过;反之不通过;(很变态)

XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;

XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过