how can I do stres test asynchronous functions with loop on swift

Viewed 29

I'm new in the unit testing.

and I had an issue about asynchronous function testing.

func test_Repository()
{
    let properEmail = ""
    let properPassword = ""
    let improperEmail = ""
    let improperPassword = ""
    let testArray = [(username : "", password : ""), // both empty
                     (username : "", password : properPassword), // empty email
                     (username : properEmail, password : ""), // empty password
                     (username : improperEmail, password : properPassword), // wrong email
                     (username : properEmail, password : improperPassword) // wrong password
            ]
    let repo = UserRepository()
    let exp =
          expectation(description: "Wait for async signIn to complete")
    
   for data in testArray
    {
       print(data.username)
       print(data.password)
       repo.createNewUser(data.username, password: data.password) {[weak self] email, error in
           XCTAssertNotNil(error)
           exp.fulfill()
       }
       sleep(5)
   }
    wait(for: [exp], timeout: 200.0)
   
}

as you can see, I want to test all improve possibilities but it didn't work.

and also my asynchronous create function is here

func createNewUser(_ email : String, password   : String,result: @escaping (_ email : String, _ error : Error?)->())
{
    auth.createUser(withEmail: email, password: password) { [weak self] authResult, error in
        if let error = error
        {
            self?.userCreationError = true
            self?.userCreationErrorText = error.localizedDescription
            result("",error)
        }
        else
        {
            if let authresult = authResult
            {
                self?.user.email = authresult.user.email ?? ""
                self?.createNewUserTable(user: self!.user)
                result((self?.user.email)!,nil)
               
            }
        }
    }
}
2 Answers

You would need to create the expectation for every iteration. For now you code continues after the first iteration.

// add the expectation to your data tuple
let testArray = [(username : "", password : "", expectation: expectation("description")), // both empty // expand this example to all testcases
                 (username : "", password : properPassword), // empty email
                 (username : properEmail, password : ""), // empty password
                 (username : improperEmail, password : properPassword), // wrong email
                 (username : properEmail, password : improperPassword) // wrong password
        ]

for data in testArray
    {
       print(data.username)
       print(data.password)
       repo.createNewUser(data.username, password: data.password) {[weak self] email, error in
           XCTAssertNotNil(error)
           //fulfill the associated expectation
           data.expectation.fulfill()
       }
       sleep(5)
   }
    //wait for all expectations
    wait(for: [testArray.map{$0.expectation}], timeout: 200.0)

Your test was probably left "early", since your expectation was fulfilled after the first completion and the test then stopped.

You need to tell your expectation that it should be considered completed only after all elements in your test array have called fulfill():

let exp = expectation(description: "Wait for async signIn to complete")
exp.expectedFulfillmentCount = testArray.count

A different approach, which serializes the tests and is going to run faster, would be to create an expectation for each iteration and wait for it:

for data in testArray
    {
       print(data.username)
       print(data.password)
       let exp = expectation(description: "…")
       repo.createNewUser(data.username, password: data.password) {[weak self] email, error in
           XCTAssertNotNil(error)
           exp.fulfill()
       }
       wait(for: [exp], timeout: 5)
   }
Related