UndoManager的undo方法在测试时执行registerUndo的次数

问题描述 投票:0回答:1

我只从 TestClass 中调用了 undoMethod 一次。但是undo方法执行了registerUndo的次数。

这是我的测试课。

import XCTest
@testable import UnitTestProject

class UnitTestProjectTests: XCTestCase {

    func testUndo() {
        let model = TestModel()
        
        model.increment()
        XCTAssertEqual(model.count, 1)
        
        model.increment()
        XCTAssertEqual(model.count, 2)
        
        model.increment()
        XCTAssertEqual(model.count, 3)
        
        model.undo()
        XCTAssertEqual(model.count, 2)
        
    }
}

这是目标班级。

import Foundation

class TestModel {
    
    let undoManager = UndoManager()
    var count = 0
    
    func registerUndo() {
        if (undoManager.isUndoRegistrationEnabled) {
            undoManager.registerUndo(withTarget: self, handler: { _ in
                print("undo is executed")
                self.count -= 1
            })
        }
    }
    
    func increment() {
        count += 1
        registerUndo()
    }
    
    func undo() {
        if(undoManager.canUndo){
            undoManager.undo()
        }
    }
}

如您所见,此测试代码仅调用了一次 undo 方法。但是undo方法实际上调用了3次,所以这个测试会失败。

this is console log
Test Case '-[UnitTestProjectTests.UnitTestProjectTests testUndo]' started.
undo is executed
undo is executed
undo is executed
/Users/project/UnitTestProject/UnitTestProjectTests/UnitTestProjectTests.swift:27: error: -[UnitTestProjectTests.UnitTestProjectTests testUndo] : XCTAssertEqual failed: ("0") is not equal to ("2")
Test Case '-[UnitTestProjectTests.UnitTestProjectTests testUndo]' failed (0.019 seconds).
Test Suite 'UnitTestProjectTests' failed at 2021-01-04 22:21:43.585.
     Executed 1 test, with 1 failure (0 unexpected) in 0.019 (0.020) seconds
Test Suite 'UnitTestProjectTests.xctest' failed at 2021-01-04 22:21:43.585.
     Executed 1 test, with 1 failure (0 unexpected) in 0.019 (0.021) seconds
Test Suite 'Selected tests' failed at 2021-01-04 22:21:43.586.
     Executed 1 test, with 1 failure (0 unexpected) in 0.019 (0.023) seconds

我想问以下2点。

・为什么测试时这个undo方法执行了registerUndo的次数?

・如何测试像这样的Undo和Redo方法?

最后,感谢您用蹩脚的英语对这个问题进行思考。

swift testing xctest
1个回答
5
投票

默认情况下,undoManager 将同一运行循环周期内执行的所有操作分组。在您的示例中,您执行三个连续的操作,因此这三个操作构成 undoManager 堆栈中的单个组。在撤消时,三个操作一次恢复,这就是为什么您会看到处理程序块被调用三次而不是一次。

您可以更改默认行为,但代价是您自己管理分组,因为任何操作,即使是单个操作,都必须包含在一个组中。我给你一个例子,但请考虑到我是一个 Objective-C 用户并且没有 Swift 的实践(幸运的是这里的语法非常简单)。

首先,您应该停用自动对操作进行分组的默认行为:

 undoManager.groupsByEvent = false
 

然后,每次调用 registerUndo 都应该包含对 beginUndoGrouping 和 endUndoGrouping 的调用(可以使用专用函数来简化):

undoManager.beginUndoGrouping()
undoManager.registerUndo(withTarget: self, handler: { _ in
            print("undo is executed")
            self.count -= 1
        })
undoManager.endUndoGrouping()

现在,您必须调用 undo 三次才能获得与示例中相同的结果,并且您应该能够更简单地分解测试。

© www.soinside.com 2019 - 2024. All rights reserved.