【问题标题】:UIAutomation testing with Cocos2d, possible?使用 Cocos2d 进行 UIAutomation 测试,可能吗?
【发布时间】:2013-09-03 19:16:24
【问题描述】:

是否可以将 UIAutomation 与 cocos2d 或任何 opengl 应用程序一起使用?

具体来说,我想使用zucchini framework 来测试我的 cocos2d 游戏,但无论如何它只是使用 UIAutomation。

【问题讨论】:

  • 我也在研究这个。您是否找到任何方法来为 Cocos2D/OpenGL 应用程序编写自动化测试?
  • 少量进展...使用 UIAutomation,您显然可以说“点击这些坐标”。不多,但这是一个开始。请参阅此处的第一个回复。 answers.oreilly.com/topic/…
  • 我们可能对 KIF 框架有更好的运气。它的测试是用 Objective-C 编写的,并作为应用程序的一部分运行。因此它可以直接查询应用程序以获取某些元素的坐标。不过我真的很喜欢西葫芦的样子。
  • 将看看 KIF... 我对 UIAutomation 方法有了进一步的想法。在调试模式下,我们可以让每个 Cocos2D 节点生成一个关联的虚拟 UIKit 元素,定位和命名有用,然后我们可以断言 UIKit 元素的属性。
  • KIF 看起来不错,但我想我会尝试使用 UIAutomation 或 Zucchini 搞定一些东西。会放到 Github 上。

标签: cocos2d-iphone bdd ios-ui-automation zucchini


【解决方案1】:

您可以在 Zucchini 中创建自定义步骤并指定要点击的坐标,例如

'Choose the red bird' : ->
   target.tap({x:278, y:36})

'Press Fire' : ->
   target.tap({x:170, y:260}) 

【讨论】:

  • 太棒了......断言/测试方面的事情怎么样?
【解决方案2】:

所以,我开始使用 calabash-iOS 并扩展它的后门。这仅适用于初学者,但通过它您可以获得当前 CCScene 的可访问性标签,因此您可以检查当前在哪个屏幕上,从而用于脚本操作。我不习惯使用 objc 运行时,但正如您所见,它可以获取属性、方法等。多一点挖掘,应该可以包装更多功能,希望也能包装 cocos2d CCNode 结构.这是一项正在进行的工作。

要使用它,您需要安装https://github.com/calabash/calabash-ios,然后在应用程序委托中实现以下功能。不要忘记在代码中将 .accessibilityLabel 设置为 @"menu"、@"game" 或类似名称。理想情况下,仅对于 *-cal 目标,您不希望在生产构建中使用此代码。

-(NSString*)calabashBackdoor:(NSString*)aIgnorable {
    DLog(@"calabashBackdoor: %@", aIgnorable);

//  UIApplication* app = [UIApplication sharedApplication];
    if (aIgnorable != nil) {
        NSArray* p = [aIgnorable componentsSeparatedByString:@" "];
        NSString* command = [p objectAtIndex:0];

        if ([command isEqualToString:@"getCurrentSceneLabel"]) {
            CCDirector* director = [CCDirector sharedDirector];
            DLog(@"director.runningScene.accessibilityLabel: %@", director.runningScene.accessibilityLabel);
            return director.runningScene.accessibilityLabel;
        }
        else if ([command isEqualToString:@"class_copyMethodList"]) {
            CCDirector* director = [CCDirector sharedDirector];
            id inspectThisObject = director.runningScene;
            DLog(@"inspectThisObject: %@, %@", [inspectThisObject class], inspectThisObject);
            unsigned int count;

            // To get the class methods of a class, use class_copyMethodList(object_getClass(cls), &count).
            Method* methods = class_copyMethodList(object_getClass(inspectThisObject), &count);
            //NSMutableString* returnstring = [NSMutableString string];
            NSMutableArray* arrayOfMethodnames = [NSMutableArray array];
            if (methods != NULL) {
                for (int i = 0; i < count; i++) {
                    Method method = methods[i];
                    NSString* stringMethod = NSStringFromSelector(method_getName(method)); //NSStringFromSelector(method->method_name);
                    [arrayOfMethodnames addObject:stringMethod];
                }
                // An array of pointers of type Method describing the instance methods implemented by the class—any instance methods implemented by superclasses are not included. The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
                free(methods);
            }
            DLog(@"arrayOfMethodnames: %@", arrayOfMethodnames);
            return [arrayOfMethodnames componentsJoinedByString:@","];
        }
        else if ([command isEqualToString:@"class_copyPropertyList"]) {
            CCDirector* director = [CCDirector sharedDirector];
            id inspectThisObject = director.runningScene;
            DLog(@"inspectThisObject: %@, %@", [inspectThisObject class], inspectThisObject);
            unsigned int count;

//          An array of pointers of type objc_property_t describing the properties declared by the class. Any properties declared by superclasses are not included. The array contains *outCount pointers followed by a NULL terminator. You must free the array with free().
//
//          If cls declares no properties, or cls is Nil, returns NULL and *outCount is 0.
//          
            objc_property_t* properties = class_copyPropertyList(object_getClass(inspectThisObject), &count);

            NSMutableArray* arrayOfProperties = [NSMutableArray array];
            if (properties != NULL) {
                for (int i = 0; i < count; i++) {
                    objc_property_t property = properties[i];
                    const char* CCS = property_getName(property);
                    NSString* str = [NSString stringWithUTF8String:CCS];
                    [arrayOfProperties addObject:str];
                }
                free(properties);
            }
            DLog(@"arrayOfProperties: %@", arrayOfProperties);
            return [arrayOfProperties componentsJoinedByString:@","];           
        }
        else {
            DLog(@"Unhandled command: %@", command);
        }
    }

    return @"calabashBackdoor nil!";
}

在 Prefix.pch 中放这个

#ifdef DEBUG
#   define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#   define DLog(...) /* */
#endif
#define ALog(...) NSLog(__VA_ARGS__)

当你获得 calabash-ios 并运行时,将其添加到 step_definitions/somesteps.rb 中:

Then(/^I backdoor (.+)$/) do |x|
  backdoor("calabashBackdoor:", x)
end

【讨论】:

  • 其实...不知道我在想什么,但遍历 CCNode 结构...我根本不需要 objc 运行时。这是很有可能的,我已经实现了一些脚本来玩我的游戏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 2016-08-28
  • 2012-05-12
相关资源
最近更新 更多