XCTest

iOS自动化单元测试示例

  • Owner: wangzhengang/XCTest
  • Platform:
  • License:: MIT License
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

XCTest

iOS自动化单元测试示例

一、前言:

UITest的单元测试能最大限度的解放测试妹妹的双手,当然也会给程序员带来巨大工作量,完整的测试代码估计是项目代码的两倍,另外大家可以自行百度 Xcode Coverage 查看测试代码覆盖率,这篇文章只讲如何在工程中用XCTest框架做单元测试。
其中主要介绍了,用六个按钮示意的UITests使用和性能测试、异步测试的。

二、创建工程:

先创建个名字为 XCTest 的示例工程:
这里写图片描述
这里要说明一下如果当初创建工程时未勾选上Include Unit TestsInclude UI Test 这两个复选框,可在项目工程targets目录下手动创建 Tests 、UITests目标,如下图示例:
这里写图片描述

然后选中“iOS”在搜索框里输入 test ,就能看到 “iOS UITesting Bundle”和 “iOS Unit Testing Bundle”两个图标了,选中后点击“Next”按钮后,就能在 TARGET 目录下看到我们创建的测试项了。

这里写图片描述

三、代码解释:

1、接下来看看具体代码:
我们可以在 XCTests.m XCUITests.m 中发现一些共同的方法:

- (void)setUp {  …  }
- (void)tearDown {  …  }

2、方法的意义:
将要开始执行测试代码时调用: - (void)setUp { … }
测试代码执行完后调用,测试失败不调用: - (void)tearDown { … }
其他任何方法都会在 - (void)setUp- (void)tearDown 调用。
所有的测试类类名都以Tests结尾,同样类中所有的测试方法也都以- (void)test 开头。

3、获取app启动对象:

[[[XCUIApplication alloc] init] launch];///为app对象分配内存并启动它

4、其他:
UI测试示例代码:

XCUIElement *button1 = [[XCUIApplication alloc] init].buttons[@"1111"];///获取名字为2222的按钮
    XCTAssertTrue(button1.exists, @"'1111'按钮存在");///#值为true才能通过,为false会停在这里
    [button1 tap];///触发按钮的点击事件

性能测试示例代码:

    NSLog(@"性能测试");
    [self measureBlock:^{  ///#用来分析代码执行的时间,log会打印在 console 里,同时本地也会有一份日志
        //实例化测试对象
        ///#测试那个类里的方法就要引入那个类
        ViewController *vc = [[ViewController alloc] init];
        //#调用测试方法获取测试结果
        [vc performanceExample];
    }];


异步测试示例代码:
注意其中的“执行顺序1、2、3、4”

 XCTestExpectation *expectation = [self expectationWithDescription:@"百度翻译 测试"];
    NSLog(@"执行顺序:1");
    ///请求参数
    NSMutableDictionary *paramer = [NSMutableDictionary dictionary];
    [paramer setValue:@"apple"  forKey:@"q"];
    [paramer setValue:@"en"     forKey:@"from"];
    [paramer setValue:@"zh"     forKey:@"to"];
    [paramer setValue:@"2015063000000001"   forKey:@"appid"];
    [paramer setValue:@"1435660288"         forKey:@"salt"];
    [paramer setValue:@"f89f9594663708c1605f3d736d01d2d4"     forKey:@"sign"];
    ///开始请求
    [ViewController networkRequestWithAPI:@"https://api.fanyi.baidu.com/api/trans/vip/translate" requestMethod:@"POST" cachePolicy:NSURLRequestUseProtocolCachePolicy requestParamer:paramer Completion:^(NSDictionary * _Nullable result, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        [expectation fulfill];///调用fulfill后 waitForExpectationsWithTimeout 会结束等待
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        XCTAssertTrue(httpResponse.statusCode==200, @"接口请求成功");///200表明http请求成功,请求失败会停在这里
        XCTAssertNotNil(result, @"json 对象不为空");///result结果为nil,会停在这里
        XCTAssertNil(error, @"请求没有出错");//error 不为nil,会停在这里
        NSLog(@"执行顺序:3");
    }];
    NSLog(@"执行顺序:2");
    ///因为接口设置的是30秒超时,所以这里也设置30秒,意思就是这个线程最多等待30秒,
    [self waitForExpectationsWithTimeout:30.f handler:^(NSError * _Nullable error) {
        NSLog(@"执行顺序:4");
        if (error) {
            ///测试代码无异常
        } else {
            ///测试代码有异常
        }
    }];

这里写图片描述

这里写图片描述

这里写图片描述

四、图标解释:

1、测试前的图标:
这里写图片描述 这个图标出现在所有以 - (void)test 开头的方法前,这个是将要开始测试前的按钮状态图标,一旦点击就开始测试这个方法里的内容,或者我们也可以通过 command+U 的快捷键启动完整测试,完整测试会执行 Tests 和 UITests 下所有的测试类和类中所有的测试方法。

2、测试成功图标:
这里写图片描述
绿色代表测试成功,同时xcode 也会弹框提示,
这里写图片描述

3、测试失败:
这里写图片描述
表示某个测试方法测试失败,同时进程也会停在测试未通过的代码那。
这里写图片描述

