Common tests for KIF automated UI testing for iOS

Example tests for KIF

See if a view is displayed.

it(@"should be able to load a table view controller", ^{
     [tester waitForViewWithAccessibilityLabel:@"Locations Table"];
}

Tap a cell in a table view controller.

it(@"should be able to tap a cell in a table view controller", ^{
     NSIndexPath *thirdLocation = [NSIndexPath indexPathForRow:2 inSection:0];
     [tester tapRowAtIndexPath:thirdLocation inTableViewWithAccessibilityIdentifier:@"Locations Table"];
}

Tap a view (such as a button)

it(@"should be able to tap a cell in a table view controller", ^{
      [tester tapRowAtIndexPath:thirdLocation inTableViewWithAccessibilityIdentifier:@"Locations Table"];
}

Check text of a cell

it(@"should have the correct third element in the table view", ^{
       NSIndexPath *thirdLocation = [NSIndexPath indexPathForRow:2 inSection:0];
       UITableViewCell *cell = (UITableViewCell*)[tester waitForCellAtIndexPath:thirdLocation inTableViewWithAccessibilityIdentifier:@"Locations Table"];
       expect(cell.textLabel.text).to.equal(@"Statue Of Liberty");
       expect(cell.detailTextLabel.text).to.equal(@"1");
});

Accessibility Label

KIF is relying on the accessibility label to find the views on the app. The accessibility label is on the identity inspector or it can be set programmatically.

Accessibility Label
Accessibility Label. Make sure it’s enabled.

Programmatically (in viewDidLoad of a table view controller for example):

self.tableView.accessibilityIdentifier = @"Trivia Table";

Flatiron School Week 3 Questions and Answers (Cool stuff I found this week)

Question: How do I got a progress bar to update on it’s own? 

Answer: Use a NSTimer with a UIProgressView. Stack Overflow


Question: What method is called after a UITableViewCell is tapped?

Answer: didSelectRowAtIndexPath


Question: What’s the thing that allows you to toggle a playlist sort by artist, album and title?

Answer: UISegmentedControl. It’s like a switch that has more than 2 settings.


Question: How should I make a static table view?

Answer: Use a table view with static cells, do not try to make a table view with dynamic cells. It’s a major waste of time.

Week 3 Mistakes and Lessons

Topics this week: TableViewControllers

Symptom: When I see an empty table view controller, this is usually the culprit. 

Mistake: Forgetting to initializing the array in a table view controller.

Lesson: always initialize the array.


Symptom: The dreaded Apple Mach-O Linker Error. Linker command failed with exit code 1. This error is super intimidating because it’s so cryptic. (What the heck does that mean anyway?)

Mistake: Turned out that I had imported a KIF test file “TableViewControllerSpec.m” into another TableViewControllerSpec.m and it was giving the errors:

duplicate symbol _OBJC_METACLASS_$_TableViewControllerSpec ...
duplicate symbol _OBJC_CLASS_$_TableViewControllerSpec ...

Lesson: Don’t quit when you hit error messages. Read the logs, it usually gets you close to the problem.


Symptom: Realizing that the full solution to a problem is not worth implementing and not having the previous version. 

Mistake: Deleting code when it’s a partial solution to go for a full solution.

Lesson: Commit code before trying an experimental solution.


Symptom: Tests fail sometimes but not all the time.

Mistake: Not resetting the test conditions after each or before each tests. Test do not go on in order in KIF.

Lesson: Check the starting condition each time before a test is run. Resetting the tester is cool.

Week 2 Questions and Answers

Topics

  • “Deprecated”

  • Storyboard or programmatic views

  • Mystery letters next to file names

  • Designated initializer

  • _instanceVariables in inits and setters


Question: When I look at Storyboard segues, there’s the word deprecated next to push segues. What does deprecated mean?

Answer: Apple will not be phasing out that features soon in the next release. It looks like they’re replaced the push segue with a show segue.


Question: Should I be learning to use the storyboard or learning to make views programmatically?

Answer: It depends on the usage. Storyboard is great for building views quickly and with little code. I was told that one major drawback is that it’s almost impossible to merge conflicts on storyboards. This means that when another programming changing the same view, one person’s changes will be lost. This can be mitigated by creating xib files for each classes and one owner per class. Storyboard tutorial for iOS 7.


Question: What are those A, C and M letters next to file names on the project Navigator in Xcode.

Answer: Those are the git version control symbols. A for added. C for conflict. M for modified. More here.


Question: Do I make the base initializer(init) or the custom initializer (initWithName:Birthday:Hometown:) make the designated initializer?

Answer: Use the custom initializer as the dedicated initializer. For the base initializer, use the dedicated initializer and pass in default values. More here. It saves repeated code and makes there one point of failure.


Question: Why should I use _instanceVariable in the init and setter methods instead of self.instanceVariable? I thought that we were supposed to always call methods.

Answer: For one, using self.instanceVariable in the setter will get an infinite loop because it will keep calling setInstanceVariable. There is a thing called key value observing (KVO) (awesome tutorial), which notices whenever the setter method is called for a property. In the init method, we don’t always want other people to know that we’re setting the property value.

Week 2 Mistakes and Lessons

Mistake: Thinking that tests in Specta run in order.

I was running into trouble with a test that setup a BeforeAll statement that initialized the objects and tested the initialized conditions without reinitializing the objects. The test would sometimes pass and sometimes fail. The reason was that another test was changing the variables before the test that tested the initialization was run.

Lesson: They do not! Make sure that the test resets the objects each time by using BeforeEach instead of BeforeAll.


Mistake: Designing apps for one screen size.

I was playing around with a craiglist type app before coming to the Flatiron School and was about to add the item page for each of the listings. In Xcode 5, the UI in the storyboard was in the shape of an iPhone 5s. In Xcode 6, this became a 600 x 600 point box. I learned that since there were now four screen sizes ( 3.5″, 4.0″, 4.7″ and 5.5″ diagonal), Apple wants apps to be able to support the different screen sizes. If you design the app for the 4.0″ screen, the constraints that Storyboard uses will be messed up for the other formats.

Lesson: Design for all four screen sizes. 


Mistake: Giving my classes confusing names.

Here are my class names for a project with a tableview and a detailed view.

ViewListingsTableViewController
Listing
ListingTableViewController
ListingTableViewCell

What’s the difference between the first and third controller? I couldn’t remember and ended up making the first one into ListingDetailsViewController.

Lesson: Make class names self documenting. 


Mistake: Not initializing an array and thinking that an array property is an empty array to begin with. 

If you don’t initialize an array, as in

NSArray *newArray = [[NSArray alloc] init];

(even if it’s a property) then, the new array property is nil and it will not be able to add things to it.

Lesson: Initialize and avoid nils.


Mistake: Staying late to finish something only to oversleep the next day. 

Lesson: Have a hard deadline for when to leave the office.


Mistake: Not selecting the storyboard as the main interface and not being able to see anything on the app.

Lesson: Make sure that General Settings > Deployment Info > Main Interface is not empty. Otherwise, nothing will show up.

Screen Shot 2014-10-11 at 8.26.05 PM

Week 1 Questions and Answers

Question: When should I explicitly write strong vs. weak when declaring properties in class interfaces?

In other words, what is the difference between

@property (strong, nonatomic) NSString *name;

and

@property (nonatomic) NSString *name;

?

And when do I use:

@property (weak, nonatomic) NSString *name;

Answer: I found the answer on Ry’s Objective-C Tutorial, which I think is an amazing reference, because it’s very well organized and comprehensive.

In short,

@property (strong, nonatomic) NSString *name;

and

@property (nonatomic) NSString *name;

are equivalent. However, the first version is better, because there is no doubt. (Learning iOS Development by Maurice Sharp et al. p.79)

An example of when to use weak is when two objects have each other in their properties.

A Person may have a

@property Computer *myComputer;

and a computer may have a

@property Person *owner;

but you would not want to have both properties be strong because it would cause a memory leak (the program will use memory and not give up the memory, slowing down the phone).

In this case, I would make the owner weak because the parent object is the Person and not the computer.

@property (weak) Person *owner;

Question: If I clone a branch from Github and the branch that I wanted was not moved to my local machine, what should I do to get that branch from the remote? 

Answer: git checkout -t origin/<branch name>


Question:

//Should I use
[NSMutableArray new];
//or
[[NSMutableArray alloc] init];
//?

Answer: It’s up to you. The latter is more consistent because sometimes you might

[[NSMutableArray alloc] initWithArry:newArray];

Question:

//Should I use
[newString length];
//or 
newString.length;
//?

Answer: Dot notation is more readable, but opinions may differ, sometimes within the same person. Ex.

Dot notation in Objective-C: 100% Pure Evil

In Which I Embrace Dot Notation