SlideShare ist ein Scribd-Unternehmen logo
1 von 85
Downloaden Sie, um offline zu lesen
Unit Testing
Zašto?
Kako ubiti

2 aplikacije
Jednim commitom.
Manje bugova.
Swift 

migracija?
Nema problema.
Manje stresa.
Kad se isplati?
Testiranje je
investicija
Što testirati?
Koliko se koristi?

Koliko je kompleksno?

Koliko je važna korektnost?
Što testirati?
1. Core logika

2. Prezentacija (ViewModel)
3. UI
Zašto ljudi ne

testiraju?
Testovi su

teški.
Ako je dizajn loš.
Teško za
testirati:
Dependency (UIKit,
Foundation, libovi)
Lagano za

testirati:
“Čisti” Swift
Business logika
Granice
Razdvojiti Swift od plaforme i
libraryja
Izdvojiti logiku aplikacije
MVVM
UIViewController
NAVIGACIJA
UIKIT
PRIKAZ
UI LOGIKA
NETWORKING
BUSINESS

LOGIKA
TRANSFORMA
CIJA
PODATAKA
MIJENJANJE

STANJA
UIViewController
NAVIGACIJA
UIKIT
PRIKAZ
UI LOGIKA
NETWORKINGBUSINESS

LOGIKA
TRANSFORMA
CIJA
PODATAKA
MIJENJANJE

STANJA
ViewModel
MVVM++
Example
States
LoadedLoading No data Error
States
class FeedViewModel {
enum ViewState {
case loading
case noData
case error(String)
case loaded([FeedCellModel])
}
}
Data
struct FeedCellModel {
let name: String
let description: String
let image: URL?
}
Lagano za verificirati,
bez stanja (nepromjenljivo)
class FeedViewModel {
func loadData() {
self.state = .loading
feedService.getFeedItem(page: 0) { result in
switch result {
case let .success(items):
if items.isEmpty {
self.state = .noData
} else {
let models = self.feedCellModels(from: items)
self.state = .loaded(models)
}
case let .failure(error):
let errorText = self.errorText(for: error)
self.state = .error(errorText)
}
}
}
}
class FeedViewModel {
func loadData() {
self.state = .loading
feedService.getFeedItem(page: 0) { result in
switch result {
case let .success(items):
if items.isEmpty {
self.state = .noData
} else {
let models = self.feedCellModels(from: items)
self.state = .loaded(models)
}
case let .failure(error):
let errorText = self.errorText(for: error)
self.state = .error(errorText)
}
}
}
}
class FeedViewModel {
func loadData() {
self.state = .loading
feedService.getFeedItem(page: 0) { result in
switch result {
case let .success(items):
if items.isEmpty {
self.state = .noData
} else {
let models = self.feedCellModels(from: items)
self.state = .loaded(models)
}
case let .failure(error):
let errorText = self.errorText(for: error)
self.state = .error(errorText)
}
}
}
}
class FeedViewModel {
func loadData() {
self.state = .loading
feedService.getFeedItem(page: 0) { result in
switch result {
case let .success(items):
if items.isEmpty {
self.state = .noData
} else {
let models = self.feedCellModels(from: items)
self.state = .loaded(models)
}
case let .failure(error):
let errorText = self.errorText(for: error)
self.state = .error(errorText)
}
}
}
}
class FeedViewModel {
func loadData() {
self.state = .loading
feedService.getFeedItem(page: 0) { result in
switch result {
case let .success(items):
if items.isEmpty {
self.state = .noData
} else {
let models = self.feedCellModels(from: items)
self.state = .loaded(models)
}
case let .failure(error):
let errorText = self.errorText(for: error)
self.state = .error(errorText)
}
}
}
}
class FeedViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
viewModel.onStateChanged = { [weak self] state in
guard let `self` = self else { return }
switch state {
case .noData:
self.refreshControl.endRefreshing()
self.manager.data = []
self.errorImage.isHidden = true
self.errorLabel.text = Localizable.error_empty_feed
self.errorView.isHidden = false
case .error(let error):
self.manager.data = []
self.refreshControl.endRefreshing()
self.errorImage.isHidden = false
self.errorLabel.text = error
self.errorView.isHidden = false
case .loaded(let items):
self.refreshControl.endRefreshing()
self.manager.data = items
self.errorView.isHidden = true
case .loading:
self.refreshControl.beginRefreshing()
}
}
}
Prednosti
1. Cijeli state na jednom mjestu
2. Manipulacija statea izdvojena iz iOS-a
3. Lagano ubacivanje dodatnog 

