- Getting Started with Swift Unit Testing in Xcode
- iOS Unit Testing and UI Testing Tutorial
- Туториал По Unit И UI-Тестированию В IOS
- Writing better unit tests in Swift: Part One
- Writing better unit tests in Swift: Part Two
- Unit tests best practices in Xcode and Swift
Примечание. Чтобы увидеть полный список утверждений XCTestAssertions, перейдите к утверждениям Apple, перечисленным по категориям.
- Нейминг теста:
test_whenFilterOneModelWithWrongQuarter_ItReturnNothing()
sut
должен называться тестируемый класс. sut (subject under test) означает «испытуемый предмет».- Использовать Given-When-Then подход
- В тестах должна быть 1 логическая проверка. Количество
XCTestAssertions
может быть любым.
Open
/// DealsTests
@testable import Deals
import XCTest
class Tests: XCTestCase {
// MARK: - Properties
private var sut, sut_withError: ViewModel!
// MARK: - Test Lifecycle
override funx setUp() {
super.setUp()
sut = ViewModel()
sut_withError = ViewModel()
}
override func tearDown() {
super.tearDown()
sut = nil
sut_withError = nil
}
// MARK: - Tests
func testFunction() {
// given
sut.property = 1
// when
sut.callFunction()
// then
XCTAssertEqual(sut.funcInvokedCount, 1)
}
func testPublisher() {
// given
var loadCompleted = false
// when
cancellable = sut.getResponse()
.sink(receiveCompletion: { completion in
if case .finished = completion {
loadCompleted = true
}
}, receiveValue: { _ in })
// then
XCTAssertTrue(loadCompleted)
}
final class ViewModel: ViewModelProtocol {
// MARK: - Testing
private(set) var funcInvokedCount = 0
// MARK: - ViewModelProtocol
var property = 0
func callFunction() { funcInvokedCount += 1 }
func getResponse() -> AnyPublisher<Void, Never> {
return Empty().eraseToAnyPublisher()
}
}
Open
Для тестирования асинхронного кода можно использовать expectations:
func testAsync() {
//given
let expectation = XCTestExpectation(description: "Download apple.com home page")
//when
sut?.reloadData()
DispatchQueue.main.asyncAfter(dedline: .now() + 0.3) {
expectation.fulfill()
}
wait(for: [expectation], timeout: 0.5)
//then
XCTAssertEqual(sut?.items.count, 2)
}
func testPublisher() {
// given
var loadCompleted = false
// when
cancellable = sut.getResponse()
.sink(receiveCompletion: { completion in
if case .finished = completion {
loadCompleted = true
}
}, receiveValue: { _ in })
// then
XCTAssertTrue(loadCompleted)
}
func getResponse() -> AnyPublisher<Void, Never> {
return Empty().eraseToAnyPublisher()
}
expectation.fulfill()
: вызовите это при закрытии условия успеха обработчика завершения асинхронного метода, чтобы отметить, что ожидание было выполнено.
wait (for: timeout :)
: тест продолжается до тех пор, пока не будут выполнены все ожидания или пока timeout не закончится, в зависимости от того, что произойдет раньше.
Основная задача при тестировании Combine избавиться от использования expectation, чтобы тесты проходили намного быстрее, так как в перспективе, с увеличением количества тестов, таймауты сыграют неприятную роль в производительности тестов"
Open
Для тестирования произодительности необходимо добавить measure
перед вызовом функции с метриками, которые нужно измерить:
func testScoreIsComputedPerformance() {
measure(
metrics: [
XCTClockMetric(),
XCTCPUMetric(),
XCTStorageMetric(),
XCTMemoryMetric()
]
) {
sut.check(guess: 100)
}
}
AnyPublisher<Model, Error>: Just(Model()).setFailureType(to: Error.self).eraseToAnyPublisher()
AnyPublisher<Void, Error>: Empty().eraseToAnyPublisher()
2.4.5.2 Driven Development Theme | Back To iOSWiki Contents | 2.5 Cybersecurity Theme Folder