Pagsusuri ng Unit sa Mobile Development: Ano Ito, Mga Paraan, at Framework

May-akda: IT Sectr Nai-publish: 2026-04-06 Oras ng pagbabasa: 9 min

Ang pagsusuri ng unit ay isang paraan ng pag-verify ng software kung saan sinusuri ang kawastuhan ng mga indibidwal na module o function ng code sa paghihiwalay mula sa natitirang sistema. Ayon kay Martin Fowler, 2026, ang mga unit test ay pundasyon ng CI/CD at refactoring, na nagbibigay ng mabilis na feedback tungkol sa paggana ng code. Modular na pagsusuri ay tumutulong na makita ang mga error sa maagang yugto ng pag-develop, na binabawasan ang gastos ng pag-aayos ng mga ito nang sampu-sampung beses.

Mga Pangunahing Punto

  • Unit test — pagsusuri ng isang module (function, method, class) sa paghihiwalay mula sa mga external dependency
  • Mga prinsipyo ng FIRST — Fast, Isolated, Repeatable, Self-validating, Timely — batayan ng de-kalidad na pagsusuri
  • Mga mock at stub — kapalit ng mga external dependency (database, API, file system), tinitiyak ang paghihiwalay ng test
  • TDD (Test-Driven Development) — metodolohiya ng pag-develop sa pamamagitan ng pagsusuri: pula-berde-refactoring
  • Piramide ng pagsusuri — ang mga unit test ay sumasakop ng 70% ng piramide, nagbibigay ng mabilis na feedback sa bawat commit

Ano ang pagsusuri ng unit?

Ang pagsusuri ng unit ay proseso ng pagsuri ng mga indibidwal na yunit ng source code — mga function, method, class — sa paghihiwalay mula sa natitirang programa. Bawat test ay nagpapatakbo ng isang partikular na senaryo ng paggamit ng module at sinusuri kung ang resulta ay tumutugma sa inaasahan. Ang mga unit test ay isinusulat sa parehong programming language gaya ng pangunahing code at awtomatikong isinasagawa sa development environment o sa CI/CD pipeline. Hindi tulad ng integration tests, ang mga unit test ay hindi nakikipag-ugnayan sa mga totoong database, file system, o network services.

Bakit kailangan ang mga unit test?

Ang pangunahing layunin ay mabilis na feedback tungkol sa kawastuhan ng code pagkatapos ng mga pagbabago. Kung ang developer ay nag-refactor ng isang method, kinukumpirma ng set ng unit test na hindi nasira ang behavior. Ayon sa Google Testing Blog (2025), ang mga proyektong may coverage ng unit test na higit sa 60% ay may 2.5 beses na mas kaunting production incidents. Mga karagdagang benepisyo: dokumentasyon ng code (ipinapakita ng test kung paano gamitin ang API), pagpapasimple ng refactoring (maaaring baguhin ang implementasyon habang pinapanatili ang behavior), at mabilis na diagnosis ng regression.

Ano ang itinuturing na unit test?

Hindi lahat ng awtomatikong test ay unit test. Mga pamantayan: isang module (class o function) ang sinusuri, ang mga external dependency ay pinalitan ng mga mock o stub, ang test ay isinasagawa sa millisecond, hindi nangangailangan ng pagpapatakbo ng server o database. Ang test na uma-access sa totoong database ay integration test. Ang test na nagbubukas ng browser ay E2E test. Ang pag-unawa sa mga hangganan sa pagitan ng mga uri ng test ay mahalaga para sa tamang pamamahagi ng pagsisikap sa piramide ng pagsusuri.

Mga prinsipyo ng FIRST at istruktura ng AAA

Ang mga de-kalidad na unit test ay sumusunod sa mga prinsipyo ng FIRST na binuo ni Robert C. Martin. Bawat test ay dapat na Fast (mabilis — millisecond), Isolated (nakahiwalay — hindi nakadepende sa ibang test), Repeatable (paulit-ulit — parehong resulta sa anumang makina), Self-validating (nagpapatunay sa sarili — resulta ay “passed” o “failed”, walang manual na pagsusuri), at Timely(napapanahon — isinulat bago o kasabay ng code). Ang paglabag sa alinmang prinsipyo ay nagbabawas ng halaga ng test.

