So far I have tested my iOS/Swift project manually by running it in the simulator. Now I have added a Unit Test target to the project to also include automated tests.
I was surprised to find out, that running the default target in Simulator and running the tests target both affect the same data / the same app instance.
For example the uses a SQLite database and UserDefaults to persist some data and settings. When writing data to the database or changing settings in UserDefaults inside the tests, these changes are also visible when running the app in simulator (and vice versa).
I thought because the tests are in a separate target, separate data would be used. This is not the case.
Is it possible to setup the test target to to not interfere with the app target?
2
Answers
In addition to the excellent answer by @ThisuraDodangoda I would like to add another solution: Simply create a new target dedicated to the tests
The problem was, that the tests interferes with the data of my app target. So the solution was to simply assign another, new target to the tests:
Please note, that while this solution works it is not ideal. When new files are added to the project one has always to make sure, that they are not only added to the app target but also to the new target which is used as host app.
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.
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.
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
andvalue
methods inUserDefaults
. 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.The above extension can be used as follows.