iOS-单元测试汇总

作者 : 开心源码 本文共13828个字,预计阅读时间需要35分钟 发布时间: 2022-05-12 共256人阅读
前言:

对于单元测试来说,我想大部分同行,在项目中,很少会用到,也有一大部分,知道单元测试这个东西,但是确切的说没有尝试过,也不知道怎样回事,我想写篇文章总结一下,理解一下单元测试。我也志在学习一下单元测试。假如触碰到什么误区,希望大家多多提示,帮助,谢谢。

我看了几篇单元测试的文章,其中写到单元测试多数用于:

1.调试接口能否正常使用。比方要测试一个网络接口,通常每次都要重新启动,经过繁复的操作之后,才能测试到网络接口。要是用单元测试,即可以直接测试那个方法,相对方便很多。

2.比方因为修改较多,想测试分享功能能否正常,(而不是重新启动程序,进入到分享界面,点击分享,填写分享内容。),在单元测试通过了,直接用到相应的地方。

3.自动发布、自动测试(特别在少量大的项目,以防止程序被误改或者引起新的问题)。
4.客户注册/登陆等

理解一下单元测试:

单元测试(Unit Testing)又称为板块测试,是针对程序板块软件设计来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。对于面向对象编程,最小单元就是方法,包括基类、笼统类、或者者派生类中的方法。

通常来说,程序员每修改一次代码就会修改某个单元,那我们即可以对这个单元做修改的验证(单元测试),在编写程序的过程中前后很可能要进行屡次单元测试,以证明程序达到软件规格书(产品需求)要求的工作目标,而且没有程序错误。

每个理想的测试案例独立于其它case,测试时需隔离板块。单元测试通常由软件开发人员编写,用于确保所写的代码匹配软件需求和遵循开发目标。它的实施方式可以是手动的,或者是构建自动化的一部分。

单元测试允许程序员在未来重构代码,且确保板块仍然工作正确。这个过程是为所有方法编写单元测试,一旦变更导致错误发生,借助于单元测试可以快速定位并修复错误。

可读性强的单元测试可以使程序员方便地检查代码片断能否仍然正常工作。良好设计的单元测试案例覆盖程序单元分支和循环条件的所有路径。在连续的单元测试环境,通过其固有的持续维护工作,单元测试可以延续用于精确反映当任何变更发生时可执行程序和代码的体现。借助于上述开发实践和单元测试的覆盖,可以总是维持精确性。

理解一下单元测试目的:
  1. 保证代码的质量 (帮助你编写高质量代码、减少bu)

代码可以通过编译器检查语法的正确性,却不能保证代码逻辑是正确的,尤其包含了许多单元分支的情况下,单元测试可以保证代码的行为和结果与我们的预期和需求一致。在测试某段代码的行为能否和你的期望一致时,你需要确认,在任何情况下,这段代码能否都和你的期望一致,譬如参数可能为空,可能的异步操作等。

有一部分bug的起因是开发人员在编写工作代码的时候没有考虑到某些case或者者边际条件。造成这种问题的起因很多,其中很重要的一个起因是我们对工作代码所要完成的功能思考不足,而编写单元测试,特别是先写单元测试再写工作代码即可以帮助开发人员思考编写的代码究竟要实现哪些功能。例照实现一个简单的客户注册功能的业务类方法,用单元测试再写工作代码的方式来工作的话开发人员就会先考虑各种场景相关,例如正常注册、客户名重复、没有满足必要的填写内容……等等,之后就会编写相关的测试用例。编写单元测试代码的过程就是促使开发人员思考工作代码实现内容和逻辑的过程,之后实现工作代码的时候,开发人员思路会更清晰,实现代码的质量也会有相应的提升。

  1. 保证代码的可维护性 (提升代码的反馈速度,减少重复工作,保证你最后的代码修改不会破坏之前代码的功能)

保证原有单元测试正确的情况下,无论如何修改单元内部代码,测试的结果应该是正确的,且修改后不会影响到其余的板块。

开发人员实现某个功能或者者修补了某个bug,假如有相应的单元测试支持的话,开发人员可以马上通过运行单元测试来验证之前完成的代码能否正确,而不需要反复通过编译运行simulator、等待应用启动、通过输入数据等繁琐的步骤来验证所完成的功能。用单元测试代码来验证代码和通过发布应用以人工的方式来验证代码这两者的效率差很多,所以单元测试其实还能节约人力成本。

项目越做越大,代码越来越多,特别涉及到少量公用接口之类的代码或者是底层的基础库,谁也不敢保证这次修改的代码不会破坏之前的功能,所以与此相关的需求会被搁置或者延迟,因为不敢改进代码,代码也变得越来越难以维护,质量也越来越差。而单元测试就是处理这种问题的很好方法(不敢说最好的)。因为代码的历史功能都有相应的单元测试保证,修改了某些代码以后,通过运行相关的单元测试即可以验证出新调整的功能能否有影响到之前的功能。当然要实现到这种程度需要很大的付出,不但要能够达到比较高的测试覆盖率,而且单元测试代码的编写质量也要有保证。

  1. 保证代码的可扩展性

为了保证可行的可持续的单元测试,程序单元应该是低耦合的,否则,单元测试将难以进行,说明代码的依赖性很高。

理解一下单元测试的本质:
  1. 是一种验证行为

单元测试在开发前期检验了代码逻辑的正确性,开发后期,无论是修改代码内部抑或者重构,测试的结果为这一切提供了可量化的保障。

  1. 是一种设计行为

为了可进行单元测试,尤其是先写单元测试(TDD),我们将从调用者思考,从接口上思考,我们必需把程序单元设计成接口功能划分清晰的,易于测试的,且与外部板块耦合性尽可能小。

  1. 是一种快速回归的方式

在原代码基础上开发及修改功能时,单元测试是一种快捷,可靠的回归。

除了那些大拿们编写的代码,我相信很多易于维护、设计良好的代码都是通过不断的重构才得到的。尽管说单元测试本身不能直接改进生产代码的质量,但它为生产代码提供了“安全网”,让开发人员可以勇敢地改进代码,从而让代码的clean和beautiful不再是梦想。

  1. 是程序优良的文档

从效果上而言,单元测试就像是能执行的文档,说明了在你用各种条件调用代码时,你所能期望这段代码完成的功能。

因为给代码写很多单元测试,相当于给代码加上了规格说明书,开发人员通过读单元测试代码也能够帮助开发人员了解现有代码。很有Open Source的项目(如,AFNetworking, FMDB,喵神的VVDoucment等)都有相当量的单元测试代码,通过读这些测试代码会有助于了解生产源代码。

两种测试思想

??测试驱动开发(Test-driven development,TDD)是一种软件开发过程中的应用方法,由极限编程中倡导,以其倡导先写测试程序,而后编码实现其功能得名。测试驱动开发是戴两顶帽子思考的开发方式:先戴上实现功能的帽子,在测试的辅助下,快速实现其功能;再戴上重构的帽子,在测试的保护下,通过去除冗余的代码,提高代码质量。测试驱动着整个开发过程:首先,驱动代码的设计和功能的实现;其后,驱动代码的再设计和重构。

行为驱动开发(Behavior-driven development,BDD)是一种敏捷软件开发的技术,BDD的重点是通过与利益相关者的探讨获得对预期的软件行为的清醒认识。它通过用自然语言书写非程序员可读的测试用例扩展了 测试驱动开发方法(TDD)。这让开发者得以把精力集中在代码应该怎样写,而不是技术细节上,而且也最大程度的减少了将代码编写者的技术语言与商业用户、客户、利益相关者、项目管理者等的领域语言之间来回翻译的代价。

在iOS单元测试框架中,kiwi是BDD的代表。

详情

OCUnit即可使用XCTest进行测试)其实就是苹果自带的测试框架。

GHUnit是一个可视化的测试框架。
有了它,你可以点击APP来决定测试哪个方法,并且可以点击查看测试结果等。

OCMock就是模拟某个方法或者者属性的返回值,你可能会疑惑为什么要这样做?使用用模型生成的模型对象,再传进去不即可以了?答案是可以的,但是有特殊的情况。比方你测试的是方法A,方法A里面调用到了方法B,而且方法B是有参数传入,但又不是方法A所提供。这时候,你可以使用OCMock来模拟方法B返回的值。(在不影响测试的情况下,即可以这样去模拟。)除了这些,在没有网络的情况下,也可以通过OCMock模拟返回的数据。

UITests就是通过代码化来实现自动点击界面,输入文字等功能。靠人工操作的方式来覆盖所有测试用例是非常困难的,尤其是加入新功能以后,旧的功能也要重新测试一遍,这导致了测试需要花非常多的时间来进行回归测试,这里产生了大量重复的工作,而这些重复的工作有些是可以自动完成的,这时候UITests即可以帮助处理这个问题了。

案例 1
简单的单元测试

1-1 创立一个新的项目

Snip20180619_12.png

1-2点开测试文件,进入到这个类

setUp       :每个测试方法调用前执行tearDown    :每个测试方法调用后执行testExample :是测试方法,和我们新建的没有差别。              测试方法必需testXXX的格式,且不能有参数,不然不会识别为测试方法  测试方法的执行顺序: 字典序排序。快捷键:Command + U进行单元测试,这个快捷键是一律测试。

image.png

1-3在testExample方法中输入如下:

NSLog(@"自己设置测试testExample");int  a= 3;XCTAssertTrue(a == 0,"a 不能等于 0");


备注:红色的叉子:代表测试未通过。绿色叉子:代表测试通过。

案例 2

iOS-Main – 单元测试 &基本体验

案例 3

进行网络请求的测试
使用CocoaPods安装AFNetworking和STAlertView(CocoaPods安装和使用教程 )
Pofile:

platform :ios, '7.0'  target 'UnitTestDemoTests' do    pod 'AFNetworking', '~> 2.5.0'    pod 'STAlertView', '~> 1.0.0' endtarget 'UnitTestDemoTestsTests' do    pod 'AFNetworking', '~> 2.5.0'   pod 'STAlertView', '~> 1.0.0'end

iOS9的http安全问题:现在进行异步请求的网络测试,因为测试方法主线程执行完就会结束,所以需要设置一下,否则没法查看异步返回结果。
也可以在方法结束前设置等待,调回回来的时候再让它继续执行。(另一种异步函数的单元测试)定义宏如下:

//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)testRequest{// 1.取得请求管理者AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",nil];// 2.发送GET请求[mgr GET:@"http://www.weather.com.cn/adat/sk/101110101.html" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {    NSLog(@"responseObject:%@",responseObject);    XCTAssertNotNil(responseObject, @"返回出错");    NOTIFY //继续执行} failure:^(AFHTTPRequestOperation *operation, NSError *error) {    NSLog(@"error:%@",error);    XCTAssertNil(error, @"请求出错");    NOTIFY //继续执行}];WAIT  //暂停}

有时候我们想测试一下整个流程能否可以跑通,比方获取验证码、登录、上传头像,查询个人资料。其实只需输入验证码即可以完成整个测试。这时候就需要用到输入框了,以便程序继续执行。使用了一个第三方的弹出输入框STAlertView,前面已经设置。
STAlertView的使用方法:

