Last active
August 22, 2020 12:57
-
-
Save FranDepascuali/d5aef2566a052235eb7c649e7830e2e6 to your computer and use it in GitHub Desktop.
A sample for testing memory leaks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adapted from https://www.avanderlee.com/swift/memory-leaks-unit-tests/ | |
// --------------> Usage <------------------- | |
XCTAssertDeallocation(of: { | |
MyViewController(...) | |
}) | |
// With some setup: | |
XCTAssertDeallocation(of: { () -> MyViewController in | |
let myViewController = MyViewController(...) | |
// call any function | |
return myViewController | |
}) | |
// Can also be used with other types, not only view controller. | |
// --------------> Implementation <------------------- | |
import Foundation | |
import XCTest | |
@testable import Oasis | |
public func XCTAssertDeallocation<T: AnyObject>( | |
of buildElement: () -> T, | |
file: StaticString = #file, | |
line: UInt = #line) { | |
weak var weakReference: T? | |
autoreleasepool { | |
let element = buildElement() | |
weakReference = element | |
// If it's a UIViewController, we need to trigger viewDidLoad. | |
if let viewController = element as? UIViewController { | |
_ = viewController.view | |
} | |
} | |
XCTWait(for: weakReference == nil, timeout: 3.0, description: "Memory leak in \(T.self)", file: file, line: line) | |
} | |
/// Checks for the callback to be the expected value within the given timeout. | |
/// | |
/// - Parameters: | |
/// - condition: The condition to check for. | |
/// - timeout: The timeout in which the callback should return true. | |
/// - description: A string to display in the test log for this expectation, to help diagnose failures. | |
func XCTWait( | |
for condition: @autoclosure @escaping () -> Bool, | |
timeout: TimeInterval, description: String, | |
file: StaticString = #file, | |
line: UInt = #line) { | |
let end = Date().addingTimeInterval(timeout) | |
var value: Bool = false | |
let closure: () -> Void = { | |
value = condition() | |
} | |
while !value && 0 < end.timeIntervalSinceNow { | |
if RunLoop.current.run(mode: RunLoop.Mode.default, before: Date(timeIntervalSinceNow: 0.002)) { | |
Thread.sleep(forTimeInterval: 0.002) | |
} | |
closure() | |
} | |
closure() | |
XCTAssertTrue(value, "➡️? Timed out waiting for condition to be true: \"\(description)\"", file: file, line: line) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment