iOS自动化测试包括 UI测试 和数据测试两个方面。
UI测试:
UITest介绍
XCUIApplication *app = [[XCUIApplication alloc] init];
XCUIElement *element = [[[[app.otherElements containingType:XCUIElementTypeNavigationBar identifier:@"View"] childrenMatchingType:XCUIElementTypeOther].element childrenMatchingType:XCUIElementTypeOther].element childrenMatchingType:XCUIElementTypeOther].element;
XCUIElement *textField = [[element childrenMatchingType:XCUIElementTypeTextField] elementBoundByIndex:0];
[textField tap];
[textField typeText:@"Blank_佐毅"];
XCUIElement *textField2 = [[element childrenMatchingType:XCUIElementTypeTextField] elementBoundByIndex:1];
[textField2 tap];
XCUIElement *moreNumbersKey = app/*@START_MENU_TOKEN@*/.keys[@"more, numbers"]/*[[".keyboards.keys[@\\\\"more, numbers\\\\"]",".keys[@\\\\"more, numbers\\\\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/;
[moreNumbersKey tap];
[textField2 typeText:@"123"];
[app.buttons[@"Login"] tap];
XCUIApplication。这是你正在测试的应用的代理。它能让你启动应用,这样你就能执行测试了。它每次都会新起一个进程,这会多花一些时间,但是能保证测试应用时的状态是干净的,这样你需要处理的变量就少了些。
XCUIElement。这是你正在测试的应用中UI元素的代理。每个元素都有类型和标识符,结合二者就能找到应用中的UI元素。所有的元素都会嵌套在代表你的应用的树中。
XCUIElementQuery。 当你想要找到某个元素时,就会用到 element query。每个 XCUIElement 里都包含一个query。这些query搜索 XCUIElement 树, 必须要找到一个匹配的。否则当你视图访问该元素时,测试就会失败。 例外是exists 属性,你可以使用这个属性来检查一个元素是否展示在树中。 这对于断言很有用。 更一般地你可以使用 XCUIElementQuery 来找到对accessibility可见的元素。Query会返回结果的集合。
数据测试(行为驱动测试)
BDD DSL 测试
【行为驱动测试-Objc中国】(http://objccn.io/issue-15-1/)
SpecBegin 声明了一个名为StalkerSpec 测试类. SpecEnd 结束了类声明。
describe 块声明了一组实例。
context 块的行为类似于 describe 。
it 是一个单一的例子 (单一测试)。
beforeEach 是一个运行于所有同级块和嵌套块之前的块。
可能你已经注意到,几乎在这种 DSL 中定义的所有组件由两部分都组成:一个字符串值定义了什么被测试,以及一个包含了测试其本身或者更多组件的块。这些字符串有两个非常重要的功能。
首先,在 describe 块内,这些字符串将联系紧密的被测试的一部分特性的行为进行分组描述 。因为你可以按意愿指定任意多的嵌套块,你可以基于对象或者它们的依赖关系的上下文来编写的不同的测试。
#define EXP_SHORTHAND
#import "Expecta.h"
#import "Specta.h"
#import "NSObject+BPStalker.h"
SpecBegin(Stalker)
describe(@"objectWithStalker", ^{
__block NSMutableDictionary *objectToBeObserved;
__block NSObject *objectWithStalker;
__block NSString *testNotification;
beforeEach(^{
//
objectWithStalker = [[NSObject alloc] init];
objectToBeObserved = [@{ @"one" : @1,@"two" : @2 } mutableCopy];
testNotification = @"TEST_NOTIFICATION";
});
it(@"should have a stalker", ^{
expect(objectWithStalker.stalker).toNot.beNil;
});
it(@"should be able to observer changes", ^{
__block BOOL objectChanged = NO;
__block NSInteger blockCalled = 0;
[objectWithStalker.stalker whenPath:@"one"
changeForObject:objectToBeObserved
options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
then:^(NSMutableDictionary *object, NSDictionary *change) {
expect(object[@"one"]).to.equal(@1);
blockCalled++;
}];
[objectWithStalker.stalker whenPath:@"two"
changeForObject:objectToBeObserved
options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
then:^(NSMutableDictionary *object, NSDictionary *change) {
blockCalled++;
if (objectChanged)
expect(object[@"two"]).to.equal(@3);
else
expect(object[@"two"]).to.equal(@2);
}];
objectChanged = YES;
objectToBeObserved[@"two"] = @3;
expect(blockCalled).to.equal(3);
});
it(@"s stalker KVO shoud be removed when it is deallocated", ^{
__block NSInteger blockCalled = 0;
@autoreleasepool
{
NSObject *objectWithStalker = [[NSObject alloc] init];
[objectWithStalker.stalker whenPath:@"one"
changeForObject:objectToBeObserved
options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
then:^(NSMutableDictionary *object, NSDictionary *change) {
blockCalled++;
}];
expect(blockCalled).to.equal(1);
objectToBeObserved[@"one"] = @3;
expect(blockCalled).to.equal(2);
}
objectToBeObserved[@"one"] = @4;
objectToBeObserved[@"one"] = @10;
expect(blockCalled).to.equal(2);
});
it(@"should be able to listen to notifications", ^{
__block NSInteger blockCalled = 0;
[objectWithStalker.stalker when:testNotification
then:^(NSNotification *notification) {
expect(notification.object).to.equal(@1);
blockCalled++;
}];
expect(blockCalled).to.equal(0);
[objectWithStalker.stalker.notificationCenter postNotificationName:testNotification object:@1];
expect(blockCalled).to.equal(1);
});
it(@"s stalker notification observing shoud be removed when it is deallocated", ^{
__block NSInteger blockCalled = 0;
@autoreleasepool
{
NSObject *objectWithStalker = [[NSObject alloc] init];
[objectWithStalker.stalker when:testNotification
then:^(NSNotification *notification) {
blockCalled++;
}];
expect(blockCalled).to.equal(0);
[objectWithStalker.stalker.notificationCenter postNotificationName:testNotification object:@1];
expect(blockCalled).to.equal(1);
}
[objectWithStalker.stalker.notificationCenter postNotificationName:testNotification object:@1];
expect(blockCalled).to.equal(1);
}); });
SpecEnd
如果界面UI元素中出现中文,UITest脚本报错,使用下边方法解决:
You can use the following workaround as this seems to be a bug in xcode: replace all \U to \u and it should work.