Background
That certainly would be a great feature, but it is not possible as of now. This is because a Unit Test is not exactly a full blown iOS App Target. Rather it simply hosts the main App Target as the System Under Testing and tests its code.
Below is a screenshot of the Unit Test Target's "General" Settings tab. See that it is actually hosting the main App Target, and is not a clone / variant of the main App Target.
You can work around this limitation by using the following bit of code which checks whether the application is being Unit Tested.
extension UIApplication{
var isTesting: Bool {
#if DEBUG
if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil {
return true
}
return false
#else
return false
#endif
}
}
Note that I have added the "#if DEBUG
" conditional compilation markers to prevent process information from being evaluated in release builds.
Below I have presented two workarounds for your scenario.
Workaround for SQLite
You can use this extension to use two different database names depending on whether a Unit Test is being carried out or not.
import SQLite
do {
let dbName = UIApplication.shared.isTesting ? "db_test" : "db"
let path = "path/to/\(dbName).sqlite"
let db = try Connection(path)
// ...
}
catch{
print(error)
}
Workaround for UserDefaults
Using two sets of data for normal app execution and testing is not as straightforward. The suggested workaround introduces two new methods similar to the standard setValue
and value
methods in UserDefaults
. These special versions append a "_test" suffix to the key depending on whether a Unit Test is being run or not. The effect is that normal settings are not modified by Unit Test settings.
extension UserDefaults{
private var testKeySuffix: String{
return UIApplication.shared.isTesting ? "_test" : ""
}
func safeSetValue(_ value: Any?, forKey key: String){
UserDefaults.standard.setValue(value, forKey: "\(key)\(testKeySuffix)")
}
func safeValue(forKey key: String) -> Any?{
return UserDefaults.standard.value(forKey: "\(key)\(testKeySuffix)")
}
}
The above extension can be used as follows.
// UserDefaults.standard.setValue("123", forKey: "myKey")
UserDefaults.standard.safeSetValue("123", forKey: "myKey")
// let str = UserDefaults.standard.value(forKey: "myKey")
let str = UserDefaults.standard.safeValue(forKey: "myKey")