You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Swift Testing测试含不同类型元素矩阵的泛型函数?

Swift泛型矩阵中心点镜像函数的测试问题

背景情况

我有一个Swift泛型函数,可对任意元素类型的方阵进行中心点镜像:

func pointMirroredMatrix<T>(_ matrix: inout [[T]]) {
    assert(matrix.count > 0 && matrix[0].count > 0) // 确保矩阵非空
    assert(matrix.count == matrix[0].count) // 确保矩阵是方阵
    let n = matrix.count // 矩阵为n×n
    for row in 0 ..< n/2 {
        for col in 0 ..< n {
            // 交换元素
            (matrix[row][col], matrix[n - 1 - row][n - 1 - col]) = (matrix[n - 1 - row][n - 1 - col], matrix[row][col])
        }
    }
}

我想要编写测试验证这个函数的正确性,但由于测试框架的@Test不支持泛型,所以定义了如下测试参数和测试结构:

typealias PointMirroredMatrixParams = (matrix: [[Any]], expectedResult: [[Any]])
let pointMirroredMatrixArgs: [PointMirroredMatrixParams] = [(matrix:         [[0, 1], [0, 0]], 
                                                             expectedResult: [[0, 0], [1, 0]])]

struct VisionTests {
    
    @Test("pointMirroredMatrix", arguments: pointMirroredMatrixArgs)
    func pointMirroredMatrix(p: PointMirroredMatrixParams) throws {
        // 测试逻辑见下文
    }  
}

测试逻辑大致如下:

var mirroredMatrix = deepCopyMatrix(p.matrix) // 创建深拷贝
pointMirroredMatrix(&mirroredMatrix) // 对拷贝执行镜像操作
let mirroredCorrectly = maticesAreEqual(p.expectedResult, mirroredMatrix)
#expect(mirroredCorrectly)  

遇到的问题

我无法正确实现maticesAreEqual函数,因为测试参数的矩阵元素类型是Any。尝试了以下代码但编译失败:

func maticesAreEqual(_ matrix1: [[Any]], _ matrix2: [[Any]]) -> Bool {
    guard matrix1.count == matrix2.count else { return false }
    guard matrix1[0].count == matrix2[0].count else { return false }
    guard !matrix1.isEmpty else { return true }
    guard type(of: matrix1[0][0]) == type(of: matrix2[0][0]) else { return false }
    guard type(of: matrix1[0][0]) == (any Equatable).self else { return false }
    // 此时已知两个矩阵维度相同、元素类型一致且符合Equatable协议
    // 但如何判断元素相等?
    for i in 0 ..< matrix1.count {
        for j in 0 ..< matrix1[i].count {
            if matrix1[i][j] != matrix2[i][j] { return false } // 编译错误
        }
    }
    return true
}  

内层循环的代码无法编译,错误信息为:Type 'Any' cannot conform to 'Equatable'(注:原错误描述有误,实际是Any未遵循Equatable协议,无法直接用!=比较)。

我的问题

如何通过@Test传入不同元素类型的矩阵,来测试pointMirroredMatrix函数?


解决方案

方案1:基于类型擦除实现Equatable比较

通过将Any元素向下转换为any Equatable,并借助扩展方法实现类型安全的相等判断,修改maticesAreEqual函数如下:

func maticesAreEqual(_ matrix1: [[Any]], _ matrix2: [[Any]]) -> Bool {
    guard matrix1.count == matrix2.count else { return false }
    
    for (row1, row2) in zip(matrix1, matrix2) {
        guard row1.count == row2.count else { return false }
        
        for (elem1, elem2) in zip(row1, row2) {
            // 验证元素类型一致且遵循Equatable
            guard let equatable1 = elem1 as? any Equatable,
                  let equatable2 = elem2 as? any Equatable,
                  type(of: equatable1) == type(of: equatable2) else {
                return false
            }
            
            // 调用扩展方法执行相等判断
            if !equatable1.isEqual(to: equatable2) {
                return false
            }
        }
    }
    return true
}

// 给Equatable扩展类型擦除后的比较方法
extension Equatable {
    func isEqual(to other: any Equatable) -> Bool {
        guard let otherTyped = other as? Self else {
            return false
        }
        return self == otherTyped
    }
}

方案2:拆分测试用例,避免使用Any

针对不同元素类型(如Int、String、自定义Equatable类型)单独编写测试函数,绕过泛型参数限制:

struct VisionTests {
    @Test("pointMirroredMatrix_Int")
    func pointMirroredMatrixInt() throws {
        var matrix = [[0, 1], [0, 0]]
        let expected = [[0, 0], [1, 0]]
        pointMirroredMatrix(&matrix)
        #expect(matrix == expected)
    }
    
    @Test("pointMirroredMatrix_String")
    func pointMirroredMatrixString() throws {
        var matrix = [["a", "b"], ["c", "d"]]
        let expected = [["d", "c"], ["b", "a"]]
        pointMirroredMatrix(&matrix)
        #expect(matrix == expected)
    }
}

方案3:用泛型包装器复用测试逻辑

创建泛型测试逻辑函数,在不同测试用例中调用,减少重复代码:

private func runPointMirroredMatrixTest<T: Equatable>(matrix: [[T]], expected: [[T]]) throws {
    var mirrored = matrix
    pointMirroredMatrix(&mirrored)
    #expect(mirrored == expected)
}

struct VisionTests {
    @Test("pointMirroredMatrix_Int")
    func pointMirroredMatrixInt() throws {
        try runPointMirroredMatrixTest(matrix: [[0, 1], [0, 0]], expected: [[0, 0], [1, 0]])
    }
    
    @Test("pointMirroredMatrix_String")
    func pointMirroredMatrixString() throws {
        try runPointMirroredMatrixTest(matrix: [["a", "b"], ["c", "d"]], expected: [["d", "c"], ["b", "a"]])
    }
}

内容的提问来源于stack exchange,提问作者Reinhard Männer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:09:57