首页 > 代码库 > 测试控制器
测试控制器
测试不应该是很教条的,相反的测试工作应该达到的状态是能够让我们加快开发速度,并且让我们的工作更加的有趣。
Keeping Things Simple(保持事情的简单性)
测试简单的任务是简单的,测试复杂的工程是复杂的,我们这里想要讨论的是如何让事情保持简单和尽可能小,这样的话完全是有利于测试工作的进行的,是双赢的工作。保持事情的简单性其实就和TDD(test-driver development)相似的,有人喜欢它有人厌恶它,此文的目的并不在TDD上,所以我们仅仅是粗略的概述一下TDD的概念:在编写代码之前,测试人员首先会在对于系统新的改进和功能函数的需求的基础上创建自动的测试用例,并在这个前提之下,尽量使用最少量的代码来通过测试用例,最后修改代码进行重构,并且确保重构之后的代码遵守系统的代码标准。
对UI元素进行测试往往都是很困难的,因为UI元素包含了太多的移动的内容。而控制器面对的情况其实更加的复杂,因为控制器和view层和model层的很多类都有着联系。为了能够对控制器进行测试工作,我们需要让不同层次之间的工作能够分开进行。
我们期望的是这样的:在更加干净的控制器那篇文章中让控制器更加的干净的的那些方法一样也能够让我们的测试工作更加的简单。通常情况下,如果你发现测试工作让你十分痛苦,那么这其实就是暗示你的设计或许很糟糕,需要重新进行设计或者代码的抽取才能让测试工作变得简单。我们总体的设计目标是让不同层次之间层次分明,关系清晰。最佳的设计其实就是:我所创造的每一个类只去做一件事情,并且它需要把自己分内的工作做的很好。这样话对每一个类进行的测试都是非常的简单的。
Mark:添加的测试越多,得到的返回结果越少!首先也是最终要的是要保持测试的简单性!
Mocking
当我们将复杂的事情分散到很多的类中分别进行的时候,我们测试的工作将会变得异常的简单:只需要分别测试每一个独立的类就可以了。我们正在测试的这个类和其他的类之间有着联系,我们通过使用一个代码仿造品(mock or stub. )来避免这种联系。其实可以把这一个仿造代码看做是占位符,这样的话我们测试的这个类就是和这些占位对象进行联系了,而不是真正的对象。这样的话我们就可以专心在这个类的测试上,而不用担心其他的类对测试这个类的干扰。
OC中的模拟代码的强大工具是 OCMock,这是一个影响了objective-c的运行时(runtime)的作用和灵活性的非常成熟的工具。
SenTestKit
另一个我们需要用到的测试框架SenTestingKit现在集成在了xcode中,它的作用是运行测试代码,通过SenTestingKi你完全可以将测试代码组织到一个类中去。在这些测试类中的每一个方法都需要有具体的测试功能(职责)而且方法名要以test开头,test是在运行时将方法解读为测试的标志,可以重写-setUp
and -tearDown两个特殊方法来初始化测试,需要记住的重要的一点是:测试类也只是一个类,如果能够帮助你进行测试工作那么就不要犹豫直接向里面加入需要的属性和方法。
在测试的时候还有一点是,通常我们会先创造一个测试的基类,并且在这个基类中存放一些通用的逻辑代码以便帮助我们更加专注的进行测试工作。通常我们也不会使用Xcode的模板进行测试工作,我们仅仅是添加一个简单的.m文件,为了方便我们命名这个类的时候在用Tests作为结尾,而且这个类的名字应该反映这个类的测试用途。
Integration with Xcode(融合Xcode)
测试会内置到你选择的静态库和资源包种去,如果你的测试需要特殊的资源文件,直接加入到测试目标中去Xcode会把它们放入到资源包中的。然后你可以使用NSBundle进行定位操作-URLForResource:withExtension:
测试运行的方式:程序会运行,然后测试包会进行注入。你可能不希望你的app做太多的事情,因为这样很可能会影响测试工作,你可以在程序的代理类中放入下面的东西来解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | static BOOL isRunningTests(void) __attribute__((const)); - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if (isRunningTests()) { return YES; } // // Normal logic goes here // return YES; } static BOOL isRunningTests(void) { NSDictionary* environment = [[NSProcessInfo processInfo] environment]; NSString* injectBundle = environment[@"XCInjectBundle"]; return [[injectBundle pathExtension] isEqualToString:@"octest"]; } |
可以在Xcode中编辑scheme给了我们很大的灵活性,你可以在测试运行之前或者之后执行特定的脚本,而且也可用使用很多的测试包,对于大型项目这些都是很重要的。更加重要的是我们可以打开或者关闭特定的测试代码,这在进行debug测试的时候异常重要,但是别忘了在结束之后都打开。