[Перевод] UI тесты в Xcode с Embassy и Succulent

Всем привет!

Очередная новинка в списке наших курсов: «Разработчик iOS», а значит пришло время интересных штук, которые мы находили за время подготовки курса. В этой заметке автор разбирает как записывать и воспроизводить запросы API для работы UI тестов.

Поехали.

Недавно я интегрировал Embassy и Succulent в свои UI тесты. Если вам нужно запустить UI тесты для приложения, использующего данные API, это руководство может предложить альтернативу mock / stub.

Проблемы:

  • Приложение использует данные API для заполнения UI;
  • Использование stub«ов может потребовать написания и поддержки большого количества файлов;
  • При использование mock«ов, логика приложения может отличаться от фактического сетевого вызова;
  • Использование настоящего API соединения — СОВЕРШЕННО ИСКЛЮЧЕНО, слишком много переменных и сбоев


yqkz3onp8vidqhlzxjmoummp_ok.png


Решение с помощью Embassy + Succulent

Решение заключается в создании локального сервера, на который направлено ваше приложение (с помощью Embassy), и в записи/ответах на сетевые вызовы (с помощью Succulent).

При первом запуске теста, стандартные сетевые вызовы будут выполнены и записаны в файл трассировки.

В следующий раз эти же сетевые вызовы получат ответ автоматически. Круто, не правда ли? Не нужно писать mock«и, можно симулировать лаги и ошибки, и все это запускается внутри билд-машины, внутри XCtest!

Как этим пользоваться?

1. Скачайте и установите под Succulent. Во время написания этой статьи пода не было на cocoapods.com, поэтому нужно скачать источник и добавить его в ваш под-файл следующим образом:

target "UI Tests” do
  inherit! :search_paths
  pod ‘Succulent’, :path => ‘Succulent/’
end


Succulent требуется Embassy и он будет установлен автоматически.

2. Создайте новый файл UI теста и скопируйте инструкцию из Succulent GitHub. В итоге должен получиться такой файл:

import Succulent

@testable import TestAppUITests

class SucculentTestUITest: XCTestCase {
 
    private var succulent: Succulent!
    var session: URLSession!
    var baseURL: URL!
    
    /// The name of the trace file for the current test
    private var traceName: String {
        return self.description.trimmingCharacters(in: CharacterSet(charactersIn: "-[] ")).replacingOccurrences(of: " ", with: "_")
    }
    
    /// The URL to the trace file for the current test when running tests
    private var traceUrl: URL? {
        let bundle = Bundle(for: type(of: self))
        return bundle.url(forResource: self.traceName, withExtension: "trace", subdirectory: "Traces")
    }
    
    /// The URL to the trace file for the current test when recording
    private var recordUrl: URL {
        let bundle = Bundle(for: type(of: self))
        let recordPath = bundle.infoDictionary!["TraceRecordPath"] as! String
        return URL(fileURLWithPath: "\(recordPath)/\(self.traceName).trace")
    }
    
    override func setUp() {
        super.setUp()
        continueAfterFailure = false
        
        if let traceUrl = self.traceUrl {  // Replay using an existing trace file
            succulent = Succulent(traceUrl: traceUrl)
        } else {    // Record to a new trace file
            succulent = Succulent(recordUrl: self.recordUrl, baseUrl: URL(string: "https//base-url-to-record.com/")!)
        }
        
        succulent.start()
        
        let app = XCUIApplication()
        
        app.launchEnvironment["succulentBaseURL"] = "http://localhost:\(succulent.actualPort)/"
        
        app.launch()
    }
    
    override func tearDown() {
        super.tearDown()
    }
}


При запуске Succulent есть возможность указать базовый URL, благодаря которому все запросы, включающие базовый URL, будут записаны, а все прочие проигнорированы.

3. Добавьте следующую строку в Info.plist цели вашего UI теста:

TraceRecordPath
$(PROJECT_DIR)/Succulent/Traces


4. Направьте приложение на локальный сервер.

Чтобы сделать это внутри вашего основного приложения, необходимо проверить существует ли переменная окружения «succulentBaseURL» и настроена ли она.

Она показывает url вашего локального веб-сервера и настраивается в setUp функции, которую скопировали выше в пункте 2.

#if DEBUG
if let localServerUrl = ProcessInfo.processInfo.environment["succulentBaseURL”] {
   return URL(string: localServerUrl)!
}
#endif


Вот, пожалуй, и все!

Теперь когда вы сделаете простой тест и запустите его, Succulent запишет запрос API и создаст .trace файл в папке Traces директории цели вашего UI теста. Когда вы запустите этот же тест в следующий раз, он проверит, существует ли файл и запустит его.

Вы можете открывать .trace файлы напрямую из Xcode, смотреть все сетевые запросы и изменять их по необходимости.

Надеюсь, статья оказалась полезной, вот пицца:

qrdf905quxx5f0ih0ewj9vh_a1w.jpeg

THE END

Как обычно ждём комментарии, вопросы и прочее тут или можно заглянуть на День открытых дверей и задать вопрос преподавателю там.

© Habrahabr.ru