TDD: шта је то, принципи тестирања и методологија

Аутор: IT Sectr Објављено: 2026-04-09 Време читања: 9 мин

Test-Driven Development (TDD) — јесте методологија развоја у којој се тестови пишу пре имплементације кода. Програмер прво формулише очекивано понашање у виду падајућег теста, затим пише минимални код за његово пролажење и након тога рефакторише резултат. Према Martin Fowler (2023), TDD није техника тестирања — то је техника пројектовања која дисциплинује архитектуру и смањује број дефеката у фази писања кода.

Главно

  • TDD — методологија у којој се тест пише пре имплементације, а не после ње
  • Циклус Red-Green-Refactor — основа TDD: црвени тест, зелени тест, рефакторинг
  • JUnit и Mockito — главни алати за TDD у Android развоју
  • Покривеност кода у TDD пројектима често прелази 90% захваљујући дисциплини „тест пре свега"
  • Рефакторинг без страха од ломљења функционалности — кључна предност TDD приступа

Шта је TDD?

Test-Driven Development — јесте пракса развоја софтвера у којој аутоматизовани тестови одређују писање продукцијског кода. За разлику од традиционалног приступа где се код прво пише, а затим тестира, TDD преокреће редослед: прво се пише тест, затим код који тај тест пролази.

Оснивачем TDD сматра се Kent Beck, који је формулисао ову праксу крајем 1990-их година у оквиру методологије Extreme Programming (XP). У књизи „Test-Driven Development: By Example" (2002) Бек је описао пет правила TDD која су постала канонска: пиши тест пре продукцијског кода, пиши тачно онолико кода колико је потребно за пролажење теста и рефакториши после сваког циклуса.

Кључни принципи TDD

Први принцип — тест дефинише интерфејс. Програмер је приморан да размишља о томе како ће компонента бити коришћена пре него што размисли о томе како је имплементирана. Ово формира чист API од самог почетка.

TDD као техника пројектовања

Други принцип — минимална имплементација. Када је тест написан, програмер пише тачно онолико продукцијског кода колико је потребно за његово пролажење — ни ред више. Ово спречава превремену апстракцију и прекомерну сложеност коју Martin Fowler назива Speculative Generality.

Разлика између TDD и обичног тестирања

Кључна разлика између TDD и тестирања „накнадно" — дисциплина редоследа. У TDD тест не само да проверава код — он усмерава његову структуру. Према истраживању Microsoft Research (Nagappan et al., 2008), тимови који примењују TDD показују смањење густине дефеката за 40–90% у поређењу са тимовима који користе традиционални приступ.

Циклус Red-Green-Refactor

Циклус Red-Green-Refactor — је тростепени след који се понавља за сваки нови тест. Red: напиши тест који не пролази. Green: напиши минимални код да тест прође. Refactor: побољшај код без мењања његовог понашања.

Фаза Red: писање падајућег теста

Програмер пише тест који проверава још неимплементирану функционалност. У овој фази тест треба да падне — то потврђује да тест заиста нешто проверава. У окружењу Android развоја оквир JUnit 5 показује црвену индикацију за пале тестове, што је и дало име фази.

kotlin
class CalculatorTest {
    fun testAddition() {
        val result = Calculator().add(2, 3)
        Assertions.assertEquals(5, result)
    }
}

Фаза Green: минимална имплементација

У овој фази пише се минимални продукцијски код довољан за пролажење теста. Без икаквог вишка — само оно што је потребно за зелену индикацију. Ако имплементација може бити константа — нека буде константа. Рефакторинг ће се десити у следећем кораку када се појаве нови тестови.

kotlin
class Calculator {
    fun add(a: Int, b: Int): Int {
        return a + b
    }
}

Фаза Refactor: побољшање без ризика

Зелени тест је осигурање за рефакторинг. Програмер може да препише имплементацију, оптимизује перформансе или побољша читљивост, сигуран да ће тест одмах открити било какво одступање од очекиваног понашања. У мобилном развоју на Android-у ова фаза је посебно важна за издвајање заједничких интерфејса и смањење дуплирања кода.

Предности TDD у мобилном развоју

Примена TDD у мобилним пројектима даје мерљиве предности, потврђене како академским истраживањима, тако и праксом водећих развојних студија.

Смањење густине дефеката

Истраживање IBM (Bhat & Nagappan, 2006) на четири индустријска пројекта показало је да тимови који користе TDD праве 40% мање дефеката у поређењу са сличним тимовима који раде по традиционалној шеми. За мобилни развој, где је цена исправке бага после објављивања у Google Play значајно већа него у фази писања кода, ова метрика је критична.

Документовање кода кроз тестове

Тестови написани по TDD служе као жива документација API-ја. Програмер који долази у пројекат може да чита тестове и разуме како треба да се користи свака компонента. Ово је посебно вредно у условима високе флуктуације тима — типичног проблема мобилних студија.

Сигуран рефакторинг

Покривеност кода тестовима која прелази 90% омогућава програмерима да спроводе рефакторинг без страха да ће нешто покварити. Google у својој књизи „Software Engineering at Google" (2020) назива тест покривеност кључним фактором који омогућава одржавање базе кода чистом у пројектима са милионима линија кода.

Алати и оквири за TDD

Екосистем TDD у мобилном развоју укључује алате за јединичне тестове, mocking и проверу UI компоненти — како за Android, тако и за iOS.

АлатПлатформаНамена
JUnit 5Android (Kotlin/Java)Основни оквир за јединичне тестове
MockitoAndroidКреирање mock објеката и верификација позива
MockKAndroid (Kotlin)Mocking са Kotlin-first синтаксом и подршком за корутине
TurbineAndroidТестирање Kotlin Flow и реактивних токова
XCTestiOS (Swift)Стандардни оквир за тестирање