Istruktura ng AAA (Arrange-Act-Assert)

Karaniwang template para sa pagsulat ng mga unit test. Arrange — paghahanda ng data at dependency: paggawa ng object, pag-configure ng mock, pagtatakda ng input parameter. Act — pagsasagawa ng sinusuri na aksyon: pagtawag ng method o function. Assert — pagsusuri ng resulta: paghahambing ng aktwal na halaga sa inaasahan. Ang paghahati sa tatlong block ay ginagawang nababasa at naiintindihan ang test. Kung ang Assert block ay nangangailangan ng komplikadong logic, malamang na masyadong marami ang sinusuri ng test nang sabay-sabay.

kotlin
// Halimbawa ng unit test ayon sa AAA template sa Kotlin na may JUnit 5
class CalculatorTest {

    private lateinit var calculator: Calculator

    @BeforeEach
    fun setUp() {
        // ARRANGE — ginagawa natin ang sinusuring object
        calculator = Calculator()
    }

    @Test
    fun addition_shouldReturnCorrectSum() {
        // ACT — ginagawa natin ang aksyon
        val result = calculator.add(2, 3)

        // ASSERT — sinusuri natin ang resulta
        Assertions.assertEquals(5, result)
    }
}

Pagpapangalan ng test

Ang pangalan ng test ay dapat naglalarawan kung ano ang sinusuri at kung anong resulta ang inaasahan. Format: [methodName]_[scenario]_[expectedResult]. Halimbawa: calculateTotal_whenDiscountApplied_shouldReturnDiscountedTotal. Ang magandang pangalan ng test ay pumapalit sa komento at sa pagkabigo ay agad na nagpapakita kung aling functionality ang nasira. Iwasan ang mga pangalan tulad ng test1, checkSomething, o verify — hindi sila nagbibigay ng impormasyon at nagpapahirap sa diagnosis.

Mga mock, stub, at fake: ano at kailan gagamitin

Para sa paghihiwalay ng sinusuring module mula sa mga external dependency, ginagamit ang mga test double. Mga pangunahing uri: mock — sinusuri kung ang isang partikular na method ay tinawag gamit ang tamang parameter; stub — nagbabalik ng itinakdang halaga kapag tinawag ang method; fake — pinasimpleng implementasyon ng isang totoong component (hal. InMemoryUserRepository sa halip na UserRepository na gumagana sa database). Ang pagpili ay depende sa kung ano ang kailangang suriin: estado (stub) o interaksyon (mock).

DoubleAno ang sinusuriHalimbawa
MockPagtawag ng method na may tamang parameteruserRepository.save(user) ay tinawag nang eksaktong 1 beses
StubIbinabalik na halagarepository.findById(1) ay nagbabalik ng User(id=1, name=“Test”)
FakeLogic sa pamamagitan ng pinasimpleng implementasyonInMemoryMapUserRepository na may HashMap sa halip ng database
SpyBahagyang mocking ng totoong objectspy(repo).when(findById).thenReturn(user)

Mockito: halimbawa ng mocking sa Java/Kotlin

Ang Mockito ay ang pinakasikat na framework para sa mocking sa Java at Kotlin. Nagbibigay-daan sa paggawa ng mock sa pamamagitan ng mock(), pag-configure ng mga ibinabalik na halaga sa pamamagitan ng when().thenReturn(), at pagsusuri ng mga tawag sa pamamagitan ng verify(). Ang mga modernong bersyon ng Mockito (5.x) ay sumusuporta sa static mock (mockStatic) at pinasimpleng syntax sa pamamagitan ng BDDMockito (given-willReturn). Mahalagang patakaran: huwag i-mock ang hindi sa iyo — huwag gumawa ng mock para sa value object at standard library.

kotlin
// Halimbawa ng unit test na may Mockito sa Kotlin
class OrderServiceTest {

    @Mock
    private lateinit var paymentGateway: PaymentGateway

    @Mock
    private lateinit var userRepository: UserRepository

    private lateinit var orderService: OrderService

