带信号量的 XCTest 单一异步设置
Posted
技术标签:
【中文标题】带信号量的 XCTest 单一异步设置【英文标题】:XCTest Single Asynchronous SetUp With Semaphores 【发布时间】:2017-04-26 14:09:56 【问题描述】:我正在通过 Alamofire 测试 API。我需要对服务器进行一次调用,以便为集成测试做好准备。完成后,我就可以开始运行测试了。
每次测试都会运行通常的override setUp()
,所以我不想这样做。
因此,我选择覆盖class setUp()
,如下所述:https://developer.apple.com/reference/xctest/xctestcase
这一切都很好,但是现在,我不能再使用标准的waitForExpectations
。 (在class override setUp())
中,我收到几个编译器错误,告诉我我不再调用相同的waitForExpectations
,因为我在类方法中,而不是测试用例中。
为了解决这个问题,我想使用这样的信号量:
class ServiceLayerTests: XCTestCase
static var apiService: APIService = APIService()
let sessionManager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: ["http://localhost:3000/": .disableEvaluation]))
static var companyManger: UserWebResource?
static var companyManagerID = -1
override class func setUp()
apiService.baseURL = "http://localhost:3000/"
beginIntegrationTests()
class func beginIntegrationTests()
var semaphore = DispatchSemaphore(value: 0)
apiService.beginIntegrationTests(completion: resource, error in
if let resource = resource
if let manager = resource as? UserWebResource
companyManger = manager
companyManagerID = manager.id
semaphore.signal()
)
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
这不起作用。在后台,有一个对服务器的 alamo fire 调用,它会响应用户以用于集成测试。我确实看到服务器在旋转,所以我知道实际的通信正在发生,但我从未进入完成关闭。
我怀疑我不了解 Swift 是如何处理信号量的,并且我以某种方式造成了死锁。如果有人有更好的解决方案,我会很高兴听到它。
【问题讨论】:
仍在等待更好的解决方案。在类设置中调用等待似乎是合理的。 【参考方案1】:我收到几个编译器错误,告诉我我不再调用 相同的
waitForExpectations
因为我在一个类方法中,而不是一个 测试用例
这是有道理的。您可能想要的是重构,以便您处于测试用例中:
override class func setUp()
apiService.baseURL = "http://localhost:3000/"
func testIntegrationTests()
let urlExpectation = expectation(description: "INTEGRATION TEST")
apiService.beginIntegrationTests(completion: resource, error in
// ...
urlExpectation.fulfill()
)
// not sure what an acceptable timeout would be, I chose this at random
waitForExpectations(timeout: 25) error in
if let error = error
print("Error: \(error.localizedDescription)")
可以在此处找到带有一些良好测试示例的最佳资源之一:http://nshipster.com/xctestcase/
【讨论】:
有什么方法可以保证这个测试首先运行?强迫其他测试依赖于这个测试在它们运行之前完成,这感觉有点好笑。 @Mizmor 如果您使用的是XCode 8, no。 我希望有更好的方法,但这似乎是唯一的选择。谢谢【参考方案2】:您可以将期望创建为一个惰性变量,它执行您的一次性设置并在完成时实现。
在您的 per-test setUp()
函数开始时,您可以等待该期望。
在完成之前,您的任何测试都不会运行,并且初始设置只会运行一次。
class WaitForSetup_Tests: XCTestCase
lazy var initialSetupFinished: XCTestExpectation =
let initialSetupFinished = expectation(description: "initial setup finished")
initialSetupTask() // your setup task that executes this closure on completion
initialSetupFinished.fulfill()
return
return initialSetupFinished
()
override func setUp()
wait(for: [initialSignOutFinished], timeout: 2.0)
// do your per-test setup here
注意:此解决方案避免使用 override class function setUp()
类方法,因为除了在实例中之外,我无法弄清楚如何使用期望。
【讨论】:
以上是关于带信号量的 XCTest 单一异步设置的主要内容,如果未能解决你的问题,请参考以下文章