Избор оквира за Android

За Android пројекте на Kotlin стандардни стек укључује JUnit 5 + MockK. MockK је пожељнији од Mockito-а јер подржава Kotlin функције прве класе — sealed class, корутине и suspend-функције без додатног подешавања.

Алати за iOS

У iOS развоју TDD се имплементира кроз XCTest — уграђени Apple оквир који пружа асерције, тест класе и интеграцију са CI/CD путем Xcode Server или GitHub Actions. За mocking на iOS-у користе се библиотеке Cuckoo и OHHTTPStubs.

Примери кода са TDD у Kotlin

Размотримо реални сценарио TDD у Kotlin за Android — тестирање репозиторијума корисника. Прво пишемо тест, затим — имплементацију која пролази тај тест.

Корак 1: тест за UserRepository

kotlin
class UserRepositoryTest {
    private val api = mockk<UserApi>()
    private val dao = mockk<UserDao>()
    private val repo = UserRepository(api, dao)

    fun `when api returns user then cache and emit`() = runTest {
        val user = User(1, "Alice")
        coEvery { api.getUser(1) } returns user
        every { dao.insert(user) } returns Unit

        val result = repo.getUser(1)

        assertEquals(user, result)
        verify { dao.insert(user) }
    }
}

Корак 2: минимална имплементација

kotlin
class UserRepository(
    private val api: UserApi,
    private val dao: UserDao
) {
    suspend fun getUser(id: Int): User {
        val user = api.getUser(id)
        dao.insert(user)
        return user
    }
}

Корак 3: тест за кеширање са офлајн режимом

Након пролажења првог теста додајемо други — проверавамо понашање при грешци мреже. Сада тест одређује да при паду API-ја репозиторијум треба да врати податке из кеша.

kotlin
fun `when api fails then return cached user`() = runTest {
    val cached = User(1, "Cached Alice")
    coEvery { api.getUser(1) } throws IOException()
    every { dao.getById(1) } returns cached

    val result = repo.getUser(1)

    assertEquals(cached, result)
}

Типичне грешке при увођењу TDD

Прелазак на TDD праћен је типичним грешкама које могу поништити све предности методологије. Разумевање ових замки помаже тимовима да ефикасније имплементирају праксу.

Превелики тестови

Први и најраспрострањенији анти-образац — тестирање превеликог обима функционалности у једном тесту. Тест треба да проверава тачно једну тврдњу (један асерт). Ако тест падне, програмер треба да зна шта се тачно покварило без додатног отклањања грешака.

Игнорисање црвене фазе

Друга грешка — писање теста који одмах пролази. Ако тест није био црвен бар једном, нема сигурности да уопште нешто проверава. Правило: никада не веруј тесту који ниси видео да пада.

Прескакање рефакторинга

Трећа типична грешка — заустављање на зеленој фази. Рефакторинг није опциона, већ обавезна фаза циклуса. Без ње база кода деградира, тестови постају крхки и предности TDD се губе.

  • Тестирање имплементације, а не понашања — тестови се везују за детаље и ломе при сваком рефакторингу
  • Недостатак тестова за ивичне случајеве — празне листе, null вредности, гранични услови остају непокривени
  • Игнорисање брзине тестова — спори тестови успоравају повратну петљу и убијају дисциплину TDD

Често постављана питања

TDD — је техника тестирања или пројектовања?

TDD је пре свега техника пројектовања, а не тестирања. Тестови у TDD играју улогу спецификације: они дефинишу API компоненте пре њене имплементације. Сам Kent Beck назива TDD „дисциплином пројектовања, а не тестирања".

Колико времена је потребно да се савлада TDD?

Према истраживањима Microsoft Research, тимовима је потребно од 3 до 6 месеци непрекидне праксе да TDD уђе у навику. Прве 2–3 недеље продуктивност пада за 15–30%, али након адаптације враћа се на почетни ниво или га премашује захваљујући смањењу времена за отклањање грешака.

Да ли TDD одговара за UI компоненте?

Да, али са ограничењима. За UI логику (ViewModel, State) TDD се примењује директно. За визуелне компоненте (Compose UI, SwiftUI Views) тестирање снимцима екрана (snapshot testing) допуњује TDD, али га не замењује. Препоручује се раздвајање пословне логике и приказа.

Може ли се TDD применити у legacy пројектима?

За legacy код препоручује се стратегија „карактеризационих тестова" (characterization tests) — када се тестови пишу на постојеће понашање, а затим се код рефакторише. Овај приступ описан у књизи Michael Feathers „Working Effectively with Legacy Code" (2004) омогућава постепено увођење TDD.

Како се TDD уклапа са Clean Architecture?

TDD и Clean Architecture се међусобно појачавају. Чиста архитектура захтева јасне границе између слојева, а TDD приморава програмера да пројектује те границе кроз тестове. Доменски слој се тестира изоловано са mock зависностима, слој података — кроз интеграционе тестове.

Закључак

  • TDD — методологија у којој се тест пише пре имплементације, обликујући чист API и усмеравајући архитектуру
  • Циклус Red-Green-Refactor — основна јединица TDD: пали тест → минимална имплементација → рефакторинг
  • Примена TDD смањује густину дефеката за 40–90% према истраживањима IBM и Microsoft Research
  • Главни алати за Android: JUnit 5, MockK, Turbine за Flow
  • MockK је пожељнији од Mockito-а у Kotlin пројектима захваљујући подршци за корутине и sealed class
  • Типичне грешке: превелики тестови, прескакање црвене фазе, игнорисање рефакторинга
  • Препоручена стратегија увођења — постепена, почевши од доменског слоја и нових функција, без покушаја покривања целог legacy кода одједном

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође