多个异步测试和期望

时间:2017-05-30 16:03:27

标签: swift testing asynchronous xctestexpectation

我有多个测试,每个测试都使用给定参数测试相同的异步方法以获得不同的结果。

我发现异步测试我们必须声明期望,等待期望,并满足期望。 这可以。单独完成时,每个测试都能正常运行,但是当我尝试运行整个测试类时,一些测试会通过,而其他测试会在运行并正常通过时崩溃或失败。

我在网上看到了“快速3次多次测试与期待”,并且每个解释期望的人都只有一个测试方法的例子。 是否不可能在同一个班级的多个方法中有期望?

测试的一个例子如下:

func testLoginWrongUsernameOrPasswordFailure() {
  let viewModel = LoginViewModel()
  let loginAPI = APIManager()
  let expect = expectation(description: "testing for incorrect credentials")

  viewModel.loginWith(username: "qwerty", password: "qwerty", completion: { loginCompletion in

      do {
        try loginCompletion()
          XCTFail("Wrong Login didn't error")
          expect.fulfill()
        } catch let error {
          XCTAssertEqual(error as? LoginError, LoginError.wrongCredentials)
          expect.fulfill()
        }
      })

      waitForExpectations(timeout: 10) { error in
        XCTAssertNil(error)
      }
}

据我所知,这是对期望的正确使用,每个测试遵循相同的模式

根据Rob的要求,我将在这里提供MCVE https://bitbucket.org/chirone/mcve_test 测试类使用模拟API管理器,但是当我使用真实测试时,仍然会发生错误。

作为代码的解释,视图模型与给定的API管理器进行通信,该管理器调用服务器并将视图模型的响应返回给他以解释错误或成功。

第一次测试测试空字段,视图模型验证的内容而不是APIManager。 第二个测试测试不正确的用户名和密码 第三次测试测试有效的用户名和密码

单独运行的三个测试运行正常,但是当整个文件运行时,我将收到SIGABRT错误,原因如下:

  

XCTAssertEqual失败:(“可选(MCVE.LoginError.wrongCredentials)”)不等于(“Optional(MCVE.LoginError.emptyFields)”) -

     

***断言失败 - [XCTestExpectation fulfill],/ Library/Caches/com.apple.xbs/Sources/XCTest_Sim/XCTest-12124/Sources/XCTestFramework/Async/XCTestExpectation.m:101

     

***因未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'API违规 - 多次调用 - [XCTestExpectation fulfill]用于测试空字段。'

SIGABRT通常在第二个测试方法上发生,如果你点击播放,那么它会在其中一个XCTest方法上失败,声称它得到的错误不是它所期望的错误。

我希望MCVE有助于解释我的问题。

3 个答案:

答案 0 :(得分:1)

是否有可能等待多重期望;是。以下是显示此内容的XCTestCase方法的签名。

func wait(for: [XCTestExpectation], timeout: TimeInterval)

还有一个版本可以确保按照for:数组中显示的顺序完成预期。

请参阅Apple在XCode-> Window->文档和API参考中提供的文档,然后搜索XCTestCase。

答案 1 :(得分:0)

重构了以下代码。

func testLoginWrongUsernameOrPasswordFailure() {
  let viewModel = LoginViewModel()
  let loginAPI = APIManager()
  let expect = expectation(description: "testing for incorrect credentials")

  viewModel.loginWith(username: "qwerty", password: "qwerty", completion: { loginCompletion in

      do {
        try loginCompletion()
        XCTFail("Wrong Login didn't error")

      } catch let error {
        XCTAssertEqual(error as? LoginError, LoginError.wrongCredentials)
      }
      expect.fulfill()
   })

  waitForExpectations(timeout: 10) { error in
    XCTAssertNil(error)
  }
}

如果仍然遇到以下崩溃,则意味着异步代码的完成处理程序将多次调用。然后多次调用 expect.fulfill()。不允许。

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'API violation - multiple calls made to -[XCTestExpectation fulfill] for testing for empty fields.'

出于期望, fulfill()应该只调用一次。如果有一些罕见的情况,并且您需要多次调用 expect.fulfill(),然后设置以下属性。

expectedFulfillmentCount

请参考以下链接 https://developer.apple.com/documentation/xctest/xctestexpectation/2806572-expectedfulfillmentcount?language=objc

答案 2 :(得分:0)

如果一个XCTestCase中有多个测试(方法),请不要使用

let expectation = expectation(description: "")

相反,使用

let expectation = XCTestExpectation(description: "")

self.expectaion()在XCTestCase测试之间共享。在某些情况下,这会带来奇怪的行为。例如,即使您达到期望的次数为零,也可能会遇到API违规错误。