彻底测试Swift结构与Equalable一致性的方法?

彻底测试Swift结构与Equalable一致性的方法?,swift,unit-testing,struct,Swift,Unit Testing,Struct,标题几乎说明了一切。我的项目在Swift 2.3中。此外,还引入了自定义结构模型对象。出于各种原因,这必须符合Equalable 例如,让我们有一个包含6个不同值类型变量的结构,所有这些变量都来自Swift标准库 struct Address: Equatable { let firstName: String let lastName: String let street: String let streetNumber: Int let city:

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

例如,让我们有一个包含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)
}
什么是正确的算法来确保我将在单元测试中测试所有(in)相等的组合


排列/组合?也许是一些更具程序性的东西?

我是TDD的新手,但到目前为止我学到的是:

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


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

在这种情况下,彻底测试所有组合只是一个彻头彻尾的糟糕策略。这是不必要的,只会让单元测试变得更麻烦,让您不太可能做好

对于这样一个非常简单的等式函数,有一个很好的例子,您根本不需要测试它。如果你必须测试它,测试一个等式和一个不等式就足够了。如果你真的想发疯,你可以对每个成员进行一次平等测试,六次不平等测试

最好是单独或手动编写测试用例,因为您只需查看单元测试,就应该能够相信单元测试的正确性。如果你不能,那么你可能会陷入一个相当荒谬的境地,不得不对你的单元测试进行单元测试

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

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个可能的组合,因为您有六个成员,在两个结构之间,每对成员可以相等,也可以不相等。在这里,我们有一个helper函数来生成一对结构,该结构基于一个列表,其中成员之间应该相等,还有一个嵌套循环来生成所有可能的对组合。当你比较所有对时,正好有一对应该比较相等,正好有63对应该比较不相等,所以这就是我们所断言的测试条件,因为至少在测试的正确性方面,我们的质量控制有点差劲


相反,如果您手动测试两个或七个案例,那么与这种方式相比,它将更简单、更清晰、更易于阅读和验证,并且需要更少的代码行。

1)您还没有展示您的
Compariable
协议的实现,因此您的问题目前无法回答;2) 我很想知道您打算如何实现地址的小于运算符;3) 除非组合的数量很小,否则您通常不会也不应该对任何可能的组合进行单元测试-在这里,您最多不应该需要超过7个合法的测试用例。啊..总是混淆了Equalable和Compariable…我需要解决这个问题..至于实现,我们已经全部看到了。我发现把它放在这里是没有意义的,结构只是一个例子。而且我坚信我应该测试所有的组合,因为Equalable实现是一个很好的机会,可以避免愚蠢的错误或打字错误,而且测试可能不会打错或漏线。这不是没有意义的。在很多情况下,平等的定义不是通过所有成员的简单比较。例如,取两个地址。英国利兹相思大道10号的约翰·史密斯与英国利兹相思大道10号的简·史密斯相比是否相等?这可能“只是一个例子”,但“正确的算法”取决于你在做什么。例如,它可以在必须测试所有成员的所有组合和不必测试之间产生差异。在示例中,当每个lhs成员等于每个rhs成员时,它是相等的。将其写入6(或N)时间正是我想要避免的。另外,我不认为它是所有可能的组合。欢迎来到TDD。我正在从书中学习TDD。我极力推荐。作者是。他这样做是基于我目前对TDD的有限理解。这是最好的办法。你想要的是不可能的。你必须测试6个独立的表达式。如果你找到更好的方法,一定要让我们知道。我才刚开始……肯定有比你的6个病例更多的病例。你指的是什么病例?那是什么呢!!!!!假设是什么意思?我不知道你需要什么来测试所有64个组合。如果失败,6个就足够了。你能给我一个组合会失败的情况,但简单的6测试不会吗?@Honey:正如我在回答中所说的,我认为你不需要测试所有64个组合。然而,如果测试数据选择不当,这是可能的。例如,如果您将第一个
&&
替换为
|
,并且测试数据中的前两个字段都不同,那么简单的6测试将通过,但是当您测试完整的64时,您会得到一些不正确的等式。我现在明白了,我认为您提到的错误的可能性与其他6相同,或者可能稍微少一点,这使得它有足够的理由进行测试。
 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, ...
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)
    }

}