Xcode Unit Testing run function correctly - swift

Let's say I have this test code
class MyTests: XCTestCase {
// I want to call this func first when I run class test.
func testLoginUser() {
... do some test
... expectation.fulfiil() // jump to the next testGetUserProfile func.
}
// I want to run this func after testLoginUser fulfill expectation
func testGetUserProfile() {
}
}
Questions:
As I understood that all functions which started from prefix test will be called automatically by pressing this button on the image below with undefined queue of calls. So testGetUserProfile func can be called before actually testLoginUser fulfilled am I right?
If so then does it mean that I need to rename testGetUserProfile to getUserProfile function and call it from testLoginUser after expectation fulfilled?
Is there a way to program a queue of test func calls one by one after each of them fulfilled?

The order of test method execution is defined by their names, by default Xcode runs them in alphabetical order.
Xcode 11 has introduced Test Plans, where you can configure the execution order to be either "random" or "alphabetical".

Related

is there a library similar to Reentrant Lock in Java for Swift?

I am currently working on a function that can be used by multiple threads. The issue is that the function needs to complete first and store the result in the cache. In the meantime, other threads could be calling this function and I would need them to wait until is completed. We were able to accomplish this on Java using Reentrant Lock is there a similar library in swift? I saw that NSRecursiveLock approaches what we are trying to do, however, we want to keep it with swift only. I have also been seeing multiple articles such as this one that talks about using GCD, however, I believe this is for something similar but different: https://medium.com/#prasanna.aithal/multi-threading-in-ios-using-swift-82f3601f171c
Thank you in advance.
Recursion with locking is always a bit of a pain point. A clean solution would be to refactor your function that requires the lock into an external API that acquires the lock and forwards to an internal API that doesn't. Internally don't call the external API.
A simple example might be something like this (this is almost Swift code - parameters and actual work implementations need to be filled in)
extension DispatchSemaphore
{
func withLock<R>(_ block: () throws -> R) rethrows -> R
{
wait()
defer { signal() }
return try block()
}
}
let myLock = DispatchSemaphore(value: 1)
func recursiveLockingFunction(parameters)
{
func nonLockingFunc(parameters) {
if /* some terminating case goes here */ {
// Do the terminating case
return
}
// Do whatever you need to do to handle the partial problem and
// and reduce the parameters
nonLockingFunc(reducedParameters)
}
myLock.withLock { nonLockingFunc(parameters) }
}
Whether this will work for you depends on your design, but should work if the only problem is that the function you want to lock is recursive. And it only uses GCD (DispatchSemaphore) to achieve it.

Can I reset private static variable or reset application from XCTest code?

I am testing a framework.
Every test case set static variable and it looks like XCTest shares static area of a framework.
As a result, running tests at the same time makes test failure from the second test.
Note that running tests individually makes all test succeed.
I am testing with Unit test not UI test, but should I reset App at the stage of class tearDown()?
If so, please tell me how to do it, because
XCUIApplication.terminate() fails in the subclass of XCTestCase.
I am using Xcode 11 Swift 5.1
I believe what you're looking for are the instance methods, not the type methods.
Furthermore, consider setUp over tearDown:
Here is the description for the instance method setUp from Apple's documentation:
Before each test begins, XCTest calls setUpWithError(), followed by setUp(). Override this method to reset state for each test method. If state preparation might throw errors, override setUpWithError().
https://developer.apple.com/documentation/xctest/xctest/1500341-setup
Example usage:
override func setUp() {
// reset state for each test
}
For comparison, here is the description for the type method setUp from Apple's documentation:
The setUp() class method is called exactly once for a test case, before its first test method is called. Override this method to customize the initial state for all tests in the test case.
https://developer.apple.com/documentation/xctest/xctestcase/1496262-setup
Example usage:
override class func setUp() {
// customize the initial state for all tests
}
I don't know what the purpose of your static variables are, but it sounds like they are responsible for changing behavior in your app. I recommend using mock objects and/or data. I would consider looking into writing "testable code." It will help you keep your code clean and also make it easier for you to write unit tests. It is also object-oriented.

Consecutive unit tests fail, although they succeed individually

