 // MARK: - Tests
 
 #if !FOUNDATION_XCTEST
+var tests = [
+    "test_Calendar_JSON" : TestCodable.test_Calendar_JSON,
+    "test_Calendar_Plist" : TestCodable.test_Calendar_Plist,
+    "test_CharacterSet_JSON" : TestCodable.test_CharacterSet_JSON,
+    "test_CharacterSet_Plist" : TestCodable.test_CharacterSet_Plist,
+    "test_CGAffineTransform_JSON" : TestCodable.test_CGAffineTransform_JSON,
+    "test_CGAffineTransform_Plist" : TestCodable.test_CGAffineTransform_Plist,
+    "test_CGPoint_JSON" : TestCodable.test_CGPoint_JSON,
+    "test_CGPoint_Plist" : TestCodable.test_CGPoint_Plist,
+    "test_CGSize_JSON" : TestCodable.test_CGSize_JSON,
+    "test_CGSize_Plist" : TestCodable.test_CGSize_Plist,
+    "test_CGRect_JSON" : TestCodable.test_CGRect_JSON,
+    "test_CGRect_Plist" : TestCodable.test_CGRect_Plist,
+    "test_CGVector_JSON" : TestCodable.test_CGVector_JSON,
+    "test_CGVector_Plist" : TestCodable.test_CGVector_Plist,
+    "test_DateComponents_JSON" : TestCodable.test_DateComponents_JSON,
+    "test_DateComponents_Plist" : TestCodable.test_DateComponents_Plist,
+    "test_Decimal_JSON" : TestCodable.test_Decimal_JSON,
+    "test_Decimal_Plist" : TestCodable.test_Decimal_Plist,
+    "test_IndexPath_JSON" : TestCodable.test_IndexPath_JSON,
+    "test_IndexPath_Plist" : TestCodable.test_IndexPath_Plist,
+    "test_IndexSet_JSON" : TestCodable.test_IndexSet_JSON,
+    "test_IndexSet_Plist" : TestCodable.test_IndexSet_Plist,
+    "test_Locale_JSON" : TestCodable.test_Locale_JSON,
+    "test_Locale_Plist" : TestCodable.test_Locale_Plist,
+    "test_NSRange_JSON" : TestCodable.test_NSRange_JSON,
+    "test_NSRange_Plist" : TestCodable.test_NSRange_Plist,
+    "test_TimeZone_JSON" : TestCodable.test_TimeZone_JSON,
+    "test_TimeZone_Plist" : TestCodable.test_TimeZone_Plist,
+    "test_URL_JSON" : TestCodable.test_URL_JSON,
+    "test_URL_Plist" : TestCodable.test_URL_Plist,
+    "test_UUID_JSON" : TestCodable.test_UUID_JSON,
+    "test_UUID_Plist" : TestCodable.test_UUID_Plist,
+]
+
+#if os(OSX)
+    tests["test_AffineTransform_JSON"] = TestCodable.test_AffineTransform_JSON
+    tests["test_AffineTransform_Plist"] = TestCodable.test_AffineTransform_Plist
+#endif
+
+if #available(OSX 10.11, iOS 9.0, *) {
+    tests["test_PersonNameComponents_JSON"] = TestCodable.test_PersonNameComponents_JSON
+    tests["test_PersonNameComponents_Plist"] = TestCodable.test_PersonNameComponents_Plist
+}
+
+if #available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *) {
+    // tests["test_DateInterval_JSON"] = TestCodable.test_DateInterval_JSON
+    tests["test_DateInterval_Plist"] = TestCodable.test_DateInterval_Plist
+    // tests["test_Measurement_JSON"] = TestCodable.test_Measurement_JSON
+    // tests["test_Measurement_Plist"] = TestCodable.test_Measurement_Plist
+}
+
 var CodableTests = TestSuite("TestCodable")
