[IOS translation] iOS7 by Tutorials series: using unit testing in Xcode 5 (I)

Source: Internet
Author: User

Introduction:

Unit testing is an important aspect of software development. After all, unit tests can help you identify bugs and causes of crashes, and program crashes are the primary cause of Apple's rejection of app shelving during review.

Unit testing is not omnipotent, but Apple uses it as a part of the development kit, which not only makes your APP more stable, but also provides a consistent and interesting user experience, these are the sources that allow users to give you a five-star rating! IOS7 provides an upgraded unit test framework, making it easier to run unit tests in Xcode. After completing this section, you will learn how to add tests to existing apps-and possibly cultivate your passion for writing tests!

/*

This article is translated from Chapter 11th "Unit Testing in Xcode 5" in iOS7 by Tutorials. If you want to understand the essence of the original article, please go to the Raywenderlich store to support genuine versions.

------ (Blog Park, Sina Weibo)

*/

 

Directory:

I. unit test Basics

2. Start the project

3. What should I do next?

Iv. Challenges

Appendix: XCTest assertions reference

 

I. unit test Basics

In the past, Xcode introducedOCUnitOpen source unit test framework. In Xcode 5, Apple released its own unit test framework, XCTest.

If you are familiar with OCUnit, don't worry,XCTestIs an API built on OCUnit with ten similar copies. It is very easy to transition from OCUnit to XCTest. You only need to replace STFail with XCTFail, STAssert with XCTAssert, and so on. If you are familiar with these basics, you can skip to the next section.

 

 

1. high-level overview

 

Unit testing has four levels. From top to bottom, they are:

 

  • Test suite)
    • This is a set of all tests in the project. In Xcode, the test suite is set to a separate build target.
  • Test case classes)
    • As you may expect, in an object-oriented system, testing is integrated into classes. In your app, each test class usually corresponds to a separate class. For example, the deletests class should correspond to the testing of the Developer class.
  • Test case methods)
    • Each test class contains multiple methods to test various functions of the class. Just like a method or function should be both concise and practical, and each test case should test a specific result-and be fully tested.
  • Assertions)
    • The condition that the assertion check corresponds to the expected result. If the conditions do not match the expected results, Xcode reports an error indicating that the assertion fails. For example, you can assert that your Developer Class responds to "writeKillerApp: message". If it does not, the asserted fails and Xcode reports an error.

 

 

The theory is good, but sometimes it is easier to explain things. UseEmpty ApplicationTemplate to create a new project namedEmptyApp. The Xcode template automatically containsEmptyAppTestsAddEmptyAppApp target, such:

 

Note that the test case class contains a. m file that is not associated with the header file. OpenEmptyAppTests. mCheck the source code of the first test case.

The test method must start with the word test.So that test runner can find them. In your example project, the test class contains a test method calledTestExample.

 

SetUpAndTearDownThe method is like guarding the test case.

Set the code orPut repetitive code in setUpTo keep the test case method fresh and efficient.

Similarly, close the file handle or cancel a pending network request.The cleanup method should be put in tearDown..

 

The Test runner calls the setUp, testExample, and tearDown methods in sequence. If you declare the second Test method testSecondExample, the Test runner will call setUp, testSecondExample in sequence, and the tearDown method. If you have multiple test methods, setUp and tearDown will call multiple times in one test step-each time a test case method is called!

 

The implication of this story is:Do not put anything that is too slow or frequently processed into the setUp or tearDown method.-- This will lead to a long wait for you to run the test suite.!

 

 

 

2. Create your first test

 

 

The testExample method has only one statement called XCTFail, as its name implies: it will always fail. This statement is not very useful. You can write a statement better than it! Delete the testExample method and add the following method:

- (void)test_addition_twoPlusTwo_isFour 
{  XCTAssert(2 + 2 == 4, @"2 + 2 should be 4 but %d was returned instead", 2+2);}

