diff --git a/iOSBooks/iOSBooks.xcodeproj/project.pbxproj b/iOSBooks/iOSBooks.xcodeproj/project.pbxproj index c58777e..3652d78 100644 --- a/iOSBooks/iOSBooks.xcodeproj/project.pbxproj +++ b/iOSBooks/iOSBooks.xcodeproj/project.pbxproj @@ -10,7 +10,7 @@ 0E3964D82314BB470093738B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3964D72314BB470093738B /* AppDelegate.swift */; }; 0E3964DF2314BB4A0093738B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E3964DE2314BB4A0093738B /* Assets.xcassets */; }; 0E3964E22314BB4A0093738B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E3964E02314BB4A0093738B /* LaunchScreen.storyboard */; }; - 0E3964ED2314BB4A0093738B /* iOSBooksTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3964EC2314BB4A0093738B /* iOSBooksTests.swift */; }; + 0E3964ED2314BB4A0093738B /* BookDetailViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3964EC2314BB4A0093738B /* BookDetailViewModelTests.swift */; }; 477DA993F6CBE89C179034EE /* Pods_iOSBooksTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28F20F388C60D311258C5680 /* Pods_iOSBooksTests.framework */; }; 7447D35E2316C91700E01BD3 /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7447D35D2316C91700E01BD3 /* APIClient.swift */; }; 7447D3602316CB1200E01BD3 /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7447D35F2316CB1200E01BD3 /* Reachability.swift */; }; @@ -59,7 +59,7 @@ 0E3964E12314BB4A0093738B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 0E3964E32314BB4A0093738B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0E3964E82314BB4A0093738B /* iOSBooksTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSBooksTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 0E3964EC2314BB4A0093738B /* iOSBooksTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSBooksTests.swift; sourceTree = ""; }; + 0E3964EC2314BB4A0093738B /* BookDetailViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookDetailViewModelTests.swift; sourceTree = ""; }; 0E3964EE2314BB4A0093738B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 18F9E4DBC4A549B0B6E5DFAB /* Pods-iOSBooksTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOSBooksTests.release.xcconfig"; path = "Target Support Files/Pods-iOSBooksTests/Pods-iOSBooksTests.release.xcconfig"; sourceTree = ""; }; 275296C36B2B5A1EBD78A5F1 /* Pods-iOSBooks.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOSBooks.release.xcconfig"; path = "Target Support Files/Pods-iOSBooks/Pods-iOSBooks.release.xcconfig"; sourceTree = ""; }; @@ -156,7 +156,7 @@ 0E3964EB2314BB4A0093738B /* iOSBooksTests */ = { isa = PBXGroup; children = ( - 0E3964EC2314BB4A0093738B /* iOSBooksTests.swift */, + 0E3964EC2314BB4A0093738B /* BookDetailViewModelTests.swift */, 0E3964EE2314BB4A0093738B /* Info.plist */, ); path = iOSBooksTests; @@ -535,7 +535,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0E3964ED2314BB4A0093738B /* iOSBooksTests.swift in Sources */, + 0E3964ED2314BB4A0093738B /* BookDetailViewModelTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/iOSBooks/iOSBooks/BookDetail/View/BookDetailViewController.swift b/iOSBooks/iOSBooks/BookDetail/View/BookDetailViewController.swift index b803c3c..4a3b9c1 100644 --- a/iOSBooks/iOSBooks/BookDetail/View/BookDetailViewController.swift +++ b/iOSBooks/iOSBooks/BookDetail/View/BookDetailViewController.swift @@ -40,7 +40,7 @@ class BookDetailViewController: UIViewController { // MARK: - Actions @IBAction func saveBook(_ sender: UIButton) { - viewModel?.saveBookIfNeeded() + viewModel?.saveBookIfNeeded(andImage: bookImageView?.image) toggleFavoriteButton(sender) } diff --git a/iOSBooks/iOSBooks/BookDetail/ViewModel/BookDetailViewModel.swift b/iOSBooks/iOSBooks/BookDetail/ViewModel/BookDetailViewModel.swift index 9c0ea44..a0790bc 100644 --- a/iOSBooks/iOSBooks/BookDetail/ViewModel/BookDetailViewModel.swift +++ b/iOSBooks/iOSBooks/BookDetail/ViewModel/BookDetailViewModel.swift @@ -6,7 +6,7 @@ // Copyright © 2019 Guilherme Antunes. All rights reserved. // -import Foundation +import UIKit protocol BookDetailViewModelProtocol { func getBookTitle() -> String @@ -17,7 +17,7 @@ protocol BookDetailViewModelProtocol { func presentPreviousStep() func getScreenTitle() -> String? func getBookBuyLinkURL() -> URL? - func saveBookIfNeeded() + func saveBookIfNeeded(andImage image: UIImage?) var savedBook: Bool { get } } @@ -27,7 +27,7 @@ class BookDetailViewModel: BookDetailViewModelProtocol { var selectedBook: Item? weak var view: BookDetailViewControllerPresentable? var coordinator: AppCoordinatorProtocol? - var service = CoreDataClient() + var service: CoreDataClientProtocol? var savedBook: Bool = false // MARK: - ViewModel Protocol Methods @@ -77,18 +77,18 @@ class BookDetailViewModel: BookDetailViewModelProtocol { return nil } - func saveBookIfNeeded() { + func saveBookIfNeeded(andImage image: UIImage? = nil) { if savedBook { deleteBook() return } savedBook = true - service.saveBook(selectedBook) + service?.saveBook(selectedBook, withThumbnail: image) } func deleteBook() { savedBook = false - service.deleteBook(selectedBook) + service?.deleteBook(selectedBook) } } diff --git a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+CollectionView.swift b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+CollectionView.swift index e5fd44c..d22a042 100644 --- a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+CollectionView.swift +++ b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+CollectionView.swift @@ -10,7 +10,7 @@ import UIKit extension BooksListViewController: UICollectionViewDataSource, UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return viewModel?.numberOfItemsInSection() ?? 0 + return viewModel?.numberOfItemsInSection(section) ?? 0 } func numberOfSections(in collectionView: UICollectionView) -> Int { diff --git a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+View.swift b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+View.swift index 13658e0..05a7121 100644 --- a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+View.swift +++ b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController+View.swift @@ -38,7 +38,8 @@ extension BooksListViewController: BooksListViewControllerPresentable { guard var viewModel = viewModel else { return } if !viewModel.showFavorites { viewModel.showFavorites.toggle() - viewModel.loadSavedBooks(shouldShowOnScreen: true) + viewModel.loadSavedBooks() + reloadView() return } viewModel.showFavorites.toggle() diff --git a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController.swift b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController.swift index 733a08c..a528d44 100644 --- a/iOSBooks/iOSBooks/BooksList/View/BooksListViewController.swift +++ b/iOSBooks/iOSBooks/BooksList/View/BooksListViewController.swift @@ -26,7 +26,7 @@ class BooksListViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) setupNavigationBar() - viewModel?.loadSavedBooks(shouldShowOnScreen: false) + viewModel?.loadSavedBooks() viewModel?.showFavorites = false viewModel?.loadBooks() } diff --git a/iOSBooks/iOSBooks/BooksList/View/Subviews/BooksCell.swift b/iOSBooks/iOSBooks/BooksList/View/Subviews/BooksCell.swift index 45011f0..6238cd9 100644 --- a/iOSBooks/iOSBooks/BooksList/View/Subviews/BooksCell.swift +++ b/iOSBooks/iOSBooks/BooksList/View/Subviews/BooksCell.swift @@ -16,23 +16,14 @@ class BooksCell: UICollectionViewCell { // MARK: - Properties var selectedBook: Book? - lazy var imageCache = ImageCache(name: selectedBook?.title ?? "") - func setup(withBook book: Book?) { + func setup(withBook book: Book?, andImage image: UIImage? = nil) { selectedBook = book - if let image = imageCache.retrieveImageInMemoryCache(forKey: selectedBook?.subtitle ?? "") { + if let image = image { bookImageView?.image = image } else { if let book = book, let bookURLString = book.imageLinks?.smallThumbnail, let url = URL(string: bookURLString) { - bookImageView?.kf.setImage(with: url, options: [.cacheOriginalImage], completionHandler: { (result) in - switch result { - case .success(let result): - self.imageCache.store(result.image, forKey: self.selectedBook?.subtitle ?? "") - case .failure(let error): - print(error.localizedDescription) - } - }) - + bookImageView?.kf.setImage(with: url) } } diff --git a/iOSBooks/iOSBooks/BooksList/ViewModel/BooksListViewModel.swift b/iOSBooks/iOSBooks/BooksList/ViewModel/BooksListViewModel.swift index a439fe0..9fe2f68 100644 --- a/iOSBooks/iOSBooks/BooksList/ViewModel/BooksListViewModel.swift +++ b/iOSBooks/iOSBooks/BooksList/ViewModel/BooksListViewModel.swift @@ -10,11 +10,10 @@ import UIKit protocol BooksListViewModelProtocol { func loadBooks() - func loadSavedBooks(shouldShowOnScreen reloadView: Bool) + func loadSavedBooks() func selectBook(atIndexPath indexPath: IndexPath) - func presentPreviousStep() func numberOfSections() -> Int - func numberOfItemsInSection() -> Int + func numberOfItemsInSection(_ section: Int) -> Int func cellForItem(inCollectionView collectionView: UICollectionView, atIndexPath indexPath: IndexPath) -> UICollectionViewCell var showFavorites: Bool { get set } } @@ -22,8 +21,8 @@ protocol BooksListViewModelProtocol { class BooksListViewModel: BooksListViewModelProtocol { var items: [Item] = [] - var savedItems: [Item] = [] - var service = BooksClient() + var savedItems: (books: [Item], images: [UIImage]) = ([],[]) + var service: BooksClientProtocol? var startingIndex = 0 weak var view: BooksListViewControllerPresentable? var selectedBook: Item? @@ -35,34 +34,33 @@ class BooksListViewModel: BooksListViewModelProtocol { return 1 } - func numberOfItemsInSection() -> Int { - return showFavorites ? savedItems.count : items.count + func numberOfItemsInSection(_ section: Int = 0) -> Int { + return showFavorites ? savedItems.books.count : items.count } func cellForItem(inCollectionView collectionView: UICollectionView, atIndexPath indexPath: IndexPath) -> UICollectionViewCell { let cell: BooksCell = collectionView.dequeueReusableCell(for: indexPath) let book: Book? + var image: UIImage? = nil if showFavorites { - book = savedItems[indexPath.item].book + book = savedItems.books[indexPath.item].book + image = savedItems.images[indexPath.item] } else { book = items[indexPath.item].book } - cell.setup(withBook: book) + cell.setup(withBook: book, andImage: image) if indexPath.item == (items.count - 1) && !showFavorites { loadBooks() } return cell } - func loadSavedBooks(shouldShowOnScreen reloadView: Bool = false) { - savedItems = service.fetchSavedBooks() - if reloadView { - view?.reloadView() - } + func loadSavedBooks() { + savedItems = service?.fetchSavedBooks() ?? ([],[]) } func loadBooks() { - service.fetchBooksList(startingIndex: startingIndex).done { [weak self] (list) in + service?.fetchBooksList(startingIndex: startingIndex).done { [weak self] (list) in guard let self = self, let items = list.items else { return } self.items.append(contentsOf: items) self.startingIndex = items.count @@ -79,12 +77,8 @@ class BooksListViewModel: BooksListViewModelProtocol { func selectBook(atIndexPath indexPath: IndexPath) { selectedBook = nil - selectedBook = showFavorites ? savedItems[indexPath.item] : items[indexPath.item] - selectedBookIsFavorite = savedItems.contains(where: { $0.id == selectedBook?.id }) + selectedBook = showFavorites ? savedItems.books[indexPath.item] : items[indexPath.item] + selectedBookIsFavorite = savedItems.books.contains(where: { $0.id == selectedBook?.id }) coordinator?.presentNextStep() } - - func presentPreviousStep() { - coordinator?.presentPreviousStep() - } } diff --git a/iOSBooks/iOSBooks/Coordinators/AppCoordinator/AppCoordinatorDependencyInjector.swift b/iOSBooks/iOSBooks/Coordinators/AppCoordinator/AppCoordinatorDependencyInjector.swift index da9f5b8..48f2e24 100644 --- a/iOSBooks/iOSBooks/Coordinators/AppCoordinator/AppCoordinatorDependencyInjector.swift +++ b/iOSBooks/iOSBooks/Coordinators/AppCoordinator/AppCoordinatorDependencyInjector.swift @@ -25,7 +25,9 @@ class AppCoordinatorDependencyInjector { }() lazy var booksListViewModel: BooksListViewModel = { - return BooksListViewModel() + let viewModel = BooksListViewModel() + viewModel.service = BooksClient() + return viewModel }() lazy var bookDetailViewController: BookDetailViewController = { @@ -38,6 +40,7 @@ class AppCoordinatorDependencyInjector { lazy var bookDetailViewModel: BookDetailViewModel = { let viewModel = BookDetailViewModel() viewModel.selectedBook = booksListViewModel.selectedBook + viewModel.service = CoreDataClient() return viewModel }() diff --git a/iOSBooks/iOSBooks/Data/Clients/Book.xcdatamodeld/Book.xcdatamodel/contents b/iOSBooks/iOSBooks/Data/Clients/Book.xcdatamodeld/Book.xcdatamodel/contents index 5392189..c71747d 100644 --- a/iOSBooks/iOSBooks/Data/Clients/Book.xcdatamodeld/Book.xcdatamodel/contents +++ b/iOSBooks/iOSBooks/Data/Clients/Book.xcdatamodeld/Book.xcdatamodel/contents @@ -5,10 +5,11 @@ + - + \ No newline at end of file diff --git a/iOSBooks/iOSBooks/Data/Clients/BooksClient.swift b/iOSBooks/iOSBooks/Data/Clients/BooksClient.swift index 9ccfee7..2e69b8c 100644 --- a/iOSBooks/iOSBooks/Data/Clients/BooksClient.swift +++ b/iOSBooks/iOSBooks/Data/Clients/BooksClient.swift @@ -9,7 +9,12 @@ import Foundation import PromiseKit -class BooksClient { +protocol BooksClientProtocol: class { + func fetchBooksList(startingIndex index: Int) -> Promise + func fetchSavedBooks() -> (books: [Item], images: [UIImage]) +} + +class BooksClient: BooksClientProtocol { let apiClient: APIClient let coreDataClient: CoreDataClient @@ -23,7 +28,7 @@ class BooksClient { return apiClient.request(model: BooksList.self, BooksAPI.list(startingIndex: index).request) } - func fetchSavedBooks() -> [Item] { + func fetchSavedBooks() -> (books: [Item], images: [UIImage]) { return coreDataClient.fetchAllSavedBooks() } diff --git a/iOSBooks/iOSBooks/Data/Clients/CoreDataClient.swift b/iOSBooks/iOSBooks/Data/Clients/CoreDataClient.swift index e4ce74a..5942a61 100644 --- a/iOSBooks/iOSBooks/Data/Clients/CoreDataClient.swift +++ b/iOSBooks/iOSBooks/Data/Clients/CoreDataClient.swift @@ -7,12 +7,19 @@ // import CoreData -import Foundation import UIKit -class CoreDataClient { - func saveBook(_ item: Item?) { - guard let item = item, let context = context, let entity = NSEntityDescription.entity(forEntityName: "CoreDataBook", in: context) else { return } +protocol CoreDataClientProtocol: class { + func saveBook(_ item: Item?, withThumbnail thumbnail: UIImage?) + func fetchAllSavedBooks() -> (books: [Item], images: [UIImage]) + func deleteBook(_ book: Item?) +} + +class CoreDataClient: CoreDataClientProtocol { + + func saveBook(_ item: Item?, withThumbnail thumbnail: UIImage? = nil) { + guard let item = item, let context = context, let entity = NSEntityDescription.entity(forEntityName: "CoreDataBook", in: context), let imageData = thumbnail?.pngData() else { return } + let coreDataBook = NSManagedObject(entity: entity, insertInto: context) coreDataBook.setValue(item.book?.title, forKey: "title") coreDataBook.setValue(item.id, forKey: "id") @@ -20,6 +27,7 @@ class CoreDataClient { coreDataBook.setValue(item.salesInfo?.buyLink, forKey: "buyLink") coreDataBook.setValue(true, forKey: "isFavorite") coreDataBook.setValue(item.book?.authors?.first, forKey: "author") + coreDataBook.setValue(imageData, forKey: "image") do { try context.save() @@ -28,12 +36,13 @@ class CoreDataClient { } } - func fetchAllSavedBooks() -> [Item] { + func fetchAllSavedBooks() -> (books: [Item], images: [UIImage]) { var books: [Item] = [] - guard let context = context else { return [] } + var images: [UIImage] = [] + guard let context = context else { return ([], []) } let fetchRequest = NSFetchRequest(entityName: "CoreDataBook") do { - guard let result = try context.fetch(fetchRequest) as? [NSManagedObject] else { return [] } + guard let result = try context.fetch(fetchRequest) as? [NSManagedObject] else { return ([], []) } for data in result { let item = Item() item.book = Book() @@ -46,11 +55,17 @@ class CoreDataClient { item.salesInfo?.buyLink = data.value(forKey: "buyLink") as? String item.book?.title = data.value(forKey: "title") as? String books.append(item) + + if let bookImageData = data.value(forKey: "image") as? Data, let bookImage = UIImage(data: bookImageData) { + images.append(bookImage) + } else { + images.append(UIImage()) + } } - return books + return (books, images) } catch { print("Failed to load data from CoreData") - return [] + return ([], []) } } diff --git a/iOSBooks/iOSBooksTests/BookDetailViewModelTests.swift b/iOSBooks/iOSBooksTests/BookDetailViewModelTests.swift new file mode 100644 index 0000000..cb61bc8 --- /dev/null +++ b/iOSBooks/iOSBooksTests/BookDetailViewModelTests.swift @@ -0,0 +1,126 @@ +// +// BookDetailViewModelTests.swift +// iOSBooksTests +// +// Created by Guilherme Antunes on 26/08/19. +// Copyright © 2019 Guilherme Antunes. All rights reserved. +// + +import Quick +import Nimble +@testable import iOSBooks + +class BookDetailViewModelTests: QuickSpec { + + class MockedCoordinator: AppCoordinatorProtocol { + var presentNextStepCalled = false + var presentPreviousStepCalled = false + + func presentNextStep() { + presentNextStepCalled = true + } + + func presentPreviousStep() { + presentPreviousStepCalled = true + } + + + } + + class MockedService: CoreDataClientProtocol { + var saveBookCalled = false + var fetchAllSavedBooksCalled = false + var deleteBookCalled = false + + func saveBook(_ item: Item?, withThumbnail thumbnail: UIImage?) { + saveBookCalled = true + } + + func fetchAllSavedBooks() -> (books: [Item], images: [UIImage]) { + fetchAllSavedBooksCalled = true + return ([],[]) + } + + func deleteBook(_ book: Item?) { + deleteBookCalled = true + } + + + } + + private func createFilledMockedItem() -> Item { + let mockedItem = Item() + let mockedBook = Book() + let mockedSalesInfo = SalesInfo() + let mockedImageLinks = ImageLinks() + mockedBook.title = "Book title" + mockedBook.description = "Book description" + mockedBook.authors = ["Book author"] + mockedImageLinks.thumbnail = "http://www.google.com/bookthumbnail" + mockedBook.imageLinks = mockedImageLinks + mockedSalesInfo.buyLink = "http://www.google.com" + mockedItem.salesInfo = mockedSalesInfo + mockedItem.book = mockedBook + return mockedItem + } + + override func spec() { + + var subject: BookDetailViewModel! + let mockedCoordinator = MockedCoordinator() + var mockedService = MockedService() + + beforeEach { + subject = BookDetailViewModel() + subject.coordinator = mockedCoordinator + subject.selectedBook = nil + mockedService = MockedService() + subject.service = mockedService + } + + it("should test successfully item retriving") { + subject.selectedBook = self.createFilledMockedItem() + expect(subject.getBookAuthors()).to(equal("Autor: Book author")) + expect(subject.getBookTitle()).to(equal("Título: Book title")) + expect(subject.getBookBuyLink()).to(equal("http://www.google.com")) + expect(subject.getScreenTitle()).to(equal("Book title")) + expect(subject.getBookBuyLinkURL()).to(equal(URL(string: "http://www.google.com")!)) + expect(subject.getBookImageLink()).to(equal(URL(string: "http://www.google.com/bookthumbnail")!)) + expect(subject.getBookDescription()).to(equal("Book description")) + } + + it("should test a nil item") { + expect(subject.getBookAuthors()).to(equal("Autores não disponíveis")) + expect(subject.getBookTitle()).to(equal("Título indisponível")) + expect(subject.getBookBuyLink()).to(equal("Link de compra não disponível")) + expect(subject.getScreenTitle()).to(beNil()) + expect(subject.getBookBuyLinkURL()).to(beNil()) + expect(subject.getBookImageLink()).to(beNil()) + expect(subject.getBookDescription()).to(equal("Sem descrição disponível")) + } + + it("should test back button function call") { + subject.presentPreviousStep() + expect(mockedCoordinator.presentPreviousStepCalled).to(beTrue()) + expect(mockedCoordinator.presentNextStepCalled).to(beFalse()) + } + + it("should test book saving") { + subject.savedBook = false + subject.saveBookIfNeeded() + expect(subject.savedBook).to(beTrue()) + expect(mockedService.saveBookCalled).to(beTrue()) + expect(mockedService.deleteBookCalled).to(beFalse()) + } + + it("should test book deletion") { + subject.savedBook = true + subject.saveBookIfNeeded() + expect(subject.savedBook).to(beFalse()) + expect(mockedService.saveBookCalled).to(beFalse()) + expect(mockedService.deleteBookCalled).to(beTrue()) + } + + } + +} diff --git a/iOSBooks/iOSBooksTests/iOSBooksTests.swift b/iOSBooks/iOSBooksTests/iOSBooksTests.swift deleted file mode 100644 index 9c97b0e..0000000 --- a/iOSBooks/iOSBooksTests/iOSBooksTests.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// iOSBooksTests.swift -// iOSBooksTests -// -// Created by Guilherme Antunes on 26/08/19. -// Copyright © 2019 Guilherme Antunes. All rights reserved. -// - -import XCTest -@testable import iOSBooks - -class iOSBooksTests: XCTestCase { - - override func setUp() { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -}