iOS 单元测试 Tests 和 UITests

一 :前言

此篇文章是我自己探索来的,查看了很多前人写的文章,也看了很多 demo,稍微对此有了一些了解,所以就在此记录一下,此中肯定会有很多不足,请诸位精通单元测试的大佬给予支出,非常感谢

环境

Xcode 13.1

二:简介

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

三: 为什么需要使用 单元测试

1.0 设想你在在一个庞大的工程里面加个了 小功能 A ,按照我们前面的说法,是不是每次都要把工程跑起来,然后 去到 A 处 然后进行测试。甚至如果我们仅仅是想 测试一个 接口 返回的参数 而这个接口又需要使用到现有工程中的很多参数 等 如果使用 单元测试的话 就不用每次去 把整个工程跑起来,只需要跑你测试的部分。

2.0 我们可以使用单元测试测 某个方法的耗时和性能,单次 和 多次运行的整体对比的。当然你可以在 方法执行前 获取时间 ,方法结束 后获取时间等方式 获取时间消耗 姑且这样写 麻烦不说 但是如何 计算 CPU 占用这些消耗呢?当然我们可以使用 instrument 来做更专业的测试。 相对而言 单元测试更加便捷 和 方便使用给我们省不少事。

四:如何做单元测试

本文只介绍 Xcode 自带的 Unit Tests 和 UI Tests

4.1 在新建任何一个 工程时 很多小伙伴 对如下图 所示的 Include Tests (我记得之前是Include Unit Tests 和 Include UI Tests的,应该是 xcode 做了改动) 感到疑惑。


在这里插入图片描述

选择之后会,项目会生成 Tests he UITests 的文件夹以及里面的文件


在这里插入图片描述

当前,你也可以后续新建,或新增这种测试文件
在这里插入图片描述

五: 断言

说起 测试,就要先了解断言,下面列出一些常用的断言

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

六: Tests

6.1 测试方法

打开 Tests.m、或者 UITests.m 文件 ,如下图所示 鼠标光标选中菱形区域 就会 显示这个播放的状态,然后 点击 这个播放的状态 就会测试这个方法。 或者 选择左边 testDate右边也会出现 黑色的小播放按钮 点击也可以测试。
下面标注的有测试失败、成功的例子
注:自己写测试方法,要以 test 开头,无论 oc 还是 swift,否则不会出现菱形图标,没法进行测试


在这里插入图片描述

6.2 开始测试

6.2.1 测试自己写的方法

//测试 NSDate
- (void)testDate {
    NSDate * date = [NSDate new];
    NSString * nowTime = [date dateStringWithDateFormat:@"YYYY-MM-dd HH:mm:sszzz"];
    NSLog(@"当前时间:%@", nowTime);
    XCTAssertNotNil(nowTime, @"数据不能为空");
}
//设备信息
- (void)testDevice {  
    NSString * device_system_name = [HCDevice shared].device_system_name;
    NSLog(@"设备系统名称:%@", device_system_name);
    XCTAssertNotNil(device_system_name, @"设备系统名称不能为空"); 
}

6.2.2 测试网络请求

等待测试语句

//waitForExpectationsWithTimeout是等待时间,超过了就不再等待往下执行。
#define WAIT do {\
[self expectationForNotification:@"RSBaseTest" object:nil handler:nil];\
[self waitForExpectationsWithTimeout:30 handler:nil];\
} while (0);

#define NOTIFY \
[[NSNotificationCenter defaultCenter]postNotificationName:@"RSBaseTest" object:nil];
- (void)testNetwork {
    NSDictionary * parameters = @{@"type": @"1",
                                  @"page": @"1",
    };
    NSString * url = @"https://apitwo.tupian.ltd/index.php/api/index/rankingList";
    [[HQJNetwork shared] request:POST setUrl:url
                  setParameters:parameters
                      setFinish:^(HTTPResult type, id  _Nonnull response, NSString * _Nonnull message) {
        NSLog(@"%ld \n%@ \n%@", type, response, message);
        if (type == HTTPResultSuccess) {
             
        }
        NOTIFY
    }];
    WAIT
}

6.2.3测试弹窗

//测试  弹窗
- (void)testAlert {
    [HCAlertBottomView showMessage:@"message" setDelete:@"删除" setCancel:@"取消" completion:^(BOOL result) {
        
        NOTIFY //继续执行
    }];
    WAIT  //暂停   超出暂停时间会报错
}

这点我有点不理解,像弹窗不应该放到 UITests 里面测试吗?但是我放到 UITests 里面一直报错,希望有大佬看到给予解答,下面是放到 UITests 报错信息,同样的代码,我是从 Tests 里面完全复制来的
在这里插入图片描述

在这里插入图片描述

上面问题先忽略,因为并没有影响我做测试

七:UITests

这块是借鉴了iOS 单元测试(Unit Test 和 UI Test),感谢大佬的文章和 demo
关于这块的疑问: 像 app.buttons[@"登录"], app.textFields[@"请输入密码"],如果代码中有多个,他怎么识别呢? 下面是我的解决方式,也不知道对不对,期待大佬的解答
我这边做的处理,做那块的 UI 测试,代码在模拟器上运行之后(保持最新代码),关闭,重新再模拟器上打开,点击进入到该页面,然后运行测试,会自动进行填充数据,点击按钮

此处突然出现问题,进入到该页面启动不了,运行测试代码还是 app重新运行,除非测试内容在启动的第一个页面才能进行测试,求大佬给予技术支持!(如果在APP启动第一个页面,下面方法没有问题,问题解决中。。。未完待续 )

关于 UITest 有更加详细的介绍文字:UI Tests 自动化测试

7.1 模拟登录

如果secureTextEntry设置为 YES,textFields 会识别不到
self.textField.secureTextEntry = YES;

- (void)testlogin {
    XCUIApplication *app = [[XCUIApplication alloc] init];
    
    for (NSInteger i = 0;i < app.textFields.count; i++) {
        XCUIElement * textField = [app.textFields elementBoundByIndex:i];
        if ([textField exists]) {//判断是否存在
            NSString * placeholder =  [textField placeholderValue]; 
            if ([placeholder isEqualToString:@"请输入手机账号"]) {
                [textField tap];
                [textField typeText:@"12345678910"];
            }
            if ([placeholder isEqualToString:@"请输入验证码"]) {
                [textField tap];
                [textField typeText:@"1234"];
            } 
            if ([placeholder isEqualToString:@"请输入密码"]) {
                [textField tap];
                [textField typeText:@"66666"];
            }
            if ([placeholder isEqualToString:@"请再次输入密码"]) {
                [textField tap];
                [textField typeText:@"66666"];
            }
        }
    } 
    XCUIElement * buttonLogin = app.buttons[@"登录"];
    if ([buttonLogin exists]) {
        [buttonLogin tap];
    }
}

此篇文章是做记录使用,刚刚开始搞这个东西,后续会继续补充,
各位大佬如果有建议,请给与提出,非常感谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容