彻底测试Swift结构符合Equatable的方法?

时间:2016-11-16 23:35:31

标签: swift unit-testing struct

标题几乎说明了一切。我的项目是在Swift 2.3中。 Ocassionaly引入了一个自定义结构模型对象。由于各种原因,这必须符合Equatable。

例如,让我们有一个包含6个不同值类型变量的结构,全部来自Swift标准库。

struct Address: Equatable {

    let firstName: String
    let lastName: String
    let street: String
    let streetNumber: Int
    let city: String
    let countryCode: Int
}

func ==(lhs: Address, rhs: Address) -> Bool {

    return (
        lhs.firstName == rhs.firstName &&
        lhs.lastName == rhs.lastName &&
        lhs.street == rhs.street &&
        lhs.streetNumber == rhs.streetNumber &&
        lhs.city == rhs.city &&
        lhs.countryCode == rhs.countryCode)
}

确保在单元测试中测试 ALL (in)相等组合的正确算法是什么?

排列组合/组合?也许是更程序化的东西?

2 个答案:

答案 0 :(得分:2)

在这种情况下,详尽地测试所有组合只是一个完全不好的策略。它是不必要的,仅用于使单元测试更麻烦,并且使您不太可能做得好。

通过这样一个非常简单的平等功能,可以做出一个很好的例子,你根本不需要对它进行测试。如果你必须对它进行测试,那么测试一个案例是否相等,一个案例是不平等,这就足够了。如果你真的想要疯狂,你可以进行一次平等测试,并对每个成员进行六次不平等测试。

最好单独和手动写出测试用例,因为只要看一下,你就应该能够相信单元测试的正确性。如果你不能,那么你可能最终处于相当荒谬的位置,不得不对你的单元测试进行单元测试。

然而,如果你真的绝对坚持以错误的方式做事并详尽地测试每一种可能的组合,那么你可以这样做:

func makeAddressPair(sames: [Bool]) -> (Address, Address) {
    let firstName = ["John", sames[0] ? "John" : "Jane"]
    let secondName = ["Smith", sames[1] ? "Smith" : "Williams"]
    let street = ["Acacia Avenue", sames[2] ? "Acacia Avenue" : "Privet Close"]
    let streetNumber = [10, sames[3] ? 10 : 21]
    let city = ["Leeds", sames[4] ? "Leeds" : "Bolton"]
    let country = [1, sames[5] ? 1 : 2]

    return (Address(firstName: firstName[0], lastName: secondName[0], street: street[0],
                    streetNumber: streetNumber[0], city: city[0], countryCode: country[0]),
            Address(firstName: firstName[1], lastName: secondName[1], street: street[1],
                    streetNumber: streetNumber[1], city: city[1], countryCode: country[1]))

}

class AddressCompareTests: XCTestCase {

    func testAddressCompare() {
        var comparesEqual = 0
        var comparesInequal = 0

        for a in [true, false] {
            for b in [true, false] {
                for c in [true, false] {
                    for d in [true, false] {
                        for e in [true, false] {
                            for f in [true, false] {
                                let (first, second) = makeAddressPair(sames: [a, b, c, d, e, f])

                                if first == second {
                                    comparesEqual += 1
                                }
                                else {
                                    comparesInequal += 1
                                }
                            }
                        }
                    }
                }
            }
        }

        XCTAssertEqual(comparesEqual, 1)
        XCTAssertEqual(comparesInequal, 63)
    }

}

您有2 ^ 6 = 64种可能的组合,因为您有六个成员,并且在两个结构之间,每对成员可以相等或不相等。这里我们有一个辅助函数来生成一对结构,这些结构基于哪些成员应该在它们之间相等,以及一个嵌套循环来生成所有可能的对组合。当你比较所有的对时,恰好一个应该比较相等,而63个应该比较不相等,所以这些是我们断言的测试条件,因为至少那时我们有某种表兄弟对我们测试的正确性进行质量控制。

如果您手动测试了两个或七个案例,那么它会比这样做更简单,更清晰,更易于阅读和验证,并且占用更少的代码行。

答案 1 :(得分:0)

我是TDD的相对新手,但这是我迄今所学到的:

辅助功能

 func performNotEqualTestWithAddresssProperties(firstNameF: String, firstNameS: String, LastNameF: String, LastNameS: String, streetF: String, streetS: String streetNumberF: Int, streetNumberS: Int, cityF: String, cityS: String, countryCodeF : Int, countryCodeS : Int){
  let AddressFirst = Address(firstName: firstNameF, LastName:LastNameF, street: streetF, streetNumber: streetNumberF, city : cityF, countryCode: countryCodeF)
  let AddressSecond = Address(firstName: firstNameS, LastName:LastNameS, street: streetS, streetNumber: streetNumberS, city : cityS, countryCode: countryCodeS)

  XCTAssertNotEqual(AddressFirst, AddressSecond, "Addresses are not equal")

  // 'F' means first, 'S' means second, I just avoided to not have long lines
 // The helper function takes 2 sets of Addresses and Asserts if they ARE equal

    }

实际测试

 func testWhenAddressDiffers_SHouldNotBeEqual() {
performNotEqualTestWithAddresssProperties(firstNameF: "Earl", firstNameS: "Earl", LastNameF: "Grey", LastNameS: "Grey", streetF: "south", streetS: "south", streetNumberF: 23, streetNumberS: 23, cityF: "silicon valley", cityS: "silicon valley", countryCodeF: 24, countryCodeS: 29)

//write another and switch firstName,another and switch LastName, ...

这里我只测试了countryCode。所有其他元素都是一样的。 要完全测试您的Address结构相等性,每次填充地址相同之外的所有属性。所以基本上你必须写这个函数6次。

你有6个等于测试。它们是独立的表达,需要独立对待。这是我所知道的最好的编程方式。