    @BeforeEach
    fun init() {
        MockitoAnnotations.openMocks(this)
        orderService = OrderService(paymentGateway, userRepository)
    }

    @Test
    fun processOrder_whenPaymentFails_shouldThrowException() {
        // given
        val user = User(id = 1, balance = 100.0)
        val order = Order(amount = 200.0)
        Mockito.`when`(paymentGateway.charge(any())).thenReturn(false)
        Mockito.`when`(userRepository.findById(1)).thenReturn(user)

        // when & then
        assert Throws<PaymentException> {
            orderService.processOrder(user.id, order)
        }

        // verify
        Mockito.verify(paymentGateway).charge(any())
    }
}

TDD: pag-develop sa pamamagitan ng pagsusuri

TDD (Test-Driven Development) — metodolohiya kung saan ang test ay isinusulat bago ang implementasyon ng code. Ikot ng “Red-Green-Refactor”: sumulat ng test na nabigo (Red), sumulat ng minimal na code para pumasa ang test (Green), pagbutihin ang code nang hindi binabago ang behavior (Refactor). Ginagarantiya ng TDD na ang lahat ng code ay sakop ng test (coverage = 100% para sa isinulat na functionality) at na ang code ay natetest — kung ang code ay mahirap i-test, nangangahulugan ito na ang arkitektura ay nangangailangan ng pagpapabuti.

Mga benepisyo ng TDD

Ayon sa pananaliksik ng IBM (2006-2026, longitudinal study), ang mga team na gumagamit ng TDD ay may 40-80% mas kaunting defect sa produksyon kumpara sa mga team na sumusulat ng test pagkatapos ng code. Pinapabuti rin ng TDD ang arkitektura: ang developer ay kailangang mag-isip tungkol sa disenyo ng API bago ang implementasyon, na humahantong sa maluwag na coupling (loose coupling) at mataas na cohesion (high cohesion). Karagdagang epekto — dokumentasyon na may buhay na code: ang mga test ay nagsisilbing specification ng behavior ng module na laging napapanahon.

Kailan hindi angkop ang TDD?

Ang TDD ay hindi laging optimal. Ang mga UI component ay mahirap i-test sa paghihiwalay — para sa kanila, mas epektibo ang snapshot test o visual regression testing (Percy, Chromatic). Ang prototyping at research (spike solutions) ay hindi nangangailangan ng test. Ang legacy code na walang test ay mahirap sakop sa pamamagitan ng TDD — dito kailangan muna ang characterization tests (mga test na nagre-record ng kasalukuyang behavior bago ang refactoring). Sa mga kasong ito, ang TDD ay hindi ganap na inaalis, kundi inaayos — ang test ay isinusulat para sa binagong functionality, hindi para sa buong legacy code.

Pagsusuri ng unit sa mga mobile application

Ang mobile development ay may kanya-kanyang spec: ang business logic ay madalas na halo-halong may UI code (Activity, ViewController, ViewModel), na nagpapahirap sa unit testing. Pinakamahusay na kasanayan — manipis na view, makapal na ViewModel: ilipat ang lahat ng logic mula sa UI component patungo sa hiwalay na klase (UseCase, Repository, ViewModel) na madaling i-test nang walang emulator. Para sa Android at iOS, may mga native na unit testing framework na tumatakbo sa JVM/Native nang hindi pinapatakbo ang device.

Unit test sa Android (JUnit + Mockito/Robolectric)

Ang Android unit test ay isinasagawa sa lokal na JVM nang walang emulator, na tinitiyak ang bilis ng pagpapatupad — isang tipikal na test ay tumatagal ng mas mababa sa 100ms. Ang JUnit 5 ang pangunahing runner. Para sa ViewModel test, gamitin ang kotlinx-coroutines-test para sa pag-test ng coroutine at Turbine para sa pag-test ng StateFlow. Ang Robolectric ay nagbibigay-daan sa pag-test ng Android-dependent component (Context, Resources) nang walang emulator sa pamamagitan ng pag-load ng shadow class. Para sa Compose test, gamitin ang Compose UI Test — ngunit ito ay UI test na, hindi unit.

Unit test sa iOS (XCTest + Quick/Nimble)

