我们使用独立的 wiremock 实例作为 Xcode UI 测试的模拟服务器。我们有一个测试观察者类,它负责启动这个实例(如果需要)并在测试运行完成后将其拆除。观察者的代码如下:
import AppKit
import XCTest
import WiremockClient
class SSUITestObserver: NSObject, XCTestObservation {
enum TestObserverError : Error {
case MockServerStartupError(String)
}
lazy var testBundleURL: URL = Bundle(for: SSUITestCase.self).bundleURL
lazy var testBundleBinURL: URL = self.testBundleURL.appendingPathComponent("..", isDirectory: true)
lazy var mockServerHomeURL: URL = self.testBundleURL.appendingPathComponent("Contents/Resources/", isDirectory: true)
lazy var mockServerJarURL: URL = self.mockServerHomeURL.appendingPathComponent("wiremock-standalone-2.18.0.jar", isDirectory: false)
override init() {
super.init()
NSLog("UI Test Observer Initialized")
XCTestObservationCenter.shared.addTestObserver(self)
}
func testBundleWillStart(_ testBundle: Bundle) {
NSLog("***Test Bundle starting")
do {
// Start the Wiremock server
try ensureMockServerIsRunning()
} catch {
fatalError("\n Failed during test bundle setup: \(error)\n")
}
}
public func testBundleDidFinish(_ testBundle: Bundle) {
NSLog("***Test Bundle completed")
stopMockServer()
}
func ensureMockServerIsRunning() throws {
WiremockClient.baseURL = SSUIIntegrationTestCase.mockServerAddress
guard !WiremockClient.isServerRunning() else { return }
let args = ["-jar",
self.mockServerJarURL.path,
"--port", "3000",
"--root-dir", self.mockServerHomeURL.path]
_ = Process.launchedProcess(launchPath: "/usr/bin/java", arguments: args)
for _ in 1...9 {
if WiremockClient.isServerRunning() { return }
sleep(1)
}
throw TestObserverError.MockServerStartupError("Error staring up the mock server instance!")
}
func stopMockServer() {
WiremockClient.shutdownServer()
}
func resetMockServerStubs() {
WiremockClient.reset()
}
}
在我迁移到 macOS 10.14 之前,一切都很好。以前,我们没有对 UITest 目标进行代码签名。迁移到 10.14 后,运行测试现在会在测试开始运行之前失败并出现引导错误。我发现为测试打开自动代码签名可以解决这个问题。
但是,这会导致第二个问题:在上面的 launchedProcess
行中,启动 wiremock 服务器的尝试将失败并显示 java.lang.RuntimeException: java.net.SocketException:不允许操作
。如果在我执行测试之前启动了服务器(例如在命令行上),则一切正常。
那么我怎样才能摆脱这个第 22 条军规呢?在 10.13 下一切正常。我不清楚代码签名与启动模拟服务器有什么关系。
最佳答案
我没有收到我的问题的直接答案,但我确实找到了解决方法。与其使用 TestObserver 启动 WireMock 服务器,不如在测试中使用预操作。
为此,您需要为 UI 测试项目编辑方案:
- 点击
测试
旁边的披露箭头,然后点击Pre-actions
- 点击
+
添加 ActionScript - 使用您选择的 shell(我保留了默认值,
/bin/sh
) - 在
Provide build settings from
下,选择您的测试目标 - 输入启动模拟服务器的脚本。
对于脚本,我使用了以下代码:
exec > /tmp/preaction-log.txt 2>&1
# Attempt to connect to an existing wiremock server, and exit if we succeed:
curl http://localhost:3000/__admin/mappings > /dev/null 2>&1 && exit 0 || echo "Attemmpting to spin up a Wiremock Server:"
# No existing server, so spin one up:
WIREMOCK_DIR=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME}-Runner.app/Contents/PlugIns/${TARGET_NAME}.xctest/Contents/Resources/
/usr/bin/java -jar "${WIREMOCK_DIR}"wiremock-standalone-2.18.0.jar --port 3000 --root-dir "${WIREMOCK_PATH}" &
这是脚本的作用:
- 将所有输出记录到
/tmp/preaction-log.txt
以进行调试,因为操作前脚本不会记录到构建日志中。 - 检查所需端口(在我们的示例中为 3000)上是否有正在运行的服务器。我使用了 WireMockClient 使用的相同方法:尝试访问“映射”API。如果成功,我们将退出脚本。
- 如果我们到了这一步,我们可以假设我们需要启动一个服务器。所以我们这样做,使用一些 XCode 环境变量来指向我们在项目中存储服务器可执行文件的位置(如果您始终在系统上安装 WireMock 客户端,您可以将路径更改为您喜欢的任何路径)。
现在,只要您运行测试用例,此脚本就会运行。我们仍然在 TestObserver 中运行结束时关闭服务器。
关于code-signing - 如何在 Xcode 10 和 macOS 10.14 下为 XCTest UI 测试启动 WireMock?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54136011/