Тестирование Cognito Authentication в приложении iOS

У меня есть приложение для iOS с аутентификацией Cognito, реализованной очень похоже на CognitoYourUserPoolsSample. Самые важные фрагменты находятся в SignInViewController.swift:

  1. Когда пользователь нажимает Войти, добавляется асинхронная задача:

    var passwordAuthenticationCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
    ...
    @IBAction func signInPressed<...> {
        ...
        let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: self.username.text!, password: self.password.text! )
        self.passwordAuthenticationCompletion?.set(result: authDetails)
        ...
    
  2. Позже мы получим либо успех, либо ответ об ошибке:

    extension SignInViewController: AWSCognitoIdentityPasswordAuthentication {
          public func getDetails<...> {
              DispatchQueue.main.async {
                  // do something in case of success
          ...
    
          public func didCompleteStepWithError<...> {
              DispatchQueue.main.async {
                 // do something in case of failure
          ...
    

У меня также есть тест пользовательского интерфейса, который заполняет имя пользователя и пароль, нажимает Вход и проверяет ответ:

class MyAppUITests: XCTestCase {
    ...
    func loginTest() {
        let usernameField = <...>
        usernameField.tap()
        usernameField.typeText("user@domain.com")
        ... 
        // same for password field
        // then click Sign In
        <...>.buttons["Sign In"].tap()

В настоящее время этот тест работает против реальной инфраструктуры AWS, которая не идеальна по многим причинам. Вместо этого я хочу смоделировать различные ответы от AWS.

Как я могу это сделать?

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

1 ответ

Ладно, я не очень знаком с AWS iOS SDK и с тем, как именно он реализует поток аутентификации, поэтому возьмем следующее с небольшим количеством соли. Это не полный ответ, а более общая "стратегия", я надеюсь. Я реализовал аналогичный подход в моем текущем проекте, не только для входа в систему, но фактически для всех удаленных подключений, которые я делаю.

Есть три вещи, которые вам нужно сделать:

  1. Запустите небольшой локальный веб-сервер внутри вашей цели тестирования пользовательского интерфейса. Я использую Посольство и Посол для этого в моем текущем проекте. Настройте его так, чтобы он возвращал любой ответ, который обычно дает Cognito (или другая конечная точка). Я просто curlотредактировал запрос вручную и где-то сохранил ответ, но в моем случае я получил простые данные (а не, например, полную страницу входа для просмотра в веб-просмотре...). Я предполагаю, что Cognito на самом деле показывает вид входа в систему (веб) и при успешном входе в систему использует глубокую ссылку, чтобы "вернуться" к вашему приложению, которое в конечном итоге вызывает ваш AWSCognitoIdentityPasswordAuthentication методы (успех или ошибка). У вас может быть цель теста, то есть веб-сервер вызывает прямую ссылку напрямую, если вы знаете, как она выглядит (что должно быть возможно узнать?).

  2. Добавьте некоторый механизм для переключения конечной точки Cognito во время теста. К сожалению, это требует добавления производственного кода, но если все сделано правильно, это не должно быть слишком сложным. Я сделал это с помощью переменной среды запуска, которую я установил во время теста (см. Ниже). Если ваш веб-сервер не поддерживает https (Embassy не из коробки), это также требует некоторой настройки App Transport Security. Самым сложным является, конечно, выяснить, где в SDK создана эта конечная точка и как ее изменить. Беглый взгляд на документацию заставляет меня поверить, что webDomain где он сохранен, но я не вижу, как он настроен. Это свойство доступно только для чтения, что усложняет ситуацию. Я предполагаю, однако, что вы можете изменить это в какой-то конфигурации в вашем проекте? Иначе это пахнет как случай для метода метания... Извините, я не могу предложить больше звукового направления здесь.

  3. Во время ваших тестов убедитесь, что реальные конечные точки, к которым будет осуществляться доступ во время соответствующих потоков приложений, переключены на http://localhost/..., Я сделал это с помощью XCUIApplication().launchEnvironment["somekey"] = "TESTINGKEY", что соответствовало моей подготовке производственного кода на втором этапе. В моем случае я мог просто загрузить разные конечные точки (у которых был домен localhost и в остальном те же пути, что и у исходных доменов). Настройте ответы вашего веб-сервера в соответствии с тестовым примером (успешный вход в систему, неверные учетные данные и т. Д.).

Я признаю, что это было / очень много работы, но для меня это стоило того, так как я мог легко запустить весь поток приложений (который включал много исходящих запросов) без какого-либо доступа к сети. В любом случае я должен был реализовать нашу систему аутентификации самостоятельно, что давало мне большой контроль над тем, какие URL-адреса использовались и где, облегчая создание единого места для их удаления в зависимости от переменной среды запуска. Самой уродливой частью в моем случае было включение исключений ATS только в моих тестах, для чего мне пришлось использовать скрипт запуска по разным причинам.

Другие вопросы по тегам