Ang iOS unit test ay isinusulat sa Swift gamit ang XCTest (integrated sa Xcode). Quick + Nimble — BDD frameworks para sa mas nababasang test (describe/context/it). Para sa mocking, gamitin ang Cuckoo (generation ng mock) o SwiftyMocky. Sinusuportahan ng Swift ang protocol at dependency injection, na nagpapadali sa pagpapalit ng dependency. Mahalagang punto: ang iOS unit test ay isinasagawa sa macOS simulator, hindi sa totoong device. Ang test na nangangailangan ng hardware functions (camera, Bluetooth) ay integration test.

Unit test sa Flutter (flutter_test + Mockito)

Ang Flutter unit test ay gumagamit ng flutter_test package at isinasagawa sa Dart VM nang walang emulator. Para sa mocking — ang mockito package na may code generator (build_runner). Ang widget test (sa parehong package) ay sumusuri ng indibidwal na widget, ngunit nangangailangan ng rendering at mas mabagal — gamitin lamang para sa pagsusuri ng UI logic. Ang purong Dart logic (model, repository, blobs) ay nate-test tulad ng ordinaryong Dart test nang hindi ini-import ang flutter_test.

dart
// Halimbawa ng unit test sa Flutter na may mockito
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';

@GenerateMocks([ApiClient])
import 'user_repository_test.mocks.dart';

void main() {
    late MockApiClient mockApi;
    late UserRepository repository;

    setUp(() {
        mockApi = MockApiClient();
        repository = UserRepository(mockApi);
    });

    test('fetchUser returns user when API succeeds', () async {
        // Arrange
        final expectedUser = User(id: 1, name: 'Test');
        when(mockApi.getUser(1))
            .thenAnswer((_) async => expectedUser);

        // Act
        final result = await repository.fetchUser(1);

        // Assert
        expect(result, expectedUser);
        verify(mockApi.getUser(1)).called(1);
    });
}

Mga pinakamahusay na kasanayan at karaniwang pagkakamali

Ang epektibong unit testing ay nangangailangan ng disiplina. Pangunahing patakaran: subukan ang behavior, hindi ang implementasyon. Hindi dapat malaman ng test kung paano na-implement ang module sa loob (anumang pribadong method ang tinatawag, sa anong pagkakasunud-sunod). Kung ang test ay nakatali sa implementasyon, nasisira ito sa bawat refactoring at nawawalan ng halaga. Sinusuri ng test ang kontrata: sa input X dapat may output Y. Exception — mga test para sa algorithm na may kritikal na performance, kung saan mahalaga ang pagkakasunud-sunod ng tawag.

  • Isang pagsusuri bawat test — isang assert o isang grupo ng kaugnay na assert para sa isang lohikal na pagsusuri
  • Iwasan ang pag-uulit — gamitin ang @BeforeEach / setUp para sa shared initialization, parameterized test para sa iba’t ibang input data
  • Huwag subukan ang pribadong method — subukan sa pamamagitan ng pampublikong API. Kung ang pribadong method ay hindi sakop, ang logic nito ay hindi nakikita mula sa labas
  • Sakop ang boundary case — walang laman na koleksyon, null/undefined, negatibong numero, maximum na halaga
  • Huwag gumamit ng Thread.sleep sa test — ginagawa nitong mabagal at hindi stable ang test. Gumamit ng test timeout at coroutine

Anong antas ng coverage ang sapat?

Ang 100% coverage ay hindi maabot at hindi kinakailangang layunin. Ayon sa Google Testing Blog (2025), ang optimal na antas ng coverage para sa unit test ay 70-80% ng lines of code. Ang 100% coverage ay madalas na naaabot sa pamamagitan ng pag-test ng getter, setter, at constructor, na hindi nagdadala ng halaga. Tumutok sa kritikal na business logic: komplikadong kalkulasyon, validation, error handling, edge case. Gamitin ang JaCoCo (Java), Coverage.py (Python), Istanbul (JS) para sa pagsukat at magtakda ng threshold sa CI — pagbagsak ng build sa coverage na mas mababa sa 60%.

CI/CD at unit test

