Date post: | 14-Apr-2017 |
Category: |
Software |
Upload: | andrey-volobuev |
View: | 181 times |
Download: | 0 times |
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 на тест
Мало тестов
Много тестов
ВОПРОСЫ?