iOS Boot Camp
-
Create VIPER template use ruby script
ruby scripts/generator.rb -m "SignUp" -t ./templates -w TooDoApp/TooDoApp/Modules -u TooDoApp/TooDoAppTests/Modules -a "<Your name>"
-
Import generated file to project
-
Add Modules.swift path to Module
case .SignUp: return "/Modules/SignUp"
-
Add module to AppRouter.swift
Module.SignUp.routePath : {(appRouter: IAppRouter) in SignUpModule(appRouter: appRouter)}
-
Un-commented this code on SignUpModule.swift
let wireframe = appRouter.resolver.resolve(ISignUpWireFrame.self, argument:appRouter)! wireframe.present(SignUpViewModel())
-
Add some protocol needed, example: we want show SignUp screen and show List of todo after SignUp
func presentView(viewModel:SignUpViewModel) func showListScreen()
-
Add method in SignUp presenter and Interface to do SignUp
func doSignUp(email: String?, password: String?, confirmPassword: String?) func didSignUp(user: User) func failedToSignUp(error: NSError?)
-
Un-wrapped all optional value to check not get nil value
-
Make sure all view action registered to viewInterface
func showLoading() func hideLoading() func showErrorMessage(message: String)
-
Add service on Interactor
let service:ITodoService init(service:ITodoService){ self.service = service }
-
Make sure All file
Target Membership
can accessed by<#AppName>Test
and<#AppName>UITest
-
Create Mock, Make sure pod already have MockFive installed
import Foundation import MockFive class SignUpViewMock: ISignUpView, Mock { let mockFiveLock: String = lock() func showLoading() { stub(identifier: "show Loading") } func hideLoading() { stub(identifier: "hide Loading") } func showErrorMessage(message: String) { stub(identifier: "show Error Message", arguments: message) } }
import Foundation import MockFive class SignUpWireFrameMock: ISignUpWireFrame, Mock { let mockFiveLock: String = lock() func presentView(viewModel: SignUpViewModel) { stub(identifier: "present View") } func showListScreen() { stub(identifier: "show List Screen") } }
import Foundation import MockFive class SignUpIteractorMock: ISignUpInteractor, Mock { let mockFiveLock: String = lock() var _presenter: ISignUpPresenter? var presenter : ISignUpPresenter?{ set { _presenter = newValue } get { return _presenter } } func signUp(email: String, password: String, confirmPassword: String) { stub(identifier: "sign Up", arguments: [email, password, confirmPassword]) _presenter?.doSignUp(email, password: password, confirmPassword: confirmPassword) } }
import Foundation import Quick import Nimble @testable import TooDoApp class SignUpPresenterTest: QuickSpec { override func spec() { var viewModel:SignUpViewModel! let viewMock = SignUpViewMock() let wireFrameMock = SignUpWireFrameMock() let interceptorMock = SignUpIteractorMock() var presenter: SignUpPresenter! beforeEach{ viewModel = SignUpViewModel() viewMock.resetMock() wireFrameMock.resetMock() interceptorMock.resetMock() presenter = SignUpPresenter(view: viewMock, viewModel: viewModel, interactor: interceptorMock, wireframe: wireFrameMock) interceptorMock.presenter = presenter } } }
-
Make all presenter test case
describe("Sign Up Test") { it("Invalid Sign Up : Invalid Email Address", closure: { presenter.doSignUp("", password: "", confirmPassword: "") expect(viewMock.invocations.count) == 1 expect(viewMock.invocations).to(contain("showErrorMessage(Please enter a valid email)")) }) it("Invalid Sign Up : Invalid Password", closure: { presenter.doSignUp("[email protected]", password: "", confirmPassword: "") expect(viewMock.invocations.count) == 1 expect(viewMock.invocations).to(contain("showErrorMessage(Please enter a valid password)")) }) it("Invalid Sign Up : Confirm password did not match", closure: { presenter.doSignUp("[email protected]", password: "password", confirmPassword: "") expect(viewMock.invocations.count) == 1 expect(viewMock.invocations).to(contain("showErrorMessage(Your password and confirm password did not match)")) }) }