Ang unit test ay unang yugto ng anumang CI/CD pipeline. Isinasagawa ang mga ito sa bawat push sa repository, bago ang build at deploy. Ang average na oras ng pagpapatakbo ng unit test sa isang proyekto ay hindi dapat lumagpas sa 5 minuto — kung mas mahaba, ang test ay hindi na “mabilis” at ang developer ay humihinto sa pagpapatakbo nito nang lokal. Hatiin ang test sa mabilis (unit) at mabagal (integration) at patakbuhin ang mga ito sa iba’t ibang yugto ng pipeline. Gamitin ang parallel execution at fail-fast para sa pagpapabilis.

Mga Madalas Itanong

Paano naiiba ang unit test sa integration test?

Sinusuri ng unit test ang isang module sa paghihiwalay, pinapalitan ang external dependency ng mock. Sinusuri ng integration test ang interaksyon sa pagitan ng maraming totoong component (database, API, file system). Ang unit test ay isinasagawa sa millisecond, ang integration test ay sa segundo. Sa piramide ng pagsusuri, ang unit test ay sumasakop ng 70%.

Anong framework ang pipiliin para sa unit test?

Ang pagpili ay depende sa platform: JUnit 5 para sa Java/Kotlin, XCTest para sa iOS/Swift, pytest para sa Python, Jest/Vitest para sa JavaScript/TypeScript, flutter_test para sa Flutter. Para sa mocking, gamitin ang Mockito (Java), Cuckoo (iOS), unittest.mock (Python), o vitest.mock (JS). Lahat ng modernong framework ay sumusuporta sa parameterized test, built-in assert, at parallel execution.

Ano ang mga prinsipyo ng F.I.R.S.T. sa pagsusuri?

Fast — ang test ay isinasagawa sa millisecond. Isolated — hindi nakadepende sa ibang test at external system. Repeatable — nagbibigay ng parehong resulta sa anumang makina. Self-validating — awtomatikong sinusuri ang resulta. Timely — isinulat bago o kasabay ng code. Ang paglabag sa alinmang prinsipyo ay nagbabawas ng epektibidad ng pagsusuri.

Kailangan bang sumulat ng unit test para sa ViewModel sa Android/iOS?

Oo, sapilitan. Ang ViewModel ay naglalaman ng business logic — paghawak ng event, pag-transform ng data, pamamahala ng estado. Sa Android, gamitin ang kotlinx-coroutines-test para sa coroutine at Turbine para sa pag-test ng StateFlow. Sa iOS, i-test ang Combine Publishers o async/await sa ViewModel. Ang ViewModel test ay purong unit test na tumatakbo sa JVM/macOS nang walang emulator.

Paano i-test ang code na may network request?

Ang network request sa unit test ay hindi isinasagawa — pinapalitan ang mga ito ng mock ng HTTP client. Sa Android, gamitin ang MockWebServer (OkHttp) — ito ay nagpapatakbo ng lokal na HTTP server, na mas gusto kaysa sa mock dahil ginagaya nito ang totoong network interaksyon. Ang MockWebServer ay nagbibigay ng paghihiwalay nang hindi nawawala ang realismo. Para sa iOS — OHHTTPStubs o URLProtocol para sa pag-intercept at pagpapalit ng tugon.

Buod

  • Pagsusuri ng unit — pagsusuri ng indibidwal na module sa paghihiwalay mula sa external dependency na may mabilis na feedback
  • Istruktura ng AAA — Arrange (paghahanda), Act (aksyon), Assert (pagsusuri) — karaniwang template ng test
  • Mock at stub — test double para sa paghihiwalay: sinusuri ng mock ang tawag, nagbabalik ng halaga ang stub
  • TDD — pag-develop sa pamamagitan ng pagsusuri (Red-Green-Refactor) ay nagbabawas ng defect ng 40-80%
  • Mga prinsipyo ng FIRST — Fast, Isolated, Repeatable, Self-validating, Timely — batayan ng de-kalidad na test
  • Mga tool ng platform — JUnit 5 (Android), XCTest (iOS), flutter_test (Flutter), Jest (React Native)
  • Coverage na 70-80% — optimal na antas para sa kritikal na business logic, getter at setter ay hindi nangangailangan ng test

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din