【问题标题】:Unit Test for TableView isSelected Scenario SwiftTableView isSelected 场景 Swift 的单元测试
【发布时间】:2021-08-20 01:38:28
【问题描述】:

我有一个简单的场景和tableView。

我需要选择 3 个单元格,即使我滚动它也会保持原样。我可以选择 1、2 或 3 个单元格,但不能选择 4 个或更多。当我选择 4 个单元格时,什么都不会发生。如果有 3 个选定的单元格并且我单击其中一个单元格,则应取消选择我选择的单元格。到目前为止,一切都很好。感谢@vadian 的帮助,我可以做到这一点,如下所示。 但是我尝试了整天为这种情况编写单元测试但无法处理它..我决定向帮助社区寻求帮助,但仍然找不到方法..

问题是:我怎样才能为这种情况编写一个好的方法的单元测试?

    /// My Model ///

struct Item: Codable {
    
    let name: String
    let image: String
   
    var isSelected = false
   
    enum CodingKeys: String, CodingKey {
        case name = "name"
        case image = "image"
      
    }
}

// MARK: - UITableViewDelegate
extension ViewController: UITableViewDelegate {

let items = [Item]() // fetched from network, there is item objects inside it.

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        items[indexPath.row].isSelected.toggle()
        tableView.reloadRows(at: [indexPath], with: .automatic)
        
    }
    
    func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
                
        return items[indexPath.row].isSelected || items.filter{$0.isSelected}.count < 3 ? indexPath : nil

    }
}
// MARK: - UITableViewDataSource
extension ItemViewModel: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Food", for: indexPath) as! FoodTableViewCell
        
        let item = self.items[indexPath.row]

        cell.isSelected = item.isSelected
      
        return cell
    }
  }
}

【问题讨论】:

  • @matt 对不起我的错。
  • "我想我的问题很简单" 其实不是。单元测试表视图行为是可能的,但它需要一些非常复杂的重构和模拟。所以这实际上是一个很大的问题。我不是说这是一个坏问题!但是暗示“这应该很简单”是错误的。你现在可能会更好地使用 UI 测试。
  • 谢谢你,马特你是对的,但我只是想基本上测试这种行为的功能。如果您回答我该怎么做,我将不胜感激。我应该嘲笑我的对象吗?我的意思是 7 个对象并检查最多 4 个可选对象?请至少给我指路

标签: ios swift unit-testing


【解决方案1】:

当然,您可以为 tableView 操作编写许多单元测试,但我同意 Matt 的观点,即“这应该很简单”。您的 ViewModel 需要根据“单独关注”原则进行处理,否则需要对其进行重构。我假设您将所有逻辑移到 ViewModel 中,然后您可以编写如下单元测试。

import Foundation

class YourViewControllerTest: XCTestCase {
    
    var viewModel: ItemViewModel!
    fileprivate var fetcher: MockItemFetcher!
    
    var tableView: UITableView!
    
    override func setUp() {
        super.setUp()
        
        fetcher = MockItemFetcher()
        viewModel = ItemViewModel(fetchable: fetcher)
        
    }
    
    override func tearDown() {
        viewModel = nil
        fetcher = nil
        tableView = nil
        super.tearDown()
    }
    
    /// test the one cell can be selectable or not
    func test_did_select_a_cell() {
        
        let items = [Item(name: "", image: "",)]
        // given
        fetcher.items = items
        viewModel.fetchItems()
        
        let viewController = YourViewController()
        let tableView = UITableView()
        viewController.viewModel = viewModel
        
        // when
        viewController.tableView(tableView, didSelectRowAt: IndexPath(row: 0, section: 0))
        let willBeSelected = viewController.tableView(tableView, willSelectRowAt: IndexPath(row: 0, section: 0))
        
        // then
        XCTAssertNotNil(willBeSelected)
        XCTAssertTrue(viewModel.items.value[0].isSelected) // please note that items need to be binded - viewmodel-view
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2010-10-20
    相关资源
    最近更新 更多