如何在Xcode 10和macOS 10.14下启动WireMock for XCTest UI测试?

时间:2019-01-10 19:53:10

标签: code-signing xctest xcode10 macos-mojave wiremock

我们正在使用独立的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: Operation not permitted。如果在执行测试之前启动了服务器(例如,在命令行上),则一切正常。

那么我如何才能使自己摆脱22号陷阱?在10.13以下,一切正常。我不清楚启动模拟服务器与代码签名有什么关系。

1 个答案:

答案 0 :(得分:0)

我没有收到我的问题的直接答案,但确实找到了解决方法。您不必使用TestObserver来启动WireMock服务器,而可以对测试使用预操作。

为此,您要编辑UI测试项目的方案:

Edit Scheme

  1. 单击Test旁边的公开箭头,然后单击Pre-actions
  2. 点击+添加操作脚本
  3. 使用您选择的外壳(我保留了默认的/bin/sh
  4. Provide build settings from下,选择测试目标
  5. 输入启动模拟服务器的脚本。

对于脚本,我使用了以下代码:

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}" &

这是脚本的作用:

  1. 将所有输出记录到/tmp/preaction-log.txt中进行调试,因为操作前脚本不会记录到构建日志中。
  2. 检查所需端口(在本例中为3000)上正在运行的服务器。我使用了WireMockClient使用的相同方法:尝试访问“映射” API。如果成功,则退出脚本。
  3. 如果到此为止,我们可以假设我们需要启动服务器。因此,我们可以使用一些XCode环境变量来指向我们在项目中存储服务器可执行文件的位置(如果您的系统上始终装有WireMock客户端,则可以将路径更改为所需的路径)。

现在,此脚本将在您运行测试用例时运行。在运行结束后,我们仍然在TestObserver中关闭服务器。