• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • Swift
  • Tech Tips

XCTest

Assertions supported in XCTest

March 23, 2017 By Ravi Shankar Leave a Comment

Here you can find the list of Assertions supported by XCTest and it is essential to know all these assertion if you are practicing Test Driven Development in IOS. You can get this list from XCTestAssertions.h

  • XCTFail(<#format…#>) – This unconditionally fails the test.
  • XCTAssertNil(<#a1#>, <#format…#>) – Failure message when object is not nil.
  • XCTAssertNotNil(<#a1#>, <#format…#>) – Failure message when object is nil
  • XCTAssertEqual(<#a1#>, <#a2#>, <#format…#>) – Failure message when expressions(a1 & a2) are not equal.
  • XCTAssertNotEqual(<#a1#>, <#a2#>, <#format…#>) – Failure message when expressions(a1 & a2) are equal.
  • XCTAssertEqualObjects(<#a1#>, <#a2#>, <#format…#>) – Failure message when objects(a1 & a2) are not equal.
  • XCTAssertNotEqualObjects(<#a1#>, <#a2#>, <#format…#>) – Failure message when objects(a1 & a2) are not equal.
  • XCTAssertEqualWithAccuracy(<#a1#>, <#a2#>, <#accuracy#>, <#format…#>) – Failure message when a1 is not equal to a2 with + or – accuracy.
  • XCTAssertNotEqualWithAccuracy(<#a1#>, <#a2#>, <#accuracy#>, <#format…#>) – Failure message when a1 is equal to a2 with + or – accuracy.
  • XCTAssertNoThrow(<#expression#>, <#format…#>) – Failure message when expression does throw exception.
  • XCTAssertNoThrowSpecific(<#expression#>, <#specificException#>, <#format…#>) – Failure message when expression throws specific exception.
  • XCTAssertNoThrowSpecificNamed(<#expression#>, <#specificException#>, <#exception_name#>, <#format…#>) – Failure message when expression throws specific class with specific name.
  • XCTAssertThrows(<#expression#>, <#format…#>) – Failure message when expression does not throw exception.
  • XCTAssertThrowsSpecific(<#expression#>, <#specificException#>, <#format…#>) – Failure message when expression does not throw specific exception.
  • XCTAssert(<#expression#>, <#format…#>) – Failure message when expression is false.
  • XCTAssertTrue(<#expression#>, <#format…#>) – Failure message when expression is false.
  • XCTAssertFailure(<#expression#>, <#format…#>) – Failure message when expression is true.

Filed Under: Develop, ios, Swift, Xcode Tagged With: Assertions, Xcode, XCTest

Test Driven Development in iOS – Beginners tutorial – Part 2

April 14, 2014 By Ravi Shankar 3 Comments

This is in continuation of the Test Driven Development in iOS – Beginners tutorial and this covers writing XCTest user interfaces in iOS. AddingTwoNumbers app will have following controls

1. Three textfields – For entering the numbers and displaying the result.

2. Two buttons – Add button to perform addition and Reset button to clear all the textfields.

Let us create a new Test case class for testing the user interface, AddTwoNumberViewControllerTests.m

201404141732.jpg

201404141743.jpg

The first test written is for checking the App Delegate call, storyboard, view controller and view.

-(void)testViewControllerViewExists {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

RSViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

XCTAssertNotNil([viewController view], @”ViewController should contain a view”);

}

The following needs to be done for passing this test.

1. Add new Objective-C class, subclass of UIViewController (RSViewController).

201404141858.jpg

2. Add a Storyboard file to your project which would contain the ViewController required for this app.

201404142108.jpg

3. Drag and drop, UIViewController on the storyboard and set the class name for the ViewController as RSViewController and StoryboardID as RSViewViewController.

201404142114.jpg

4. Now add the code required in App Delegate’s didFinishLaunchingWithOptions method. This should load the storyboard then instantiate the view controller and set it as RootViewController.

– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:[NSBundle mainBundle]];

UIViewController *vc =[storyboard instantiateInitialViewController];

  

// Set root view controller and make windows visible

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

self.window.rootViewController = vc;

[self.window makeKeyAndVisible];

return YES;

}

A lot has been added to just pass a single test case, probably this can be broken up by writing some more tests.

201404142126.jpg

Next add the test for checking the FirstNumber UITextField connection.

-(void)testFirstNumberTextFieldConnection {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

RSViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

XCTAssertNotNil([viewController firstNumberTextField], @”firstNumberTextField should be connected”);

}

Next add the test for checking the FirstNumber UITextField connection.

-(void)testFirstNumberTextFieldConnection {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

RSViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

[viewController view];

XCTAssertNotNil([viewController firstNumberTextField], @”firstNumberTextField should be connected”);

}

This test would pass after adding the IBOutlet for UITextField in the interface file.

#import <UIKit/UIKit.h>

@interface RSViewController : UIViewController

@property (nonatomic,strong) IBOutlet UITextField *firstNumberTextField;

@end

Then add UITextField to the ViewController and make the connection to UITextField with IBOutlet property.

201404142141.jpg

201404142152.jpg

Then add similar test cases for secondNumber and result textfields. Also make corresponding changes to pass the test.

-(void)testSecondNumberTextFieldConnection {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

RSViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

[viewController view];

XCTAssertNotNil([viewController secondNumberTextField], @”secondNumberTextField should be connected”);

}

-(void)testresultTextFieldConnection {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

RSViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

[viewController view];

XCTAssertNotNil([viewController resultTextField], @”resultTextField should be connected”);

}

201404142205.jpg
Before we move on to the Button test cases, let us refactor the test cases code and remove the duplication of code. The common code has been moved to setup method and now the test cases should loo lot simpler.

@implementation AddTwoNumberViewControllerTests

{

RSViewController *viewController;

}

– (void)setUp

{

[super setUp];

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@”Storyboard” bundle:nil];

viewController = [storyboard instantiateViewControllerWithIdentifier:

@”RSViewController”];

[viewController view];

}

– (void)tearDown

{

[super tearDown];

}

-(void)testViewControllerViewExists {

XCTAssertNotNil([viewController view], @”ViewController should contain a view”);

}

-(void)testFirstNumberTextFieldConnection {

XCTAssertNotNil([viewController firstNumberTextField], @”firstNumberTextField should be connected”);

}

-(void)testSecondNumberTextFieldConnection {

XCTAssertNotNil([viewController secondNumberTextField], @”secondNumberTextField should be connected”);

}

-(void)testresultTextFieldConnection {

XCTAssertNotNil([viewController resultTextField], @”resultTextField should be connected”);

}

Now add the failing test case for Add button and see if the button exists.

-(void)testAddButtonConnection {

XCTAssertNotNil([viewController addButton], @”add button should be connected”);

}

And to pass the above test, add button to ViewController, create a addButton IBOutlet property of type UIButton and make connection to IBOutlet and button field.

@property (nonatomic,strong) IBOutlet UIButton *addButton;


201404142226.jpg

Now add the next test case for checking IBAction method. The below method checks whether addButton call selector method addNumbers on UIControlEventTouchUpInside.

-(void)testAddButtonCheckIBAction {

NSArray *actions = [viewController.addButton actionsForTarget:viewController

forControlEvent:UIControlEventTouchUpInside];

XCTAssertTrue([actions containsObject:@”addNumbers:”], @””);

}

Add this method to RSViewController.m and link this to touchUpInside event of addButton.

-(IBAction)addNumbers:(id)sender {

  

}

Then add the below test cases for checking the addition of two numbers.

-(void)testAddingTenPlusTwentyShouldBeThirty {

viewController.firstNumberTextField.text = @”10″;

viewController.secondNumberTextField.text = @”20″;

[viewController.addButton sendActionsForControlEvents: UIControlEventTouchUpInside];

XCTAssertEqualObjects(viewController.resultTextField.text,@”30″,”Result of the textfield should be 30″);

}

Make changes to the addNumbers method in RSViewController.m by calling application logic method in Addition.m

-(IBAction)addNumbers:(id)sender {

RSAddition *addition = [[RSAddition alloc] init];

NSInteger result = [addition addNumberOne:[self.firstNumberTextField.text integerValue] withNumberTwo:[self.secondNumberTextField.text integerValue]];

self.resultTextField.text = [NSString stringWithFormat:@”%d”,result];

}
Now repeat the test cases for reset button which clears all the textfields.

-(void)testResetButtonConnection {

XCTAssertNotNil([viewController resetButton], @”reset button should be connected”);

}

-(void)testResetButtonCheckIBAction {

NSArray *actions = [viewController.resetButton actionsForTarget:viewController

forControlEvent:UIControlEventTouchUpInside];

XCTAssertTrue([actions containsObject:@”resetFields:”], @””);

}

-(void)testResetButtonShouldClearFields {

viewController.firstNumberTextField.text = @”10″;

viewController.secondNumberTextField.text = @”20″;

viewController.resultTextField.text = @”30″;

[viewController.resetButton sendActionsForControlEvents: UIControlEventTouchUpInside];

XCTAssertEqualObjects(viewController.firstNumberTextField.text, @””, @”FirstNumber textfield should be empty”);

XCTAssertEqualObjects(viewController.secondNumberTextField.text, @””, @”SecondNumber textfield should be empty”);

XCTAssertEqualObjects(viewController.resultTextField.text, @””, @”Result textfield should be empty”);

}

And the corresponding changes to the user interface and RSViewController.m file

-(IBAction)resetFields:(id)sender {

self.firstNumberTextField.text = @””;

self.secondNumberTextField.text = @””;

self.resultTextField.text = @””;

}

Though lot more test cases can be added, I believe this is a decent starter project for learning TDD in iOS. And it is always nice to see the green mark in test navigator.
201404142302.jpg
Now you should be able to run your app and test the functionality.

201404142303.jpg
Source code can be downloaded from here

Filed Under: ios, iPhone, Xcode Tagged With: TDD, User Interface, Xcode, XCTest

Test Driven Development in iOS – Beginners tutorial – Part 1

April 13, 2014 By Ravi Shankar 7 Comments

This is a beginner tutorial on TDD in iOS, explained with an example app that adds two numbers. Let us see try to use some XCTest assertions supported in iOS in this project.

Create a New iOS project select the template as Empty Application

201404132059.jpg

Enter the required details in Choose options for your new project screen.

201404132104.jpg

Step 3: Then specify the folder to save this project.

201404132106.jpg

The project navigator screen will have two targets, one for app and add another for XCTest framework. The folder that ends with “Tests” will contain the default XCTest file .

Lets use the class AddingTwoNumbersTests.m for testing the application logic. Open AddingTwoNumbersTests.m and delete default testExample method.

201404132127.jpg

Create a failing method that tests for existence of new “RSAddition” class that is going to have method for adding two numbers.

201404132155.jpg  

You should notice the errors displayed in the above screenshot after adding testAdditionClassExists. To fix these error, create a new class named RSAddition subclass of NSObject and add the class to both the targets. Then import the Addition.h in “AddingTwoNumbersTests.m”.

201404132152.jpg

201404132153.jpg

Now the tests should pass when it gets executed. You should notice the green tick mark before the class and method and shown in the below screenshot.

201404132158.jpg

Now add the following method to do a simple addition of 2+2.

-(void)testAddTwoPlusTwo {

RSAddition *addition = [[RSAddition alloc] init];

NSInteger result = [addition addNumberOne:2 withNumberTwo:2];

XCTAssertEqual(result, 4, @”Addition of 2 + 2 is 4″);

}

RSAddition class needs to have a new method addNumberOne: withNumberTwo: Add the method definition in RSAddition.h interface file.

-(NSInteger)addNumberOne:(NSInteger) firstNumber withNumberTwo:(NSInteger) secondNumber;

Then add the following method to RSAddition.m implementation file. Let us hardcode the result “4” for time being to pass this test.

-(NSInteger)addNumberOne:(NSInteger) firstNumber withNumberTwo:(NSInteger) secondNumber {

return 4;

}

Now the test should get executed successfully.
201404132209.jpg
Let us add another test to fix the hardcoding problem. This time we will add two different numbers 2 and 7. But before adding the test method, we need to refactor the existing code in the test file. The below code is used by both the test methods and this is the best candidate to be placed under setup method.

  RSAddition *addition = [[RSAddition alloc] init];

The changed code should look as shown in the below screenshot.

201404132223.jpg

Adding the below method should fail as the addition method is hardcoded to return value as 4.

-(void)testAddTwoPlusSeven {

NSInteger result = [addition addNumberOne:2 withNumberTwo:7];

XCTAssertEqual(result, 9, @”Addition of 2 + 7 is 9″);

}

201404132226.jpg

Now edit the addition method to fix this problem. It requires just a one line change and now the test should pass.

201404132229.jpg

201404132231.jpg

The next tutorial will cover the steps for adding the view controller and required fields for adding two numbers using the above added application logic class.

Download source code from here.

Filed Under: ios, iPhone, Xcode Tagged With: Assertions, iOS, TDD, Xcode, XCTest

Primary Sidebar

TwitterLinkedin

Recent Posts

  • How to block keywords in Jio broadband
  • How to disable opening an app automatically at login in Mac
  • How to set preferred Wifi network on Mac
  • Attribute Unavailable: Estimated section warning before iOS 11.0
  • How to recover Firefox password from Time Machine backup

Pages

  • About
  • Privacy Policy
  • Terms and Conditions

Copyright 2022 © rshankar.com

Terms and Conditions - Privacy Policy