SlideShare a Scribd company logo
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

More Related Content

What's hot

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
 

What's hot (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
 

Similar to 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
 

Similar to 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
 

Recently uploaded

Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfMayankTawar1
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxwottaspaceseo
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownloadvrstrong314
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamtakuyayamamoto1800
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfGlobus
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Hivelance Technology
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageGlobus
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowPeter Caitens
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfAMB-Review
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfkalichargn70th171
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobus
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Globus
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...informapgpstrackings
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Globus
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesKrzysztofKkol1
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...Juraj Vysvader
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILNatan Silnitsky
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfOrtus Solutions, Corp
 

Recently uploaded (20)

Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 

iOS Talks 6: Unit Testing