2016-07-24 3 views
2

Я создаю простое приложение для iOS в Swift в соответствии с шаблоном Model-View-Controller. Я могу протестировать класс Model, предоставив ему входные данные и утвердив результат вывода на мое ожидание. Но мне было интересно, как я могу проверить класс Controller?Как проверить класс контроллера в MVC?

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

+2

Контроллер - это просто клей между вашей моделью и вашим пользовательским интерфейсом. Дайте ему входные данные, как если бы они были заданы моделью, и проверьте выходные данные, которые пошли бы на UI. – Alexander

+1

https://cocoapods.org/pods/FBSnapshotTestCase - хороший инструмент для тестирования макетов и https: // cocoapods.org/pods/KIF может использоваться для автоматизации событий касания путем захвата функции доступности (и переключение на Swift имеет некоторые подводные камни). Оба требуют некоторых предварительных навыков в тестировании для реализации. Я бы предложил изучить Quick & Nimble как инструменты для тестирования единиц, если у вас еще нет – markedwardmurray

+2

Этот вопрос слишком широк и потенциально в основном основан на мнениях. – JAL

ответ

5

Не тестируйте UIViewController с. С ними происходит много всего, что вы не видите и/или не имеете контроля. Вместо этого сохраните столько логики в других объектах, таких как View Models, а не ваши UIViewController s. Затем вы можете проверить свои модели просмотра, точно так же, как вы проверили бы ваши модели.

Edit:

Как вы можете структурировать UIViewController s- и тестовые модели & Просмотр моделей:

Основной вынос из этого кода является:

  1. Использование Dependency Injection
  2. Дайте реальные зависимости от классов в Release и поддельных зависимостях в тестах

View Controller

// this class is super simple, so there's hardly any reason to test it now. 
class SomeViewController: UIViewController { 
    @IBOutlet weak var someLabel: UILabel! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // we give the *real* user accessor in the view controller 
     let viewModel = SomeViewModel(userAccessor: DBUserAccessor()) 
     someLabel.text = viewModel.welcomeMessage 
    } 
} 

Модель пользователя

struct User { 
    var name: String 
} 

Accessor Пользователь

Это некоторая зависимость, что ваши потребности View Model. Дайте реальную версию во время выпуска (в вашем контроллере просмотра). Дайте поддельную во время тестов, чтобы вы могли ее контролировать.

protocol UserAccessor { 
    var currentUser: User? { get } 
} 

// since we're using the fake version of this class to test the view model, you might want to test this class on its own 
// you would do that using the same principles that I've shown (dependency injection). 
class DBUserAccessor: UserAccessor { 
    var currentUser: User? { 
     // some real implementation that's used in your app 
     // get the user from the DB 
     return User(name: "Samantha") // so not really this line, but something from CoreData, Realm, etc. 
    } 
} 

class FakeUserAccessor: UserAccessor { 
    // some fake implementation that's used in your tests 
    // set it to whatever you want your tests to "see" as the current User from the "DB" 
    var currentUser: User? 
} 

вид Модель

Это где фактическая логика жизни, что вы хотите проверить.

class SomeViewModel { 
    let userAccessor: UserAccessor 

    init(userAccessor: UserAccessor) { 
     self.userAccessor = userAccessor 
    } 

    var welcomeMessage: String { 
     if let username = self.username { 
      return "Welcome back, \(username)" 
     } else { 
      return "Hello there!" 
     } 
    } 

    var username: String? { 
     return userAccessor.currentUser?.name 
    } 
} 

Тесты

И, наконец, как вы хотите, чтобы проверить его.

class SomeViewModelTest: XCTestCase { 
    func testWelcomeMessageWhenNotLoggedIn() { 
     let userAccessor = FakeUserAccessor() 
     let viewModel = SomeViewModel(userAccessor: userAccessor) // we give the *fake* user accessor to the view model in tests 
     userAccessor.currentUser = nil // set the fake UserAccessor to not have a user "logged in" 

     // assert that the view model, which uses whatever you gave it, gives the correct message 
     XCTAssertEqual(viewModel.welcomeMessage, "Hello there!") 
    } 

    func testWelcomeMessageWhenLoggedIn() { 
     let userAccessor = FakeUserAccessor() 
     let viewModel = SomeViewModel(userAccessor: userAccessor) 
     userAccessor.currentUser = User(name: "Joe") // this time, the use is "logged in" 

     XCTAssertEqual(viewModel.welcomeMessage, "Welcome back, Joe") // and we get the correct message 
    } 
} 
+0

Большое спасибо за предложение! Мне было интересно, можете ли вы немного подробнее остановиться на «вы можете проверить свои модели просмотра». Какая разница и сходство при тестировании только моделей? В очередной раз благодарим за помощь! – Thor

+1

Мое удовольствие. Я добавил кучу пример кода, который показывает, как вы все это настроили. – solidcell

Смежные вопросы