Как я могу запустить WireMock для тестов пользовательского интерфейса XCTest под Xcode 10 и macOS 10.14? - PullRequest
0 голосов
/ 10 января 2019

Мы используем автономный экземпляр wiremock в качестве фиктивного сервера для наших тестов пользовательского интерфейса XCode. У нас есть класс тестового наблюдателя, который отвечает за раскрутку этого экземпляра (если требуется) и разрыв его после завершения тестового прогона. Код для наблюдателя выглядит следующим образом:

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 голосов
/ 26 января 2019

Я не получил прямого ответа на свой вопрос, но я нашел обходной путь. Вместо того чтобы использовать TestObserver для запуска сервера WireMock, вместо этого можно использовать предварительное действие в тесте.

Для этого вы хотите отредактировать схему для вашего тестового проекта пользовательского интерфейса:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...