Escribí algunas pruebas para mi ViewModel. Yo uso RxSwift en este proyecto. Nunca antes había escrito pruebas unitarias, así que quiero preguntarle sobre su corrección. ¿Qué puedo hacer mejor la próxima vez? Es un poco difícil para mí cuando escribo pruebas mientras uso RxSwift. Todas las pruebas pasaron, pero no sé si son "buenas pruebas". Gracias por tu ayuda.
Ver modelo:
class SettingsViewModel { private let storage = Storage.shared private let disposeBag = DisposeBag() let userSettings = BehaviorRelay<UserSettings>(value: UserSettings(name: "", tags: [])) init() { subscribe() } private func subscribe() { storage.currentUserSettings() .subscribe(onNext: { settings in if let settings = settings { self.userSettings.accept(settings) } }) .disposed(by: disposeBag) } func saveName(_ name: String) { saveSettings(name: name, tags: userSettings.value.tags) } func addTag(_ tag: String) { let newTags = userSettings.value.tags + [tag] saveSettings(name: userSettings.value.name, tags: newTags) } func removeTag(_ index: Int) { var newTags = userSettings.value.tags newTags.remove(at: index) saveSettings(name: userSettings.value.name, tags: newTags) } private func saveSettings(name: String, tags: [String]) { let newSettings = UserSettings(name: name, tags: tags) Storage.shared.saveUserSettings(newSettings) }}
Clase de prueba:
class SettingsViewModelTests: XCTestCase { func test_userSettingsSaving_includesAddingName() { let sut = SettingsViewModel() let userSettings = UserSettingsSpy(sut.userSettings) sut.saveName("George") XCTAssertEqual(userSettings.settings.name, "George") sut.saveName("Mike") XCTAssertEqual(userSettings.settings.name, "Mike") } func test_userSettingsSaving_includesAddingTag() { let sut = SettingsViewModel() let userSettings = UserSettingsSpy(sut.userSettings) sut.addTag("Book") var savedTags: [String] = [] Storage.shared.currentUserSettings() .subscribe(onNext: { settings in if let tags = settings?.tags { savedTags = tags } }) .dispose() XCTAssertEqual(userSettings.settings.tags, savedTags) } func test_userSettingsSaving_includesRemovingTag() { let sut = SettingsViewModel() let userSettings = UserSettingsSpy(sut.userSettings) sut.addTag("TestTagToRemove") sut.removeTag(0) var savedTags: [String] = [] Storage.shared.currentUserSettings() .subscribe(onNext: { settings in if let tags = settings?.tags { savedTags = tags } }) .dispose() XCTAssertEqual(userSettings.settings.tags, savedTags) } class UserSettingsSpy { private let disposeBag = DisposeBag() private(set) var settings = UserSettings(name: "", tags: []) init(_ observable: BehaviorRelay<UserSettings>) { observable .subscribe(onNext: { settings in self.settings = settings }) .disposed(by: disposeBag) } }}
Una manera fácil de verificar la corrección de sus pruebas es cambiar el sistema bajo prueba y ver si sus pruebas marcan el error. Si no lo hacen, entonces eso es un agujero en sus pruebas. Por ejemplo, el siguiente modelo de vista pasará sus pruebas:
struct Storage { static let shared = Storage() func currentUserSettings() -> Observable<UserSettings?> { .just(nil) } } struct SettingsViewModel { let userSettings = BehaviorRelay<UserSettings>(value: UserSettings()) func saveName(_ value: String) { userSettings.accept(UserSettings(name: value, tags: [])) } func addTag(_ value: String) { } func removeTag(_ value: Int) { } } struct UserSettings { var name: String = "" var tags: [String] = [] }Obviamente, al código anterior le faltan algunas funciones importantes, lo que significa que sus pruebas están incompletas.