I have a unit test suite where every test succeeds when it is executed individually.
However, if I execute the whole suite, one test hangs when it should init a singleton. It hangs only if it is executed after a certain other unit test - if I change the order, the whole test suit executes successfully.
If I pause the execution of the hanging unit test, the stack trace is the following:
The execution hangs at the statement static let shared = StoreManager():
class StoreManager: NSObject, CalledByDataStoreInStoreManager {
static let shared = StoreManager() // Instantiate the singleton
// …
}
The other unit test that it executed before and that causes the test to hang does not use the StoreManager singleton.
My question is:
What could be the reason that the 1st test lets the initialisation of the singleton in the 2nd test fail, although this singleton is not used in the 1st test?
So the obvious answer is that there's a side effect occurring in your 1st test that is affecting your second test. Exactly what that side effect is, though, is dependent on two things:
What is being tested in the first test
What occurs in the initializer for StoreManager
From your description, it sounds like the first test is somehow affecting what's then used in the StoreManager init, which is unaffected when that test is not run before your 2nd test.
Solved: The side effect that the answer of BHendricks pointed me to, was the following:
Since my app uses also the watch, the watch session is activated in the app delegate, as recommended by Apple. This was done by calling a function in a WatchSessionManager instance, and the initialisation of this instance tried to init a singleton that is also tried to be init by the Storemanager.
This created an init cycle deadlock.
Since I use a mock app delegate for unit tests, I activate now the watch connectivity session there without initialising the unnecessary initialisation of the WatchSessionManager instance, and the deadlock is avoided.

removing runtime discovered tests labeled with "rt"

We are facing the issue that Xcode detects runtime tests.
Because of certain states of the tests these tests will always fail.
It's not possible to get rid of them, by cleaning the Project nor deleting the Derived Data.
Some Test classes are inherited by others.
Specs:
Xcode 8.3.3
Swift 3.1
Edit
Add more specific details
Subclass:
TestClassA: XCTestCase
func testA1()
func testA2()
TestClassB: TestClassA
func testB1()
Now the Problem is that when I run all tests for TestClassB Xcode will run testB1 and then testA1 and testA2. Both marked with rt and they will fail.
How can i achieve that this is not happening by not loosing the subclass structure.
Screenshot
I assume you're overriding the setup and teardown do assure the app will be in the proper state for every test case, the problem here would be that
the rT test will appear since the subclasses are inheriting the tests from their parent.
To avoid this while maintaining the subclassing structure, keep the setup and teardown functions in the classes you have but move the tests to a subclass of the setup class.
For example:
Subclass:
TestClassA: XCTestCase // This one will have the setup and teardown for A
TestClassATests: TestClassA
func testA1()
func testA2()
TestClassB: TestClassA // This one will have the setup and teardown for B, and you may reuse A setup
TestClassBTests: TestClassB
func testB1()
func testB2()

Modifying reference type parameters in Swift; are changes immediately visible outside?

I have a Swift playground that contains several classes in the source folder. These classes have tick() functions that are called as fast as possible with a while true { }. I am using a parallel thread to do this, to stop Xcode from locking up, with this code:
DispatchQueue.global(qos: .background).async {
BackgroundThread.startMainLoop(scene: scene)
}
// other file
public struct BackgroundThread {
public static func startMainLoop (scene: SKScene) {
let songController = SongController()
let uiManager = UIManager(scene: scene)
// The UIManager is going to modify this scene.
// Will the changes be available to BackgroundThread and/or the main file?
while true {
songController.tick()
uiManager.tick()
}
}
}
Because the main playground script is very slow, I have moved the repeating loop to a compiled class in the Sources folder.
I am passing an SKScene object to a UIManager compiled class, which I will need to update the UI in this (relatively complicated) scene faster than the main playground script can manage.
The main playground script calls a startMainLoop() function in the parallel thread. It passes in the SKScene object. This function never returns, since it contains a never-ending loop. Is there a way I can modify the passed object in a manner that modifies the scene displayed on the screen, live, without the function ever having to return (which means that inout is not an option), assuming this does not happen by default?
Reference type means the value is a reference -- i.e. a pointer to an object. When you pass or assign a reference, you get a copy of the reference (it is pass-by-value without inout), but multiple copies of the reference point to the same object, and modifications to the object through any reference that points to it is visible through any other reference that points to it.