statea
Prednosti
Testabilan dizajn = dobar dizajn
Testiranje
1. Spremi promjenu statea u array.
2. Okini akcije.

3. Provjeri state array.
class FeedDetailsViewModelTests: XCTestCase {
var feedService: FeedServiceMock!
var states: [FeedDetailsViewModel.ViewState] = []
var viewModel: FeedDetailsViewModel!
override func setUp() {
super.setUp()
feedService = FeedServiceMock()
states = []
viewModel = FeedViewModel(feedService)
viewModel.onState = { self.states.append($0) }
}
class FeedDetailsViewModelTests: XCTestCase {
var feedService: FeedServiceMock!
var states: [FeedDetailsViewModel.ViewState] = []
var viewModel: FeedDetailsViewModel!
override func setUp() {
super.setUp()
feedService = FeedServiceMock()
states = []
viewModel = FeedViewModel(feedService)
viewModel.onState = { self.states.append($0) }
}
class FeedDetailsViewModelTests: XCTestCase {
var feedService: FeedServiceMock!
var states: [FeedDetailsViewModel.ViewState] = []
var viewModel: FeedDetailsViewModel!
override func setUp() {
super.setUp()
feedService = FeedServiceMock()
states = []
viewModel = FeedViewModel(feedService)
viewModel.onState = { self.states.append($0) }
}
class FeedDetailsViewModelTests: XCTestCase {
var feedService: FeedServiceMock!
var states: [FeedDetailsViewModel.ViewState] = []
var viewModel: FeedDetailsViewModel!
override func setUp() {
super.setUp()
feedService = FeedServiceMock()
states = []
viewModel = FeedViewModel(feedService)
viewModel.onState = { self.states.append($0) }
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testLoadDataTransitionsToLoadedState() {
viewModel.loadData()
switch (states.first!, states.last!) {
case (.loading, .loaded):
break
default:
XCTFail()
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testLoadDataTransitionsToLoadedState() {
viewModel.loadData()
switch (states.first!, states.last!) {
case (.loading, .loaded):
break
default:
XCTFail()
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testLoadDataTransitionsToLoadedState() {
viewModel.loadData()
switch (states.first!, states.last!) {
case (.loading, .loaded):
break
default:
XCTFail()
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testLoadDataTransitionsToLoadedState() {
viewModel.loadData()
switch (states.first!, states.last!) {
case (.loading, .loaded):
break
default:
XCTFail()
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testFeedItemData() {
viewModel.loadData()
switch states.last! {
case .loaded(let data):
XCTAssertEqual(data, self.feedService.mockFeedItems)
default:
XCTFail("Expected `loaded`")
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testFeedItemData() {
viewModel.loadData()
switch states.last! {
case .loaded(let data):
XCTAssertEqual(data, self.feedService.mockFeedItems)
default:
XCTFail("Expected `loaded`")
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testFeedItemData() {
viewModel.loadData()
switch states.last! {
case .loaded(let data):
XCTAssertEqual(data, self.feedService.mockFeedItems)
default:
XCTFail("Expected `loaded`")
}
}
}
final class FeedDetailsViewModelTests: XCTestCase {
// …

func testFeedItemData() {
viewModel.loadData()
switch states.last! {
case .loaded(let data):
XCTAssertEqual(data, self.feedService.mockFeedItems)
default:
XCTFail("Expected `loaded`")
}
}
}
Rinse and

repeat.
Dependencyji
Stub / mock
Preuzeti kontrolu nad
dependencyjem
Lakše testiranje
1.
Dependency

Injection
class PersistenceService {
var token: String? {
let defaults = UserDefaults.standard
return defaults.object(forKey: "user_token") as? String
}
}
class PersistenceService {
var token: String? {
let defaults = UserDefaults.standard
return defaults.object(forKey: "user_token") as? String
}
}
Implicitni dependency
class PersistenceService {
private let defaults: UserDefaults
init(_ defaults: UserDefaults) {
self.defaults = defaults
}
var token: String? {
return defaults.object(forKey: "user_token") as? String
}
}
Pozivatelj

kreira 

dependency
2.
Dependency

Inversion
class PersistenceService {
private let defaults: UserDefaults
init(_ defaults: UserDefaults) {
self.defaults = defaults
}
var token: String? {
return defaults.object(forKey: "user_token") as? String
}
}
protocol ObjectStore {
func set(value: Any?, forKey: String)
func object(forKey: String)-> Any?
}
protocol ObjectStore {
func set(value: Any?, forKey: String)
func object(forKey: String)-> Any?
}
extension UserDefaults: ObjectStore {}
class PersistenceService {
private let defaults: ObjectStore
init(_ defaults: ObjectStore) {
self.defaults = defaults
}
var token: String? {
return defaults.object(forKey: "user_token") as? String
}
}
class UserDefaultsMock: ObjectStore {
func object(forKey: String) -> Any? {
}
func set(value: Any?, forKey: String) {
}
}
let userDefaultsMock = UserDefaultsMock()
let persistenceService = PersistenceService(userDefaultsMock)
class UserDefaultsMock: ObjectStore {
var data: [String: Any?] = [:]
func object(forKey key: String) -> Any? {
return data[key] ?? nil
}
func set(value: Any?, forKey key: String) {
data[key] = value
}
}
final class PersistenceServiceTests: XCTestCase {
var store: ObjectStoreMock!
var service: PersistenceService!
override func setUp() {
super.setUp()
store = ObjectStoreMock()
service = PersistenceService(store)
}
func testRetrievesSavedTokenFromStore() {
store.data["token"] = "savedToken"
XCTAssertEqual(service.token, "savedToken")
}
}
Pisanje
mockova.
class LoginServiceMock: LoginServiceProtocol {
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
}
}
class LoginServiceMock: LoginServiceProtocol {
var loginParameters: (username: String, password: String)?
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
loginParameters = (username, password)
}
}
class LoginServiceMock: LoginServiceProtocol {
var loginParameters: (username: String, password: String)?
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
loginParameters = (username, password)
}
}
class LoginServiceMock: LoginServiceProtocol {
var loginParameters: (username: String, password: String)?
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
loginParameters = (username, password)
}
}
func testCallsLoginServiceWithCorrectParams() {
loginViewModel.login(

email: "email@mail.com", 

password: "123pass")
let expectedParams = ("email@mail.com", "123pass")
XCTAssertEqual(expectedParams,

loginServiceMock.loginParameters)
}
var loginShouldSucceed = true
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
if loginShouldSucceed {
completion(.success(UserToken(token: "abc123")))
} else {
completion(.failure(.noInternet))
}
}
var loginShouldSucceed = true
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
if loginShouldSucceed {
completion(.success(UserToken(token: "abc123")))
} else {
completion(.failure(.noInternet))
}
}
var loginShouldSucceed = true
func login(username: String, password: String,
completion: @escaping (LoginResult)-> Void) {
if loginShouldSucceed {
completion(.success(UserToken(token: "abc123")))
} else {
completion(.failure(.noInternet))
}
}
func testHandlesErrorCorrectly() {
loginServiceMock.loginShouldSucceed = false
loginViewModel.login(email: "mail@mail.com", 

password: "123pass")
XCTAssertNotNil(viewModel.errorText)
}
Sourcery je
prijatelj.
Link na kraju preze.
Pisanje testova
Testovi su
teški.
Dobri testovi
su teški.
Ne prolazi za ni jednu netočnu
implementaciju.
1. Pokrivenost
func testHandlesErrorCorrectly() {
loginServiceMock.loginShouldSucceed = false
loginViewModel.login(email: "mail@mail.com", 

password: "123pass")
XCTAssertNotNil(viewModel.errorText)
}
Prazan string?
Test prolazi za sve korektne
implementacije.
1. Lakoća
refaktoringa
func testStoresUsernameCorrectly() {
let store = UserDataStore()
store.store(username: "Marin")
XCTAssertEqual(store.storage["username"], "Marin")
}
func testStoresUsernameCorrectly() {
let store = UserDataStore()
store.store(username: "Marin")
XCTAssertEqual(store.storage["username"], "Marin")
}
func testStoresUsernameCorrectly() {
let store = UserDataStore()
store.store(username: "Marin")
XCTAssertEqual(store.storedUsername, "Marin")
}
vs
Korektno
+
Fleksibilno
Tips & tricks
Odaberi dobar
framework
Nek te CI
natjera
Piši helpere
Testiraj nešto
Whew!
Testing For People Who Hate Testing

https://eev.ee/blog/2016/08/22/testing-for-people-who-hate-testing/
AutoMockable Sourcery template

https://cdn.rawgit.com/krzysztofzablocki/Sourcery/master/docs/mocks.html
Unit Testing in Swift

https://medium.cobeisfresh.com/unit-testing-in-swift-part-1-the-philosophy-9bc85ed5001b

Weitere ähnliche Inhalte

Was ist angesagt?

Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose worldFabio Collini
 
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsDrupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsMichael Miles
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbroncymbron
 
Selenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkSelenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkDavid Rajah Selvaraj
 
Simplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackSimplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackGabor Varadi
 
Net Beans Codes for Student Portal
Net Beans Codes for Student PortalNet Beans Codes for Student Portal
Net Beans Codes for Student PortalPeeyush Ranjan
 
Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Michael Miles
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... AgainPedro Vicente
 
Spring Certification Questions
Spring Certification QuestionsSpring Certification Questions
Spring Certification QuestionsSpringMockExams
 
Selenium my sql and junit user guide
Selenium my sql and junit user guideSelenium my sql and junit user guide
Selenium my sql and junit user guideFahad Shiekh
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgetsscottw
 
E2E testing con nightwatch.js - Drupalcamp Spain 2018
E2E testing con nightwatch.js  - Drupalcamp Spain 2018E2E testing con nightwatch.js  - Drupalcamp Spain 2018
E2E testing con nightwatch.js - Drupalcamp Spain 2018Salvador Molina (Slv_)
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceNiraj Bharambe
 
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Converting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesConverting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesKaniska Mandal
 
Sustaining Test-Driven Development
Sustaining Test-Driven DevelopmentSustaining Test-Driven Development
Sustaining Test-Driven DevelopmentAgileOnTheBeach
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 DreamLab
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsMichael Miles
 

Was ist angesagt? (20)

Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose world
 
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsDrupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
 
Exercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera CymbronExercícios Netbeans - Vera Cymbron
Exercícios Netbeans - Vera Cymbron
 
Selenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkSelenium Webdriver with data driven framework
Selenium Webdriver with data driven framework
 
Simplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackSimplified Android Development with Simple-Stack
Simplified Android Development with Simple-Stack
 
Net Beans Codes for Student Portal
Net Beans Codes for Student PortalNet Beans Codes for Student Portal
Net Beans Codes for Student Portal
 
Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
 
Spring Certification Questions
Spring Certification QuestionsSpring Certification Questions
Spring Certification Questions
 
Selenium my sql and junit user guide
Selenium my sql and junit user guideSelenium my sql and junit user guide
Selenium my sql and junit user guide
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
E2E testing con nightwatch.js - Drupalcamp Spain 2018
E2E testing con nightwatch.js  - Drupalcamp Spain 2018E2E testing con nightwatch.js  - Drupalcamp Spain 2018
E2E testing con nightwatch.js - Drupalcamp Spain 2018
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
React lecture
React lectureReact lecture
React lecture
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer science
 
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
Converting Db Schema Into Uml Classes
Converting Db Schema Into Uml ClassesConverting Db Schema Into Uml Classes
Converting Db Schema Into Uml Classes
 
Sustaining Test-Driven Development
Sustaining Test-Driven DevelopmentSustaining Test-Driven Development
Sustaining Test-Driven Development
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback Commands
 

Ähnlich wie iOS Talks 6: Unit Testing

Writing Your App Swiftly
Writing Your App SwiftlyWriting Your App Swiftly
Writing Your App SwiftlySommer Panage
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with ReduxVedran Blaženka
 
Controllers & actions
Controllers & actionsControllers & actions
Controllers & actionsEyal Vardi
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIJames Shvarts
 
Cocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersCocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersStijn Willems
 
Asp.net mvc training
Asp.net mvc trainingAsp.net mvc training
Asp.net mvc trainingicubesystem
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POPNatasha Murashev
 
Core Data with Swift 3.0
Core Data with Swift 3.0Core Data with Swift 3.0
Core Data with Swift 3.0Korhan Bircan
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testingsmontanari
 
JDBC for CSQL Database
JDBC for CSQL DatabaseJDBC for CSQL Database
JDBC for CSQL Databasejitendral
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_twTse-Ching Ho
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation洪 鹏发
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEAndrzej Ludwikowski
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and EasybIakiv Kramarenko
 
Conditional fields - Olga Riabodzei
Conditional fields - Olga RiabodzeiConditional fields - Olga Riabodzei
Conditional fields - Olga RiabodzeiDrupalCamp Kyiv
 
Unit test candidate solutions
Unit test candidate solutionsUnit test candidate solutions
Unit test candidate solutionsbenewu
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practicesClickky
 

Ähnlich wie iOS Talks 6: Unit Testing (20)

Writing Your App Swiftly
Writing Your App SwiftlyWriting Your App Swiftly
Writing Your App Swiftly
 
Asp.NET MVC
Asp.NET MVCAsp.NET MVC
Asp.NET MVC
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
Controllers & actions
Controllers & actionsControllers & actions
Controllers & actions
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVI
 
Cocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersCocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollers
 
Asp.net mvc training
Asp.net mvc trainingAsp.net mvc training
Asp.net mvc training
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
Core Data with Swift 3.0
Core Data with Swift 3.0Core Data with Swift 3.0
Core Data with Swift 3.0
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testing
 
JDBC for CSQL Database
JDBC for CSQL DatabaseJDBC for CSQL Database
JDBC for CSQL Database
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_tw
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
 
Easy tests with Selenide and Easyb
Easy tests with Selenide and EasybEasy tests with Selenide and Easyb
Easy tests with Selenide and Easyb
 
Conditional fields - Olga Riabodzei
Conditional fields - Olga RiabodzeiConditional fields - Olga Riabodzei
Conditional fields - Olga Riabodzei
 
Unit test candidate solutions
Unit test candidate solutionsUnit test candidate solutions
Unit test candidate solutions
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 

Kürzlich hochgeladen

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identityteam-WIBU
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 

Kürzlich hochgeladen (20)

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Post Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on IdentityPost Quantum Cryptography – The Impact on Identity
Post Quantum Cryptography – The Impact on Identity
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 

iOS Talks 6: Unit Testing