Top Banner
Александр Сычев Ведущий разработчик iOS Тесты и Swift
58

Чистые тесты на Swift

Jan 22, 2017

Download

Technology

Rambler-iOS
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Чистые тесты на Swift

Александр Сычев Ведущий разработчик iOS

Тесты и Swift

Page 2: Чистые тесты на Swift
Page 3: Чистые тесты на Swift
Page 4: Чистые тесты на Swift

Ретроспектива

Советы и рекомендации

Page 5: Чистые тесты на Swift

Ретроспектива

Советы и рекомендации

Page 6: Чистые тесты на Swift

xUnit

Page 7: Чистые тесты на Swift
Page 8: Чистые тесты на Swift

What makes a clean test?

Three things. Readability, readability, and readability.

Robert C. Martin, «Clean Code»

Page 9: Чистые тесты на Swift

Предметно-ориентированный язык

Нет лишнего контекста

Тестируем одно поведение

52

Page 10: Чистые тесты на Swift

Библиотеки

Page 11: Чистые тесты на Swift

Ретроспектива

Советы и рекомендации

Page 12: Чистые тесты на Swift
Page 13: Чистые тесты на Swift
Page 14: Чистые тесты на Swift

Assertions

Page 15: Чистые тесты на Swift

Assertions

public func XCTFail(_ message: String = default, file: StaticString = #file, line: UInt = #line)

Page 16: Чистые тесты на Swift

Assertions

func testExample() { // given

// when

// then XCTFail("message") }

Page 17: Чистые тесты на Swift

Assertions

func testExample() { // given let pair = (20, 16)

// when

// then XCTAssertEqual(pair, (20, 17)) }

Page 18: Чистые тесты на Swift

Assertions

func testExample() { // given let pair = (20, 16)

// when

// then XCTAssertEqual(pair, (20, 17)) }

Page 19: Чистые тесты на Swift

Assertions

func testExample() { // given let pair = (20, 16)

// when

// then XCTAssert(pair == (20, 17)) }

Page 20: Чистые тесты на Swift

Assertions

Page 21: Чистые тесты на Swift

Assertions

Page 22: Чистые тесты на Swift

Write a custom test assertion

Page 23: Чистые тесты на Swift

Custom assertions

func assertIntPairsEqual(actual: (_: Int, _: Int), expected: (_: Int, _: Int), file: StaticString = #file, line: UInt = #line) { if actual != expected { XCTFail("Expected \(expected) but was \(actual)", file: file, line: line) } }

Page 24: Чистые тесты на Swift

Custom assertions

func assertIntPairsEqual(actual: (_: Int, _: Int), expected: (_: Int, _: Int), file: StaticString = #file, line: UInt = #line) { if actual != expected { XCTFail("Expected \(expected) but was \(actual)", file: file, line: line) } }

Page 25: Чистые тесты на Swift

Custom assertions

func assertIntPairsEqual(actual: (_: Int, _: Int), expected: (_: Int, _: Int), file: StaticString = #file, line: UInt = #line) { if actual != expected { XCTFail("Expected \(expected) but was \(actual)", file: file, line: line) } }

Page 26: Чистые тесты на Swift

Custom assertions

Page 27: Чистые тесты на Swift

Custom assertions

func assertPairsEqual<T: Equatable, U: Equatable>(actual: (_: T, _: U), expected: (_: T, _: U), file: StaticString = #file, line: UInt = #line)

Page 28: Чистые тесты на Swift

Mocks

Page 29: Чистые тесты на Swift

Mocks

1. Надежность

2. Скорость

Page 30: Чистые тесты на Swift

Mocks

NSURLSession *mock = OCMClassMock([NSURLSession class]);

Page 31: Чистые тесты на Swift

Mocks

NSURLSession *mock = OCMClassMock([NSURLSession class]);

Page 32: Чистые тесты на Swift

Protocols and Extensions

Page 33: Чистые тесты на Swift

Mocks

struct ToDoService {

init(session: URLSession) { // … }}

let service = ToDoService(session: URLSession.shared)

Page 34: Чистые тесты на Swift

Mocks

struct ToDoService {

init(session: URLSession) { // … }}

let service = ToDoService(session: URLSession.shared)

Page 35: Чистые тесты на Swift

Mocks

protocol URLSessionProtocol {}extension URLSession: URLSessionProtocol {}

struct ToDoService {

init(session: URLSessionProtocol) { // … }}

Page 36: Чистые тесты на Swift

Mocks

protocol URLSessionProtocol {}extension URLSession: URLSessionProtocol {}

struct ToDoService {

init(session: URLSessionProtocol) { // … }}

Page 37: Чистые тесты на Swift

Mocks

protocol URLSessionProtocol {}extension URLSession: URLSessionProtocol {}

struct ToDoService {

init(session: URLSessionProtocol) { // … }}

Page 38: Чистые тесты на Swift

Mocks

protocol URLSessionProtocol {}extension URLSession: URLSessionProtocol {}

struct ToDoService {

init(session: URLSessionProtocol) { // … }}

Page 39: Чистые тесты на Swift

Mocks

let service = ToDoService(session: URLSession.shared)

Page 40: Чистые тесты на Swift

Mocks

class MockURLSession: URLSessionProtocol {}

Page 41: Чистые тесты на Swift

Mocks

protocol URLSessionProtocol {

func dataTask(request: URLRequest, completion:(Data?, Response?, Error?) -> Swift.Void) -> DataTask

}

Page 42: Чистые тесты на Swift

Mocks

class MockURLSession: URLSessionProtocol {

func dataTask(with …) -> URLSessionDataTask { return URLSessionDataTask() }}

Page 43: Чистые тесты на Swift

Mocks

1. Число вызовов

2. Переданные аргументы

Page 44: Чистые тесты на Swift

Mocks

class MockURLSession: URLSessionProtocol { var dataTaskCallCount = 0

func dataTask(with …) -> URLSessionDataTask { dataTaskCallCount += 1 return URLSessionDataTask() }}

Page 45: Чистые тесты на Swift

Mocks

func testExample() { // given

...

// when ...

// then XCTAssertEqual(mockURLSession.dataTaskCallCount, 1)}

Page 46: Чистые тесты на Swift

Mocks

class MockURLSession: URLSessionProtocol { var dataTaskLastURL: URL?

func dataTask(with …) -> URLSessionDataTask { dataTaskLastURL = url return URLSessionDataTask() }}

Page 47: Чистые тесты на Swift

Mocksfunc testExample() { // given

...

// when ...

// then XCTAssertEqual(mockURLSession.dataTaskLastURL?.host, "http://expected.com")}

Page 48: Чистые тесты на Swift

Mocks

1. Используйте вспомогательные методы для одной проверки

2. Накапливайте аргументы в коллекциях

Page 49: Чистые тесты на Swift

Partial mocks

Page 50: Чистые тесты на Swift

Partial mocksclass MockURLSessionDataTask: URLSessionDataTask { private var resumeCallCount = 0

override func resume() { resumeCallCount += 1 }

func verifyResume() { XCTAssertEqual(resumeCallCount, 1) }}

Page 51: Чистые тесты на Swift

Partial mocksclass MockURLSession: URLSessionProtocol { var dataTaskReturnValue: URLSessionDataTask!

func dataTask(with …) -> URLSessionDataTask { return dataTaskReturnValue }}

Page 52: Чистые тесты на Swift

Partial mocks func testExample() { // given let mockDataTask = MockURLSessionDataTask() mockURLSession.dataTaskReturnValue = mockDataTask

// when …

// then mockDataTask.verifyResume() }

Page 53: Чистые тесты на Swift

Partial mocks

💩

Page 54: Чистые тесты на Swift

Выводы

Page 55: Чистые тесты на Swift

1.Чистые тесты должны оставаться чистыми

2.Используйте коллекции вспомогательных методов

3.Добавляйте методы проверок к мокам

4.Используйте #file и #line

5.Не мокируйте value types

Page 56: Чистые тесты на Swift
Page 57: Чистые тесты на Swift

Да, есть библиотеки

Page 58: Чистые тесты на Swift

1.Чистые тесты должны оставаться чистыми

2.Используйте коллекции вспомогательных методов

3.Добавляйте методы проверок к мокам

4.Используйте #file и #line

5.Не мокируйте value types

[email protected]

@asychev89