A common naming standard for test cases is unitOfWork_stateUnderTest_expectedBehavior (unit of work _ test status _ expected behavior ).

In this example, the unit of work to be tested is addition, the test state is 2 + 2, and the expected behavior is 4.

All XCTest assertions have the prefix XCT. XCTAssert is a simple assertion that can be used for unit testing. The first parameter is the expression pre-evaluated as ture. When the assertion fails, a message is displayed for the NSLog-style parameters.

 

Make sure that the current target of the project is the iPhone simulator. Run the Test through the Product-> Test (Command-U) in the top directory of the window. The simulator starts and runs the Test suite. If the notification is active, you will see the following confirmation message:

 

 

To verify the success of the first unit Test, switch to Test Navigator and the arrow points out it:

Haha! Your unit test is displayed next to the green check box.

You can also see the code next to the diamond icon in the blank area of the border, as shown below:

These icons show the status of the associated test code:

@ Implementation: the green check mark next to implementation indicates that the test is successful. The green check mark next to test_addition_twoPlusTwo_isFour indicates that the test is successful.

These icons are also buttons:

Click the icon next to @ implementation to run all tests of this class. Click the icon next to other test methods to run the test method. Give it a try!

 

Now you have a preliminary understanding of the concept and execution of the test. It is time to start the sample project in this chapter-the test begins!

 

2. Start the project

The rest of this chapter uses a Reversi black and white game project. Rule: two players represent the white and the black, respectively, and take turns on the 8x8 board. The opponent's pawns are surrounded to eat, and the most pawns are the winners at the end of the game.

See http://www.raywenderlich.com/29228/how-to-develop-an-ipad-board-game-app-part-12 for how to create this game

Download and run the sample project provided at the end of this article, and clickVs ComputerThe button is used to compete with the computer. You can feel the interface and gameplay of the game.

Have you won? Or is the AI competitor showing up? In any case, it's not your job to play games all day-it's time to add some useful tests to the project.

 

1. Add test support

The first unit test is the GameBoard class. This class includes the basic logic of the 8x8 board. Each of the 64 cells has a status-empty, black or white-and the GameBoard instance allows you to obtain and set the status of each square.

OpenGameBoard. hLet's take a look at the methods. It is a good idea to figure out the functions and implementations of each method before writing and testing the existing code.

InGameBoard. h, You will see the following two methods:

// gets the state of the cell at the given location// raises an NSRangeException if the column or row are out of bounds- (BoardCellState) cellStateAtColumn:(NSInteger)column andRow:(NSInteger)row;// sets the state of the cell at the given location// raises an NSRangeException if the column or row are out of bounds- (void) setCellState:(BoardCellState)state forColumn:(NSInteger)column andRow:(NSInteger)row;

CellStateAtColumn: andRow: And setCellState: forColumn: andRow: Developed by the getter/setter mode you are very familiar with. Your first test is to execute the following actions:

  • Initialize a GameBoard instance
  • Set cell status
  • Get cell status
  • Obtains the cell status from the specified cell.

 

The first step is to create a GameBoard test class, right-clickReversiGameTestsGroup, selectIOS \ Cocoa Touch \ Objective-C test case classCreate a test class named GameBoardTests that inherits from XCTestCase.

Make sure your new test cases are addedReversiGameTestsTarget, for example (this step is very important. If it is not added to the correct target, your test will not run ):

 

OpenGameBoardTests. mYou do not need to delete the testExample method.

ThenGameBoardTests. mImport the header file on the top (this only allows your test class to access the GameBoard class): GameBoard. h

#import "GameBoard.h"

 

You need to provide a GameBoard instance for all your tests. Creating an instance variable is much cleaner than declaring a variable in each test.

InGameBoardTests. mUpdate @ interface in:

@interface GameBoardTests : XCTestCase 
{
  GameBoard *_board;}

Now that you have the _ board instance variable, you can start the test.

 

The setUp method is a good place to initialize _ board for the first time. Modify setUp as follows:

- (void)setUp{  [super setUp];  _board = [[GameBoard alloc] init]; }

Now all the test case methods of this class can access the initialized _ board instance variable.

 

2. First test

This is all the steps you need to add the first test case. Add the following methodGameBoardTests. m:

- (void)test_setAndGetCellState_setValidCell_cellStateChanged {  [_board setCellState:BoardCellStateWhitePiece forColumn:4 andRow:5];
  BoardCellState retrievedState = [_board cellStateAtColumn:4 andRow:5];
  

  XCTAssertEqual(BoardCellStateWhitePiece,           retrievedState,           @"The cell should be white!");}

The above Code sets a white play in cell () and immediately retrieves the status of the same cell. The XCTAssertEqual assertion checks whether they are equal. If they are not equal, you will see an exception message and you will know that something needs to be checked.

The method name in the code above follows the format I mentioned earlier. With this method name, you can easily see that it tests the setter and getter methods by setting the correct cell location, we expect the cell status to change.

 

If your testing work is planned, make sure that both the iPhone and iPad simulators are tested and then run the test (Command-U ).

Switch to Test Navigator and you will see a green tick indicating that the Test is successful, for example:

This seems to be a simple test, but it provides great value in debugging errors.

 

Internally, the GAMEBOARD class uses a simple two-dimensional array to track the 8x8 board. However, if you have changed an array that represents a vector or matrix, this test will be used as a regression test to ensure that the interface is still working.

As a companion benefit, writing tests for existing classes can greatly help you understand how code works. The analysis method can help you identify its functions and facilitate the compilation and testing.

 

3. Test exception

Testing the code based on the designed features helps ensure its correctness, but also enables your app to "fail early or make a high profile fail"-those abnormal game states or invalid conditions are quickly captured by the debugger.

The comments of cellStateAtColumn: andRow: And setCellState: forColumn: andRow: In GameBoard. h indicate that if the rows or columns exceed the checker border, an error will pop up. It seems that you have found more test conditions.

Add the following two methods:

- (void)test_setCellState_withInvalidCoords_exceptionThrown {XCTAssertThrowsSpecificNamed([_board setCellState:BoardCellStateBlackPieceforColumn:10andRow:7], NSException,NSRangeException,@"Out-of-bounds board set should raise an exception");}- (void)test_getCellState_withInvalidCoords_exceptionThrown {XCTAssertThrowsSpecificNamed([_board cellStateAtColumn:7 andRow:-10],NSException,NSRangeException,@"Out-of-bounds board access should raise an exception");}

In the above Code, test_setCellState_withInvalidCoords_exceptionThrown: tries to set cells out of the range (), while test_setCellState_withInvalidCoords_exceptionThrown: tries to get cells out of the range (7,-10 ). Again, the method name has pointed out the incorrect coordinate in the positive test, and an exception is expected.

 

XCTAssertThrowsSpecificNamed uses the following four points as the parameter:

  • Abnormal expression should be reported
  • Excluded class
  • Excluded name
  • Message displayed when the test fails

Click Command-U to run the test. You should see the following results.

What is this? You want to pass the test with excellent code, but two errors are marked on Issue Navigator. The test failure information is displayed in the code, for example:

 

All test failure messages are as follows:

[GameBoardTests test_getCellState_withInvalidCoords_exceptionThrown] failed: (([_board cellStateAtColumn:7 andRow:-10]) throws <NSException, "NSRangeException">) failed: throwing <NSException, "NSGenericException", "row or column out of bounds"> - Out-of- bounds board access should raise an exception

If you break down the above message, you will see that the expected behavior is (throws <NSException, "nsangeexception">), and what actually happens is (throwing <NSException, "NSGenericException"> ).

In this example, you expect the nsangeexception, but receive the NSGenericException.

It seems that you have done some research!

 

Example Project address: http://pan.baidu.com/s/1o6x6zxg

 

 

 

 

Related Article

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.