![](/img/trans.png)
[英]Automatic synthesis of Equatable conformance for Swift struct or enum through an extension
[英]Approach to exhaustively test Swift struct conformance to Equatable?
標題幾乎說明了一切。 我的項目是在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)
}
什么是正確的算法,以確保我將在單元測試中測試所有 (in)相等的組合?
排列/組合? 也許是更程序化的東西?
在這種情況下,詳盡地測試所有組合只是一個完全不好的策略。 這是不必要的,僅用於使單元測試更麻煩,並且使您不太可能做得好。
有了這樣一個非常簡單的相等函數,有一個很好的例子,你根本不需要測試它。 如果你必須對它進行測試,那么測試一個案例是否相等,一個案例是不平等,這就足夠了。 如果你真的想要瘋狂,你可以進行一次平等測試,並對每個成員進行六次不平等測試。
最好單獨和手動寫出測試用例,因為只要看一下它就應該能夠相信單元測試的正確性。 如果你不能,那么你可能最終處於相當荒謬的位置,不得不對你的單元測試進行單元測試。
但是,如果你真的絕對堅持以錯誤的方式做事並詳盡地測試每一種可能的組合,那么你可以這樣做:
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個應該比較不相等,所以這些是我們斷言的測試條件,因為至少那時我們有某種表兄弟對我們測試的正確性進行質量控制。
相反,如果您手動測試了兩個或七個案例,那么它會比這樣做更簡單,更清晰,更易於閱讀和驗證,並且占用更少的代碼行。
我是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結構相等性,每次填充Address相同的所有屬性, 除了一個。 所以基本上你必須寫這個函數6次。
你有6個等於測試。 它們是獨立的表達,需要獨立對待。 這是我所知道的最好的編程方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.