4、录制代码:
XCode为了方便我们进行自动化单元测试真是费劲了心思,当我们把鼠标光标放到 -(void)testXXX {....} 这种测试方法里后,能在XCode的工具条上看到红色的按钮,这个红色的按钮就是用来录制代码。我们点击这个红色按钮后就会开始录制代码,我们在app里做任何操作都会在这里产生测试代码。
这里写图片描述
app越复杂,录制代码时对电脑性能消耗就越高,一般8个G内存的苹果电脑都很卡,甚至会让 XCode 崩溃掉。我觉得录制代码只适合帮助我们寻找app页面上某个按钮或者其他view,而关于这个按钮或view的其他测试代码,需要我们手动去写。

五、断言注释:

XCTFail(format…) //生成一个失败的测试;
 XCTFail(@”Fail”);

 XCTAssertNil(a1, format…) //为空判断, a1 为空时通过,反之不通过;
 XCTAssertNil(@”not nil string”, @”string must be nil”);

 XCTAssertNotNil(a1, format…) //不为空判断,a1不为空时通过,反之不通过;
 XCTAssertNotNil(@”not nil string”, @”string can not be nil”);

 XCTAssert(expression, format…) //当expression求值为TRUE时通过;
 XCTAssert((2 > 2), @”expression must be true”);

 XCTAssertTrue(expression, format…) //当expression求值为TRUE时通过;
 XCTAssertTrue(1, @”Can not be zero”);

 XCTAssertFalse(expression, format…) //当expression求值为False时通过;
 XCTAssertFalse((2 < 2), @”expression must be false”);

 XCTAssertEqualObjects(a1, a2, format…) //判断相等, [a1 isEqual:a2] 值为TRUE时通过,其中一个不为空时,不通过;
 XCTAssertEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return YES”);
 XCTAssertEqualObjects(@”1″, @”2″, @”[a1 isEqual:a2] should return YES”);

 XCTAssertNotEqualObjects(a1, a2, format…) //判断不等, [a1 isEqual:a2] 值为False时通过,
 XCTAssertNotEqualObjects(@”1″, @”1″, @”[a1 isEqual:a2] should return NO”);
 XCTAssertNotEqualObjects(@”1″, @”2″, @”[a1 isEqual:a2] should return NO”);

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

 XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…) 判断相等,(double或float类型)//提供一个误差范围,当在误差范围(+/- accuracy )以内相等时通过测试;
 XCTAssertEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return YES”);

 XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…) 判断不等,(double或float类型)//提供一个误差范围,当在误差范围以内不等时通过测试;
 XCTAssertNotEqualWithAccuracy(1.0f, 1.5f, 0.25f, @”a1 = a2 in accuracy should return NO”);

 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没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;


 //下面介绍一下测试元素的语法

 XCUIApplication:
 //继承XCUIElement,这个类掌管应用程序的生命周期,里面包含两个主要方法
 launch():
 //启动程序
 terminate()
 //终止程序

 XCUIElement
 //继承NSObject,实现协议XCUIElementAttributes, XCUIElementTypeQueryProvider
 //可以表示系统的各种UI元素
 .exist
 //可以让你判断当前的UI元素是否存在,如果对一个不存在的元素进行操作,会导致测试组件抛出异常并中断测试
 descendantsMatchingType(type:XCUIElementType)->XCUIElementQuery
 //取某种类型的元素以及它的子类集合
 childrenMatchingType(type:XCUIElementType)->XCUIElementQuery
 //取某种类型的元素集合,不包含它的子类

 //这两个方法的区别在于,你仅使用系统的UIButton时,用childrenMatchingType就可以了,如果你还希望查询自己定义的子Button,就要用descendantsMatchingType

 //另外UI元素还有一些交互方法
 tap()
 //点击
 doubleTap()
 //双击
 pressForDuration(duration: NSTimeInterval)
 //长按一段时间,在你需要进行延时操作时,这个就派上用场了
 swipeUp()
 //这个响应不了pan手势,暂时没发现能用在什么地方,也可能是beta版的bug,先不解释
 typeText(text: String)
 //用于textField和textView输入文本时使用,使用前要确保文本框获得输入焦点,可以使用tap()函数使其获得焦点

 XCUIElementAttributes协议
 //里面包含了UIAccessibility中的部分属性

五、结尾:##

如果大家觉得这篇文章和示例工程代码有用的话,点个赞,在github 上给个小星星,多谢。
博客地址:http://blog.csdn.net/zhengang007/

Main metrics

Overview
Name With Ownerwangzhengang/XCTest
Primary LanguageObjective-C
Program languageObjective-C (Language Count: 1)
Platform
License:MIT License
所有者活动
Created At2017-11-25 04:40:30
Pushed At2017-11-28 08:24:29
Last Commit At2017-11-28 16:24:29
Release Count0
用户参与
Stargazers Count50
Watchers Count0
Fork Count10
Commits Count8
Has Issues Enabled
Issues Count2
Issue Open Count2
Pull Requests Count0
Pull Requests Open Count1
Pull Requests Close Count0
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private