在尝试使用UIGestureRecognizer的TDD代码时,我发现没有办法以编程方式验证目标操作。没有这个,我不确定我能否正确测试它。
如果在IB中设置了手势识别器(支持iOS 5+),则在加载NIB / Storyboard时设置目标操作;如果在代码中完成它使用initWithTarget:action:,这两者都意味着没有任何模拟能够检测到目标动作。
我没有想法。如果有人成功测试了UIGestureRecognizer,我可以使用这个建议。
答案 0 :(得分:4)
不幸的是,您正在尝试检查未编写测试的框架类,因此不会公开您要验证的状态。这将使您难以确定是否存在您要检查的目标 - 动作对。在这种情况下,我可以使用三个选项,其中没有一个是很好的解决方案:
您可能能够继承UIGestureRecognizer,覆盖目标操作方法以将已注册的对保存在集合中,然后可以向该类的用户公开,然后调用这些方法的超类实现。不幸的是,你只是为了让测试更容易引入新类,必须记住使用它们,并且可能必须从UIGestureRecognizer转换到你的自定义子类,具体取决于你从哪里获得手势识别器参考。
或者,您的测试可以将新版本的目标操作方法调到UIGestureRecognizer,为您提供跟踪添加目标的钩子。只需确保在完成后将原始方法实现交换回原位,或者将来的测试会出现意外行为。
最后,您可以找到一个私有API调用,它可以让您检查手势识别器上已注册的目标操作。只需确保私有API调用仅保留在测试代码中。
答案 1 :(得分:2)
这就是我在Swift中测试轻敲手势识别器的方法。测试确保执行响应轻击手势的代码。
class OnTap: NSObject {
var closure: ()->()
init(view: UIView, gesture: UIGestureRecognizer, closure:() -> ()) {
self.closure = closure
super.init()
view.userInteractionEnabled = true
view.addGestureRecognizer(gesture)
gesture.addTarget(self, action: "didTap:")
}
func didTap(gesture: UIGestureRecognizer) {
closure()
}
}
class MyClass {
var onTap: OnTap?
var didTap = false
func setupTap() {
let myView = UIView()
onTap = OnTap(view: myView, gesture: UITapGestureRecognizer()) { [weak self] in
self?.didTap = true
}
}
}
class MyGestureTests: XCTestCase {
func testRepondToGesture() {
let obj = MyClass()
obj.setupTap()
obj.onTap?.didTap(UITapGestureRecognizer())
XCTAssert(obj.didTap)
}
}
注意,这是一种单元测试技术。此外,我使用UI测试来确保所有部分在甜蜜的和谐中协同工作。
答案 2 :(得分:1)
我建议将手势识别器子类化如下:
class PanGestureRecognizer: UIPanGestureRecognizer {
let initialTarget: Any?
let initialAction: Selector?
public override init(target: Any?, action: Selector?) {
initialTarget = target
initialAction = action
super.init(target: target, action: action)
}
}
答案 3 :(得分:0)
如果有人对使用私有API的解决方案感兴趣,可以使用UIGestureRecognizer上的以下类别发送手势识别操作。正如乔纳所指出的那样,不要在生产代码中使用它。
@interface GGGestureRecognizerTarget : NSObject{
@public
id _target;
SEL _action;
}
@end
@implementation GGGestureRecognizerTarget
@end
@interface UIGestureRecognizer (GGTest)
- (void)sendActions;
@end
@implementation UIGestureRecognizer (GGTest)
- (void)sendActions{
id targets = [self valueForKey:@"_targets"];
for (GGGestureRecognizerTarget* target in targets) {
[self sendActionToTarget:target];
}
}
- (void)sendActionToTarget:(GGGestureRecognizerTarget*)recognizerTarget{
id target = recognizerTarget->_target;
SEL action = recognizerTarget->_action;
[target performSelector:action withObject:self];
}
@end