1

I'm writing scripts in Xcode to run some UI Tests and I wanted to use some global variables.
My first attempt was to declared a variable in @interface with type strong like so:

@interface Extended_Tests : XCTestCase
@property (strong) NSMutableArray *list;
@property (strong) NSString *name;
@end

but that didn't work.
I ended up using the old-fashioned C way of declaring the variable outside the methods.

My question is, why didn't this work? Why don't the values in the variables persist across all methods?

EDIT: My methods:

- (void)testMultiUser1 {
    [[[XCUIApplication alloc] init] launch];
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.buttons[@"Sign-in button"] tap];
    sleep(5);
    user1 = [app.staticTexts elementBoundByIndex:0].label;
    [app.otherElements[@"LibraryView"] tap];
    sleep(5);
    _list = [[NSMutableArray alloc] init];
    for(int i = 0; i < 3; i++){
        XCUIElementQuery *file1 = [[app.cells elementBoundByIndex:i] descendantsMatchingType:XCUIElementTypeStaticText];
        NSString *number = [file1 elementBoundByIndex:0].label;
        [_list addObject:number];
    }
    XCTAssert(_list);
}

I expected this to save the variables into the array _list so I can use it in another method like this:

-(void)testMultiUser3{
    //Go into Library and make sure top 3 files are different from user1
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.otherElements[@"LibraryView"] tap];
    sleep(5);

    NSMutableArray *user2files = [[NSMutableArray alloc] init];
    for(int i = 0; i < 3; i++){
        XCUIElementQuery *list1 = [[app.cells elementBoundByIndex:i] descendantsMatchingType:XCUIElementTypeStaticText];
        NSString *number = [list1 elementBoundByIndex:0].label;
        [user2files addObject:number];
    }
    XCTAssert(!([user2files[0] isEqualToString:_list[0]] && [user2files[1] isEqualToString:_list[1]] && [user2files[2] isEqualToString:_list[2]]));
    }
James Goe
  • 522
  • 4
  • 14
  • 1
    The little bit of code you posted doesn't declare any variables. It declares two properties. Perhaps you should update your question with more relevant code showing what you really did and explain what exact issue you had. – rmaddy Dec 17 '15 at 19:51

1 Answers1

3

Your problem is specific to XCTest.

Each test that is run is run in a new instance of your test case class. In your case, a new Extended_Tests object is instantiated for every test. That's why if you set either of your variables in one test, you won't see those changes in another.

Generally speaking it's best if tests don't rely on side-effects of other tests since you will not be able to run those tests on their own. It's best if you make a shared setup method to set up the state and use from both states.

If you absolutely must share variables between the tests, then you can use class static methods (those declared with a + instead of a -) with static variables or use global variables as you did.

Oz Solomon
  • 2,969
  • 23
  • 22
  • Objective-C doesn't have class properties. It has class methods though. – NobodyNada Dec 17 '15 at 21:24
  • Yes, true, but you can simulated them using any one of the methods here: http://stackoverflow.com/questions/695980/how-do-i-declare-class-level-properties-in-objective-c – Oz Solomon Dec 17 '15 at 21:26
  • Maybe reword your answer as @NobodyNada is technically correct. However a better reference might be [Setting Static Variables in Objective-C](http://stackoverflow.com/questions/15979973/setting-static-variables-in-objective-c/15980334#15980334), but then maybe I'm biased ;-) – CRD Dec 17 '15 at 21:48
  • Ohhhh I see. Thanks for the help guys! – James Goe Dec 18 '15 at 02:13