Unit testing iOS Applications

Post on 14-Apr-2017

181 views 0 download

transcript

Unit тестирование iOS приложений

Андрей Волобуев

Что такое unit тесты

Для чего тестировать

Когда тестировать

Виды unit тестов

Двойники для тестов

Управление зависимостями

Лучшие практики

Тезисы

Что такое unit тесты ?

Модульное тестирование, или юнит-тестирование (англ. unit testing) — процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.

Википедия

Что такое unit тесты ?Класс Тест класс

Метод 1

Метод 2

Тест метод 1.2

Тест метод 2.1

Тест метод 1.1

.

.

.

Для чего тестировать ?

Уверенность в корректности работы программы

Возможность рефакторинга

Исполняемая документация

Исполняемые требования

Работа с CI системами

Доказательство что баг исправлен

Когда тестировать ?TDD - сначала пишется тест

Refactor

Red

Green

Когда тестировать ?

Обычное тестирование - тесты пишутся после кода

Когда тестировать

Вопрос в том насколько после

Виды unit тестов

Возвращаемый результат

Состояние

Поведение

Двойники для тестов

Клиент Официант Повар

Ресторан

Двойники для тестов

Клиент Официант Тест повар

Ресторан

Двойники для тестов

Stub - возвращают заранее предопределенный результат

Mock - содержат логику для проверки поведения

Управление зависимостями

Dependency injection

// Менеджер ресторана должен сказать нам какой стол свободен struct Manager{ // Он обращается к сервису реализующему протокол var tablesService: FreeTableProvider func getFreeTable() -> Int{ let tableId = tablesService.getTable() return tableId } // Constructor injection init(tablesService: FreeTableProvider = ProductionTableProvider()){ self.tablesService = tablesService } } // Протокол для сервиса protocol FreeTableProvider{ func getTable() -> Int }

struct ProductionTableProvider: FreeTableProvider{ func getTable() -> Int { let tableId = makeLongRunningRequestAndReturnTable() return tableId } private func makeLongRunningRequestAndReturnTable() -> Int { . . . } }

class StubFreeTableProvider: FreeTableProvider{ func getTable() -> Int { return 42 } }

class ManagerTests: XCTestCase {

override func setUp() { super.setUp() } override func tearDown() {

super.tearDown() } func testManagerRetunsFreeTable(){ let stubFreeTableProvider = StubFreeTableProvider() let manager = Manager(tablesService: stubFreeTableProvider) let tableId = manager.getFreeTable() XCTAssertEqual(tableId, 42, "Менеджер возвращает столик полученный от сервиса") } }

protocol OrderExecutor{ func executeOrder() } // Теперь мы тестируем внутреннее состояние официанта struct Waiter{

// Столик с которым работает официант var currentTableId: Int?

var cook: OrderExecutor func excecuteOrder(){ cook.executeOrder() } // Функция позвать официанта к столику mutating func call(toTable tableId: Int){ currentTableId = tableId }

init(orderExecutor: OrderExecutor){ self.cook = orderExecutor } }

class WaiterUnitTests: XCTestCase { override func setUp() { super.setUp() } override func tearDown() {

super.tearDown() } func testWaiterServesTableAfterCalling(){ var waiter = Waiter() let tableId = 42 waiter.call(toTable: tableId) XCTAssertEqual(tableId, waiter.currentTableId, "Официанта приходит к столику") } }

// Тот кто реализует этот протокол может исполнять заказы protocol OrderExecutor{ func executeOrder() } // Теперь поведение официанта struct Waiter{

var currentTableId: Int?

// Тот кто реализует этот протокол может исполнять заказы var cook: OrderExecutor

// Функция передать заказ повару func excecuteOrder(){

cook.executeOrder() } mutating func call(toTable tableId: Int){ currentTableId = tableId }

// Constructor injection init(orderExecutor: OrderExecutor = ProductionOrderExecutor()){

self.cook = orderExecutor } }

class MockCook: OrderExecutor{ var isOrederExecuted = false func executeOrder() { isOrederExecuted = true } }

class WaiterUnitTests: XCTestCase {

func testWaiterGivesOrderToCook(){ let mockCook = MockCook() let waiter = Waiter(orderExecutor: mockCook) waiter.excecuteOrder() XCTAssertTrue(mockCook.isOrederExecuted, "Официант отдал заказ повару”) } }

Лучшие практики DRY

if, switch, for, while

Сложные setUp

Вычисляемые ожидаемые значения

Много assert на тест

Мало тестов

Много тестов

ВОПРОСЫ?