- (void)testAlertView { self.stAlertView = [[STAlertView alloc]initWithTitle:@"验证码" message:nil textFieldHint:@"请输入手机验证码" textFieldValue:nil cancelButtonTitle:@"取消" otherButtonTitle:@"确定" cancelButtonBlock:^{   //点击取消返回后执行   [self testAlertViewCancel];   NOTIFY //继续执行} otherButtonBlock:^(NSString *b) {   //点击确定后执行   [self alertViewComfirm:b];   NOTIFY //继续执行 }];[self.stAlertView show]; WAIT //设置等待时间}
案例 4

测试的执行顺序

Snip20180619_1.png
通过上述测试得出结论:
可以看到无论我们怎么调换test方法的书写顺序,其测试顺序都是不变的。
目前初步的结论:测试方法执行的顺序与方法名中test后面的字符大小有关,小者优先,例如testA,testB1,testB2三个方法相继执行。

案例 5

Xcode集成了对单元测试的支持,XCode4.x集成的是OCUnit,到了XCode5.x时代就更新为了XCTest,XCode7.x时代XCtest还可以进行UI测试。下面我们简单详情下XCTest的使用。

在xcode新建项目中,默认会建一个单元测试的target,并建立一个继承于XCTestCase的测试用例类

image.png
?本例实现了一个个税计算方法,在测试用例中测试输入后输出能否符合结果。
创立一个名为ASRevenueBL.h .m文件,如下面所示:

image.png

ASRevenueBL.h

#import <Foundation/Foundation.h>@interface ASRevenueBL : NSObject- (double)calculate:(double)revenue;@end

ASRevenueBL.m

import "ASRevenueBL.h"#define baseNum 3500.0 // 起征点@implementation ASRevenueBL /*  * method:传入收入计算税值  * revenue:收入  */- (double)calculate:(double)revenue {   double tax = 0.0; // 税   // 应纳税所得额 = 工资收入金额 - 各项社会保险费 - 起征点(3500元)   // 应纳税额 = 应纳税所得额 x 税率 - 速算扣除数   double dbTaxRevenue = revenue - baseNum; if(dbTaxRevenue <= 1500){   tax = dbTaxRevenue * 0.03; } else if (dbTaxRevenue > 1500 && dbTaxRevenue <= 4500){   tax = dbTaxRevenue *0.1 -105; } else if (dbTaxRevenue > 4500 && dbTaxRevenue <= 9000){   tax = dbTaxRevenue * 0.2 - 555; }else if (dbTaxRevenue > 9000 && dbTaxRevenue <= 35000) {   tax = dbTaxRevenue * 0.25 - 1005; } else if (dbTaxRevenue > 35000 && dbTaxRevenue <= 55000) {   tax = dbTaxRevenue * 0.3 - 2755; } else if (dbTaxRevenue > 55000 && dbTaxRevenue <= 80000) {   tax = dbTaxRevenue * 0.35 - 5505; } else if (dbTaxRevenue > 80000) {   tax = dbTaxRevenue * 0.45 - 13505;} return tax;}

导入测试方法所在的类的头文件,并创立一个类,在测试方法调用前,初始化类对象,测试完毕后,将对象置nil,其方法测试如下方测试代码:

 #import <XCTest/XCTest.h> #import "ASRevenueBL.h" @interface UnitTestsTwoTests : XCTestCase @property (nonatomic, strong) ASRevenueBL *revenueBL; @end @implementation UnitTestsTwoTests - (void)setUp {     [super setUp];      self.revenueBL = [[ASRevenueBL alloc] init]; } - (void)tearDown {      self.revenueBL = nil;     [super tearDown]; } - (void)testLevel1 {     double revenue = 5000;     double tax = [self.revenueBL calculate:revenue];     XCTAssertEqual(tax, 45.0,@"测试案例1失败");     XCTAssertTrue(tax == 45.0); } - (void)testLevel2 {           XCTestExpectation *exp = [self expectationWithDescription:@"超时"];           NSOperationQueue *queue = [[NSOperationQueue alloc]init];           [queue addOperationWithBlock:^{            double revenue = 1500;            double tax = [self.revenueBL calculate:revenue];            sleep(1);             NSLog(@"%f",tax);             XCTAssertEqual(tax, 45, @"用例2测试失败");             [exp fulfill];  // exp结束         }];         [self waitForExpectationsWithTimeout:3 handler:^(NSError * _Nullable error) {             if (error) {                 NSLog(@"Timeout Error: %@", error);             }         }];     } - (void)testExample { } - (void)testPerformanceExample {     [self measureBlock:^{         for (int a = 0; a<10; a+=a) {             NSLog(@"%zd", a);         }     }]; } @end

testLevel1通过revenueBL计算出来的tax与预期相同,测试通过;testLevel2通过revenueBL计算出来的tax与预期不同,测试不通过,反映出了程序少量逻辑漏洞;testPerformanceExample中的平均执行时间比基准值低,测试通过。

案例 6 命令行测试

在命令行中也可以启动测试,便于持续集成。

 Assuner$ cd Desktop/ Desktop Assuner$ cd ASUnitTestFirstDemo/ ASUnitTestFirstDemo Assuner$ xcodebuild test -project ASUnitTestFirstDemo.xcodeproj -scheme ASUnitTestFirstDemo -destination 'platform=iOS Simulator,OS=11.4,name=iPhone 7'  // 可以有多个destination

结果

 Test Suite 'All tests' started at 2017-09-11 11:12:16.348 Test Suite 'ASUnitTestFirstDemoTests.xctest' started at 2017-09-11 11:12:16.349 Test Suite 'ASUnitTestFirstDemoTests' started at 2017-09-11 11:12:16.349 Test Case '-[ASUnitTestFirstDemoTests testLevel1]' started. Test Case '-[ASUnitTestFirstDemoTests testLevel1]' passed (0.001 seconds). Test Case '-[ASUnitTestFirstDemoTests testLevel2]' started. /Users/liyongguang-eleme-iOS-Development/Desktop/ASUnitTestFirstDemo/ASUnitTestFirstDemoTests/ASUnitTestFirstDemoTests.m:46: error: -[ASUnitTestFirstDemoTests testLevel2] : ((tax) equal to (45.0)) failed: ("-60") is not equal to ("45") - 用例2测试失败 Test Case '-[ASUnitTestFirstDemoTests testLevel2]' failed (1.007 seconds). Test Suite 'ASUnitTestFirstDemoTests' failed at 2017-09-11 11:12:17.358. Executed 2 tests, with 1 failure (0 unexpected) in 1.008 (1.009) seconds Test Suite 'ASUnitTestFirstDemoTests.xctest' failed at 2017-09-11 11:12:17.359. Executed 2 tests, with 1 failure (0 unexpected) in 1.008 (1.010) seconds Test Suite 'All tests' failed at 2017-09-11 11:12:17.360. Executed 2 tests, with 1 failure (0 unexpected) in 1.008 (1.012) seconds Failing tests: -[ASUnitTestFirstDemoTests testLevel2] ** TEST FAILED **

假如是workspace

 xcodebuild -workspace ASKiwiTest.xcworkspace -scheme ASKiwiTest-Example -destination 'platform=iOS Simulator,OS=11.0,name=iPhone 7' test

每个test方法都会跑一遍,并给出结果形容。

案例 7 代码的执行时间测试-(性能测试)

性能测试主要使用 measureBlock 方法 ,用于测试一组方法的执行时间,通过设置baseline(基准)stddev(标准偏差)来判断方法能否能通过性能测试


如果直接执行方法,由于block中没有内容,所以方法的执行时间为0.0s,假如我们把baseline设成0.05,偏差10%,是可以通过的测试的。但是假如设置假如我们把baseline为1,偏差10%,那测试会失败,由于不满足条件。

如上图所示,这个方法是用来测试block内代码的执行时间的,我们可以通过打印很清楚的看到它其实执行了10次,用处也很宽广,比方想测试身份证的识别时间,请求的时间,转模型的速度等等都可以通过它来测试,这里只是举个简单的例子.

我们可以看下打印发现他的确是执行了十次.


再来看看左边的执行代码相关信息,这里因为打印"1"执行的太快无法看出效果,所以我将测试内容换成了使用for循环打印1-9999,看看他们的执行时间.

可以很清楚的看到,10次的平均时间是1.382秒,第一次时间是1.85秒,并且可以看到第一次执行时间超过了平均时间33%,这里的测试结果都是和机器性能有关系的.

案例 8 登陆板块测试

案例 9 加法测试
- (void)testExample {     //设置变量和设置预期值    NSUInteger a = 10;NSUInteger b = 15;    NSUInteger expected = 24;    //执行方法得到实际值    NSUInteger actual = [self add:a b:b];    //断言判定实际值和预期能否符合    XCTAssertEqual(expected, actual,@"add方法错误!");}-(NSUInteger)add:(NSUInteger)a b:(NSUInteger)b{    return a+b;}

从这也能看出一个测试用例比较规范的写法,1:定义变量和预期,2:执行方法得到实际值,3:断言

案例 10 代码来自于AFNetworking,用于测试backgroundImageForState方法
- (void)testThatBackgroundImageChanges {    XCTAssertNil([self.button backgroundImageForState:UIControlStateNormal]);    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(UIButton  * _Nonnull button, NSDictionary<NSString *,id> * _Nullable bindings) {    return [button backgroundImageForState:UIControlStateNormal] != nil;  }];  [self expectationForPredicate:predicate            evaluatedWithObject:self.button                                   handler:nil];   [self waitForExpectationsWithTimeout:20 handler:nil];   }

利用谓词计算,button能否正确的取得了backgroundImage,假如正确20秒内正确取得则通过测试,否则失败。

expectationForNotification 方法 ,该方法监听一个通知,假如在规定时间内正确收到通知则测试通过。

- (void)testAsynExample1 { [self expectationForNotification:(@"监听通知的名称xxx") object:nil handler:nil]; [[NSNotificationCenter defaultCenter]postNotificationName:@"监听通知的名称xxx" object:nil]; //设置推迟多少秒后,假如没有满足测试条件就报错 [self waitForExpectationsWithTimeout:3 handler:nil];}

这个例子也可以用expectationWithDescription实现,只是多些很多代码而已,但是这个可以帮助你更好的了解 expectationForNotification 方法和 expectationWithDescription的区别。同理,expectationForPredicate方法也可以使用expectationWithDescription实现。

func testAsynExample1() {let expectation = expectationWithDescription("监听通知的名称xxx")let sub = NSNotificationCenter.defaultCenter().addObserverForName("监听通知的名称xxx", object: nil, queue: nil) { (not) -> Void in   expectation.fulfill()} NSNotificationCenter.defaultCenter().postNotificationName("监听通知的名称xxx", object: nil) waitForExpectationsWithTimeout(1, handler: nil) NSNotificationCenter.defaultCenter().removeObserver(sub) }
XCTest常见的断言
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没有发生异常时通过测试;XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

特别注意下XCTAssertEqualObjects和XCTAssertEqual。 XCTAssertEqualObjects(a1, a2, format...)的判断条件是[a1 isEqual:a2]能否返回一个YES。XCTAssertEqual(a1, a2, format...)的判断条件是a1 == a2能否返回一个YES。对于后者,假如a1和a2都是基本数据类型变量,那么只有a1 == a2才会返回YES

备注:

1.关于私有方法的测试,只能通过扩展来实现

2.关于case的方法名字,肯定要以test开头并注意驼峰命名法,且不能加入参数

3.单元测试类继承自XCTestCase,他有少量重要的方法,其中最重要的有3个,setUp ,tearDown,measureBlock.

4.md + 5切换到测试选项卡后会看到很多小箭头,点击可以单独或者整体测试.

5.cmd + U运行整个单元测试

6.使用pod的项目中,在XC测试框架中测试内容包括第三方包时,需要手动去设置Header Search Paths才能找到头文件 ,还需要设置test targetPODS_ROOT

7.xcode7要使用真机做跑测试时,证书必需配对,否则会报错exc_breakpoint错误

部分案例Demo:
Demo-1 Demo-2
参考文章:
1-1 (一) 初探 iOS 单元测试
1-2 iOS单元测试(作用及入门提升)
1-3 爱上iOS单元测试系列之爱上她就要先理解她:单元测试入门
1-4 Testing with Xcode文档(中文版):从 OCUnit 过渡到 XCTest
1-5 iOS关于单元测试的学习笔记还有本人在学的路上遇到的那些 坑
1-6 Xcode 5 单元测试(一)使用XCTest进行单元测试
1-7 简单iOS单元测试-异步测试(XCTestExpectation)
1-8 cocoaChina测试专题
1-9 iOS单元测试

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS-单元测试汇总

发表回复