-
-#if os(OSX)
-    CodableTests.test("test_AffineTransform_JSON") { TestCodable().test_AffineTransform_JSON() }
-    CodableTests.test("test_AffineTransform_Plist") { TestCodable().test_AffineTransform_Plist() }
-#endif
-
-CodableTests.test("test_Calendar_JSON") { TestCodable().test_Calendar_JSON() }
-CodableTests.test("test_Calendar_Plist") { TestCodable().test_Calendar_Plist() }
-CodableTests.test("test_CharacterSet_JSON") { TestCodable().test_CharacterSet_JSON() }
-CodableTests.test("test_CharacterSet_Plist") { TestCodable().test_CharacterSet_Plist() }
-CodableTests.test("test_CGAffineTransform_JSON") { TestCodable().test_CGAffineTransform_JSON() }
-CodableTests.test("test_CGAffineTransform_Plist") { TestCodable().test_CGAffineTransform_Plist() }
-CodableTests.test("test_CGPoint_JSON") { TestCodable().test_CGPoint_JSON() }
-CodableTests.test("test_CGPoint_Plist") { TestCodable().test_CGPoint_Plist() }
-CodableTests.test("test_CGSize_JSON") { TestCodable().test_CGSize_JSON() }
-CodableTests.test("test_CGSize_Plist") { TestCodable().test_CGSize_Plist() }
-CodableTests.test("test_CGRect_JSON") { TestCodable().test_CGRect_JSON() }
-CodableTests.test("test_CGRect_Plist") { TestCodable().test_CGRect_Plist() }
-CodableTests.test("test_CGVector_JSON") { TestCodable().test_CGVector_JSON() }
-CodableTests.test("test_CGVector_Plist") { TestCodable().test_CGVector_Plist() }
-CodableTests.test("test_DateComponents_JSON") { TestCodable().test_DateComponents_JSON() }
-CodableTests.test("test_DateComponents_Plist") { TestCodable().test_DateComponents_Plist() }
-
-if #available(OSX 10.12, iOS 10.10, watchOS 3.0, tvOS 10.0, *) {
-    // CodableTests.test("test_DateInterval_JSON") { TestCodable().test_DateInterval_JSON() }
-    CodableTests.test("test_DateInterval_Plist") { TestCodable().test_DateInterval_Plist() }
-}
-
-CodableTests.test("test_Decimal_JSON") { TestCodable().test_Decimal_JSON() }
-CodableTests.test("test_Decimal_Plist") { TestCodable().test_Decimal_Plist() }
-CodableTests.test("test_IndexPath_JSON") { TestCodable().test_IndexPath_JSON() }
-CodableTests.test("test_IndexPath_Plist") { TestCodable().test_IndexPath_Plist() }
-CodableTests.test("test_IndexSet_JSON") { TestCodable().test_IndexSet_JSON() }
-CodableTests.test("test_IndexSet_Plist") { TestCodable().test_IndexSet_Plist() }
-CodableTests.test("test_Locale_JSON") { TestCodable().test_Locale_JSON() }
-CodableTests.test("test_Locale_Plist") { TestCodable().test_Locale_Plist() }
-
-if #available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
-    // CodableTests.test("test_Measurement_JSON") { TestCodable().test_Measurement_JSON() }
-    // CodableTests.test("test_Measurement_Plist") { TestCodable().test_Measurement_Plist() }
-}
-
-CodableTests.test("test_NSRange_JSON") { TestCodable().test_NSRange_JSON() }
-CodableTests.test("test_NSRange_Plist") { TestCodable().test_NSRange_Plist() }
-
-if #available(OSX 10.11, iOS 9.0, *) {
-    CodableTests.test("test_PersonNameComponents_JSON") { TestCodable().test_PersonNameComponents_JSON() }
-    CodableTests.test("test_PersonNameComponents_Plist") { TestCodable().test_PersonNameComponents_Plist() }
-}
-
-CodableTests.test("test_TimeZone_JSON") { TestCodable().test_TimeZone_JSON() }
-CodableTests.test("test_TimeZone_Plist") { TestCodable().test_TimeZone_Plist() }
-CodableTests.test("test_URL_JSON") { TestCodable().test_URL_JSON() }
-CodableTests.test("test_URL_Plist") { TestCodable().test_URL_Plist() }
-CodableTests.test("test_UUID_JSON") { TestCodable().test_UUID_JSON() }
-CodableTests.test("test_UUID_Plist") { TestCodable().test_UUID_Plist() }
+for (name, test) in tests {
+    CodableTests.test(name) { test(TestCodable())() }
+}
+
 runAllTests()
 #endif

        return try decoder.decode(T.self, from: data)
    }

    expectRoundTripEquality(of: value, encode: encode, decode: decode)
}

func expectRoundTripEqualityThroughPlist<T : Codable>(for value: T) where T : Equatable {
    let encode = { (_ value: T) throws -> Data in
        return try PropertyListEncoder().encode(value)
    }

    return result
}

func debugDescription<T>(_ value: T) -> String {
    if let debugDescribable = value as? CustomDebugStringConvertible {
        return debugDescribable.debugDescription
    } else if let describable = value as? CustomStringConvertible {
        return describable.description
    } else {
        return "\(value)"
    }
}

func expectRoundTripEquality<T : Codable>(of value: T, encode: (T) throws -> Data, decode: (Data) throws -> T, lineNumber: Int) where T : Equatable {
    let data: Data
    do {
        data = try encode(value)
    } catch {
        fatalError("\(#file):\(lineNumber): Unable to encode \(T.self) <\(debugDescription(value))>: \(error)")
    }

    let decoded: T
    do {
        decoded = try decode(data)
    } catch {
        fatalError("\(#file):\(lineNumber): Unable to decode \(T.self) <\(debugDescription(value))>: \(error)")
    }

    expectEqual(value, decoded, "\(#file):\(lineNumber): Decoded \(T.self) <\(debugDescription(decoded))> not equal to original <\(debugDescription(value))>")
}

func expectRoundTripEqualityThroughJSON<T : Codable>(for value: T, lineNumber: Int) where T : Equatable {
    let inf = "INF", negInf = "-INF", nan = "NaN"
    let encode = { (_ value: T) throws -> Data in
        let encoder = JSONEncoder()
