我只从 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方法?
最后,感谢您用蹩脚的英语对这个问题进行思考。
默认情况下,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 三次才能获得与示例中相同的结果,并且您应该能够更简单地分解测试。