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

Posted

技术标签:

【中文标题】UndoManager 的 undo 方法在测试时执行 registerUndo 的次数【英文标题】:undo method of UndoManager execute number of times the registerUndo while testing 【发布时间】:2021-01-04 13:32:37 【问题描述】:

我只从 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方法?

最后,感谢您对这个问题的思考,这是用糟糕的英语写成的。

【问题讨论】:

【参考方案1】:

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

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

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

 undoManager.setGroupByEvent = NO
 

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

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

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

【讨论】:

谢谢你,我得到了帮助!!我的测试成功了!

以上是关于UndoManager 的 undo 方法在测试时执行 registerUndo 的次数的主要内容,如果未能解决你的问题,请参考以下文章

Ace 编辑器暂停/禁用 UndoManager

UndoManager 和多个 MOC

如何使宏“原子”

带有异步或长时间运行任务的 UndoManager

如何将 undoManager 与核心数据实体一起使用

如何使用 UndoManager 确定文档是不是有未保存的更改