iOS development: xctest Unit test (with A single sample test code Attached)

Source: Internet
Author: User
Tags scalar
<span id="Label3"></p><p style="margin-left: 30px;"><p style="margin-left: 30px;">Test-driven development is not a very fresh concept. When I first learned how to write a program, my favorite thing to do was to write a piece of code and run the observation results correctly. I learned the first language is c, the most used is in the algorithm design, then the most often do is to write a piece of code, how to compile and run, to see if the results are correct, many times, you have to think of a lot of special (such as 0 value, boundary Value) test data to detect the code, the algorithm is Correct. At that time, feeling ok, compare output is just a simple number or character of the Console. In learning iOS development, it is often a test, and this output is something that must be clicked on a series of buttons before it can be displayed on the Screen. When testing, often use the simulator to start the app from the beginning, then navigate to the program of your module, do a series of clicks, and see if the results match your expectations.</p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;">This behavior is undoubtedly a great waste of good life and brilliant youth. So a lot of senior engineers found out that we could construct a similar scenario in our code, then call the code we wanted to check in the code and compare the results of the run with the assumptions in the program, and if that's the case, our code is FINE. For example, the following code:</p></p><pre class="brush:objc;gutter:true;"><pre class="brush:objc;gutter:true;">int a = 3, b = 4;int C = A + b;if (c = = A + b) { //result correct}else{ </pre></pre><p style="margin-left: 30px;"><p style="margin-left: 30px;">When the test is comprehensive and representative, we can be sure that this code is no problem, at least the problem is not from this Code. We make certain conditions and assumptions, and use them as conditions for the code being tested, and compare the expected results with the running results, which is the basic method in software Testing.</p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;"></p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;"><strong>first, What is Unit testing? The explanations in Wikipedia are:</strong></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">In computer programming, unit testing (also known as Module testing, Unit Testing) is a test work for correctness testing of program modules (the smallest unit of software design). The program unit is the smallest testable part to be Applied. In procedural programming, a unit is a single program, function, process, etc. for object-oriented programming, the smallest element is a method, including a base class (superclass), an abstract class, or a method in a derived class (subclass).</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">In general, the programmer every time the program is modified at least one unit test, in the process of writing a program is likely to conduct several unit tests to verify that the program meets the requirements of the software specification (en:specification) objectives, There is no program error, although unit testing is not necessary , but it is not bad, it involves the policy decision of project Management.</p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;"><strong>Using Xctest in Xcode</strong></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">When you create a new project in XCode7, you will default to a target for the unit test, whose name is the project name plus the test suffix, and the file name ends with Test. You will find that you already have a default test case</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">Note Where the hook is drawn, the include unit test is meant to contain the element tests. Open the Factory directory and you will find the following files:</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">Where the files in the Zymusicplayertests folder directory are our unit test Files.</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">When you create a new project, it defaults to a target for the unit test, whose name is the project name plus the tests suffix, and the file name ends with Test. You will find that you already have a default test case, which has four methods:</p></p><pre class="brush:objc;gutter:true;"><pre class="brush:objc;gutter:true;">#import <XCTest/XCTest.h> @interface zymusicplayertests:xctestcase@end@implementation zymusicplayertests-( Void) setUp { [super setUp]; Put Setup Code Here. This method was called before the invocation of each test method in the class.} -(void) tearDown { //Put TearDown code Here. This method was called after the invocation for each test method in the Class. [super tearDown];} -(void) Testexample { //this was an example of a functional test case. Use Xctassert and related functions to verify your tests produce the correct results.//xctfail (@ "no Implementation For app ", __pretty_function__);} -(void) Testperformanceexample { //this was an example of a performance test Case. [self measureblock:^{ }];} @end</pre></pre><p><p></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">The four methods were: setUp, tearDown, testexample, testperformanceexample. Where the Testexample method has a play button to the left, click on it will test this method, and in the entire file @implemenation that line also has a same button, click on the current test case to test all methods, It can also be triggered by Command+u shortcut keys. This test case class does not have a header file because the test case does not need to give the external burst interface. According to Apple's official documentation, the process of building a test case should look like this:</p></p> <ol> <ol> <ol> <li>Create a <code>XCTestCase</code> subclass of</li> <li>Implementing Test methods</li> <li>Optionally define some instance variables to store the state of the fixture</li> <li><code>setUp</code>selective instantiation of fixture by overriding method</li> <li>By overriding <code>tearDown</code> the method to clear after testing<br>The test method does not have parameters and return values, and uses test as a prefix, such as:<p>-(void) Testplayingmusic</p></li> </ol> </ol> </ol><p><p></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">is automatically recognized by the <code>XCTest</code> schema as a test case, and each <code>XCTestCase</code> subclass <code>defaultTestSuite</code> is one <code>XCTestSuite</code> that contains these test cases.<br>The implementation of the test method often contains assertions that must be validated to pass the test, for example:</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">Here are all the assertion tests that are used:</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><pre class="brush:objc;gutter:true;">Xctfail (format ...) generates a failed test; xctassertnil (a1, format ...) For null judgment, The A1 is empty when passed, and Vice versa; xctassertnotnil (a1, format ...) Not for null judgment, A1 is not empty when passed, vice versa; xctassert (expression, format ...) Passed when expression evaluates to true; xctasserttrue (expression, format ...) Passed when expression evaluates to true; xctassertfalse (expression, format ...) Passed when expression evaluates to false; xctassertequalobjects (a1, a2, format ...) Judged equal, [a1 isequal:a2] value is true when passed, where one is not empty when not passed; xctassertnotequalobjects (a1, a2, format ...) Judgment unequal, [a1 isequal:a2] value is False when passed; xctassertequal (a1, a2, format ...) Judgment Equality (used when A1 and A2 are C scalar, struct, or union, actual test found NSString can); xctassertnotequal (a1, a2, format ...) Judgment unequal (used when A1 and A2 are C scalar, struct, or union); xctassertequalwithaccuracy (a1, a2, accuracy, format ...) The judgment is equal, (double or float Type) provides an error range, which passes the test when equal within the error range (+/-accuracy); xctassertnotequalwithaccuracy (a1, a2, accuracy, format ...) Judgement unequal, (double or float Type) provides an error range, which passes the test when the error range is not equal; xctassertthrows (expression, format ...) Exception test, passed when expression has an exception; (very perverted) xctassertthrowsspecific (expression, specificexception, format ...) exception test, When expression occurs SpecificexceptiOn exception, other exception or no exception occurs; xctassertthrowsspecificnamed (expression, specificexception, exception_name, format ...) Exception test, when expression has a specific exception, the exception of the specific exception name passed the test, and Vice versa; xctassertnothrow (expression, format ...) Exception test, passing test when expression does not occur; xctassertnothrowspecific (expression, specificexception, format ...) Exception test, when expression does not have a specific exception, the specific exception name of the exception passed the test, and Vice versa; xctassertnothrowspecificnamed (expression, specificexception, exception_name, format ...) Exception testing, when expression does not have a specific exception, the specific exception name of the exception passed the test, and vice versa do not pay special attention to the next xctassertequalobjects and Xctassertequal. Xctassertequalobjects (a1, a2, Format ...) The judging condition is whether [A1 isequal:a2] returns a Yes. Xctassertequal (a1, a2, Format ...) The judging condition is A1 = = A2 whether to return a yes. For the latter, if both A1 and A2 are basic data Type variables, only A1 = = A2 will return Yes. For example</pre><p style="margin-left: 60px;"><p style="margin-left: 60px;">Reference from: http://yulingtianxia.com/blog/2014/04/28/iosdan-yuan-ce-shi-xctest/</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">A part has been tested.</p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;">When using xctest, it is generally the class name of the class that needs to be tested +tests, such as zyaudiomanagertests, to test the Zyaudiomanager class. And this class inherits from the Xctestcase class, or its subclasses, such as:</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">@interface Zyaudiomanagertests:xctestcase</p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;"></p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;">Here is a sample code for music playback with its test code:</p></p><pre class="brush:objc;gutter:true;">#import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> @interface zyaudiomanager: nsobject+ (instancetype) defaultmanager;//play music-(avaudioplayer *) playingmusic: (nsstring *) filename;-(void) Pausemusic: (nsstring *) filename;-(void) stopmusic: (nsstring *) filename;//play sound effects-(void) playSound: (nsstring *) filename ;-(void) disposesound: (nsstring *) filename, @end #import "ZYAudioManager.h" @interface zyaudiomanager () @property ( nonatomic, Strong) nsmutabledictionary *musicplayers; @property (nonatomic, Strong) nsmutabledictionary *soundIDs;@ endstatic Zyaudiomanager *_instance = nil; @implementation zyaudiomanager+ (instancetype) defaultmanager{static DISPATC h_once_t oncetoken; Dispatch_once (&oncetoken, ^{_instance = [[self alloc] init]; }); Return _instance;} -(instancetype) init{__block Zyaudiomanager *temp = self; Static dispatch_once_t oncetoken; Dispatch_once (&oncetoken, ^{if (temp = [super init])! = Nil) {_musiCplayers = [nsmutabledictionary dictionary]; _soundids = [nsmutabledictionary dictionary]; } }); Self = temp; Return self;} + (instancetype) allocwithzone: (struct _nszone *) zone{static dispatch_once_t oncetoken; Dispatch_once (&oncetoken, ^{_instance = [super allocwithzone:zone]; }); Return _instance;} Play Music-(avaudioplayer *) playingmusic: (nsstring *) filename{if (filename = = Nil | | filename.length = = 0) return nil; Avaudioplayer *player = self.musicplayers[filename]; first, query whether the object caches if (!player) {nsurl *url = [[nsbundle mainbundle] urlforresource:filename withextension:nil]; If (!url) return nil; Player = [[avaudioplayer alloc] initwithcontentsofurl:url error:nil]; If (![ Player Preparetoplay]) return nil; self.musicplayers[filename] = player; object is newly created, it is cached once} if (![ Player Isplaying]) {//if It is not playing, start playback ifIs playing, then do not need to change what [player play]; } return player; -(void) pausemusic: (nsstring *) filename{if (filename = = Nil | | filename.length = = 0) return; Avaudioplayer *player = self.musicplayers[filename]; If ([player isplaying]) {[player pause]; }}-(void) stopmusic: (nsstring *) filename{if (filename = = Nil | | filename.length = = 0) return; Avaudioplayer *player = self.musicplayers[filename]; [player stop]; [self.musicplayers removeobjectforkey:filename];} Play Sound-(void) playSound: (nsstring *) filename{if (!filename) return; Remove the corresponding sound effect ID systemsoundid soundid = (int) [self.soundids[filename] unsignedlongvalue]; If (!soundid) {nsurl *url = [[nsbundle mainbundle] urlforresource:filename withextension:nil]; If (!url) return; Audioservicescreatesystemsoundid (__bridge Cfurlref) (url), &soundid); self.soundids[filename] = @ (soundid); }//play AudioservicesplaysysTemsound (soundid);} Destroy Sound-(void) disposesound: (nsstring *) filename{if (!filename) return; Systemsoundid Soundid = (int) [self.soundids[filename] unsignedlongvalue]; If (soundid) {audioservicesdisposesystemsoundid (soundid); [self.soundids removeobjectforkey:filename]; The sound is destroyed, then the corresponding object should be removed from the cache}} @end</pre><p style="margin-left: 30px;"><p style="margin-left: 30px;">Test code (test code, only. m files, No. h files):</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><pre class="brush:objc;gutter:true;">#import <XCTest/XCTest.h> #import "ZYAudioManager.h" #import <AVFoundation/AVFoundation.h> @interface Zyaudiomanagertests:xctestcase@property (nonatomic, Strong) avaudioplayer *player; @endstatic nsstring *_fileName = @ " 10405520.mp3 "; @implementation zyaudiomanagertests-(void) setup {[super setUp]; Put Setup Code Here. This method was called before the invocation of each test method in the class.} -(void) tearDown {//Put TearDown code Here. This method was called after the invocation for each test method in the Class. [super tearDown];} -(void) Testexample {//this was an example of a functional test case. Use Xctassert and related functions to verify your tests produce the correct results.} /** * Test is a singleton, to test */-(void) testaudiomanagersingle{nsmutablearray *managers = [nsmutablearray array] under concurrency conditions; Dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{zyaudiomanager *tempManager = [ZY Audiomanager alloc] init]; [managers addobject:tempmanager]; }); Dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{zyaudiomanager *tempManager = [ZY Audiomanager alloc] init]; [managers addobject:tempmanager]; }); Dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{zyaudiomanager *tempManager = [ZYA Udiomanager defaultmanager]; [managers addobject:tempmanager]; }); Dispatch_async (dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{zyaudiomanager *tempManager = [ZYA Udiomanager defaultmanager]; [managers addobject:tempmanager]; }); Zyaudiomanager *managerone = [zyaudiomanager defaultmanager]; [managers enumerateobjectsusingblock:^ (zyaudiomanager *obj, nsuinteger idx, BOOL * _nonnull stop) {xctassertequal (managerone, obj, @ "zyaudiomanager is not a single"); }];} /** * Test to play music */-(void) Testplayingmusic{self.player = [[zyaudiomanageR defaultmanager] playingmusic:_filename]; Xctasserttrue (self.player.playing, @ "zyaudiomanager is not playingmusic");} /** * Test if normal stop music */-(void) teststopmusic{if (self.player = = Nil) {self.player = [[zyaudiomanager Defaultman ager] playingmusic:_filename]; } if (self.player.playing = = NO) [self.player play]; [[zyaudiomanager defaultmanager] stopmusic:_filename]; Xctassertfalse (self.player.playing, @ "zyaudiomanager is not stopmusic");} /** * Test whether the music */-(void) testpausemusic{if (self.player = = Nil) {self.player = [[zyaudiomanager defaultma] can be paused normally nager] playingmusic:_filename]; } if (self.player.playing = = NO) [self.player play]; [[zyaudiomanager defaultmanager] pausemusic:_filename]; Xctassertfalse (self.player.playing, @ "zyaudiomanager is not pausemusic");} @end</pre><p style="margin-left: 60px;"><p style="margin-left: 60px;">Command + u Run the Test.</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 30px;"><p style="margin-left: 30px;"><strong>What should I test?</strong></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"><strong>After learning the use of the above method, confused, in the specific development, if writing test code, then what should I test? Do private methods also need to be tested?</strong></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">We don't need to test private methods, but to answer "what should I test?" "it's not that simple, but I still want the test code to be tested in the way I actually coded it, so the test is just a call to my common approach."</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">-(void) testdownloaddata;</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">A test like this has a fundamental problem: it doesn't tell you what should happen, that is, it doesn't tell you what the actual expectations Are. It does not know what the demand is.</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">What should be tested? <strong>I should not focus on testing, but should pay attention to behavior, should test Behavior. </strong></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">What is behavior?</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">Let's think of an object in the app You're Designing. It has an interface that defines its methods and Dependencies. These methods and dependencies declare the conventions of your objects. They define how to interact with other parts of your app, and what its capabilities Are. They define the behavior of the Object.</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">There are a lot of behaviors, maybe Private. For example, I want to test the implementation of the three data source methods that must be implemented for the datasource of TableView that inherit from Uiviewcontroller zynewviewcontroller?</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">In the past, writing code, according to the principle of encapsulation, TableView must be private, then for the convenience of testing, we should write it as public?</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;">no, There is a solution is to write a common testsprocotol, and then use the delegate to implement the above Test.</p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p style="margin-left: 60px;"><p style="margin-left: 60px;"></p></p><p><p>iOS development: xctest Unit test (with A single sample test code Attached)</p></p></span>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.