Articles, podcasts and news about Swift development, by John Sundell.

Throwing tests and LocalizedError

Published on 25 Jan 2018
Discover page available: Unit Testing

Swift tests can throw, which is super useful in order to avoid both complicated logic and force unwrapping. If we make our errors conform to LocalizedError, we’ll also get a nice error message in Xcode whenever such a test started failing:

class ImageCacheTests: XCTestCase {
    func testCachingAndLoadingImage() throws {
        let bundle = Bundle(for: type(of: self))
        let cache = ImageCache(bundle: bundle)
        
        // Bonus tip: You can easily load images from your test
        // bundle using this UIImage initializer
        let image = try XCTUnwrap(UIImage(named: "sample", in: bundle, compatibleWith: nil))
        try cache.cache(image, forKey: "key")
        
        let cachedImage = try cache.image(forKey: "key")
        XCTAssertEqual(image, cachedImage)
    }
}

enum ImageCacheError {
    case emptyKey
    case dataConversionFailed
}

// When using throwing tests, making your errors conform to
// LocalizedError will render a much nicer error message in
// Xcode (per default only the error code is shown).
extension ImageCacheError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case .emptyKey:
            return "An empty key was given"
        case .dataConversionFailed:
            return "Failed to convert the given image to Data"
        }
    }
}

For more information, check out "Avoiding force unwrapping in Swift unit tests".