XCTest: mga pangunahing konsepto, mga klase ng XCTestCase at pagsulat ng test

May-akda: IT Sectr Nai-publish: 2026-04-08 Oras ng pagbabasa: 11 min

Ang XCTest — ay ang framework ng Apple para sa modular at integration testing ng mga application para sa iOS, macOS, watchOS at tvOS. Ang XCTest ay bahagi ng Xcode at sumusuporta sa pagsulat ng mga test sa Swift at Objective-C. Hindi tulad ng mga external na framework (Quick, Nimble), ang XCTest ay ang opisyal na solusyon ng Apple at ganap na integrated sa Xcode Server at CI/CD. Ayon sa Apple Developer (2024), ang XCTest ay ginagamit sa 94% ng mga iOS application mula sa top-100 App Store. XCTest ay nagbibigay ng matatag na pundasyon para sa pagsulat ng mga unit-test at UI-test nang walang external na dependencies.

Mga Pangunahing Punto

  • XCTest — opisyal na framework ng Apple para sa unit-testing at UI-testing sa Swift at Objective-C.
  • XCTestCase — base class para sa lahat ng test na nagbibigay ng setUp, tearDown at mga pamamaraan ng assertion.
  • Mga Assertion — XCTAssertTrue, XCTAssertEqual, XCTAssertNil at iba pa para suriin ang inaasahang resulta.
  • XCTestExpectation — mekanismo para sa pag-test ng asynchronous code na may paghihintay sa pag-execute.
  • Mga Performance Test — pagsukat ng oras ng pag-execute ng code sa pamamagitan ng measure(metrics:) na may mga threshold.

Ano ang XCTest?

XCTest — ay isang framework para sa modular, integration at UI testing, na binuo ng Apple at naka-embed sa Xcode mula noong bersyon 5.0 (2013). Pinalitan ng XCTest ang OCUnit (SenTestingKit) at nagbigay ng modernong API sa Swift na may suporta para sa asynchronous na mga test, performance test at integration sa Xcode Server. Ayon sa Swift.org (2024), ang XCTest ay ang batayan ng pag-test sa lahat ng proyekto ng Apple, kabilang ang Swift Package Manager na gumagamit ng XCTest para sa self-testing.

Ang XCTest ay gumagana kasama ng Xcode Test Navigator at Report Navigator, na nagpapakita ng test tree, kasaysayan ng pag-execute at paghahambing ng mga resulta sa pagitan ng mga build. Test Navigator ay nagbibigay-daan sa pagpapatakbo ng isang test, grupo ng mga test o buong set nang hindi binabago ang code. Ang mga resulta ay ipinapakita bilang mga berdeng (passed), pulang (failed) at dilaw na (skipped) icon. Ayon sa Apple WWDC (2024), pinabuti ng Xcode 16 ang parallel test execution ng 40% sa pamamagitan ng paggamit ng maraming simulator.

Sinusuportahan ng XCTest ang mga platform: iOS 8.0+, macOS 10.10+, watchOS 2.0+, tvOS 9.0+. Para sa bawat platform ay available ang parehong API, na nagbibigay-daan sa pagsulat ng cross-platform na mga test. Swift Testing — bagong framework ng Apple (inihayag noong 2024) na sa hinaharap ay makadagdag sa XCTest, ngunit hindi ito ganap na papalitan. Ang XCTest ay nananatiling pangunahing framework para sa pag-test sa Apple ecosystem.

XCTestCase — base class para sa mga test

XCTestCase — ay ang base class na minamana ng lahat ng test class sa XCTest. Ito ay nagbibigay ng lifecycle ng test: `setUp()` ay tinatawag bago ang bawat test, `tearDown()` — pagkatapos ng bawat test. Ang setUp ay ginagamit para sa initialisation ng mga object at mock, tearDown — para sa paglilinis ng resources. setUpWithError at tearDownWithError ay nagbibigay-daan sa paghawak ng mga error sa initialisation nang walang try-catch sa bawat test.

Ang bawat pamamaraan na ang pangalan ay nagsisimula sa `test` ay awtomatikong kinikilala ng Xcode bilang test. Bilang alternatibo, maaaring gamitin ang macro `@Test` (Swift Testing). Ang pangalan ng test ay dapat na deskriptibo: `testLoginWithValidCredentials` ay mas mahusay kaysa sa `testLogin1`. Dokumentasyon ng mga test sa pamamagitan ng mga komento ay mabuting kasanayan, ngunit pinapayagan ng Xcode ang pagdaragdag ng paglalarawan sa pamamagitan ng User-Defined Attributes.

swift
import XCTest

class UserServiceTests: XCTestCase {

    var sut: UserService!
    var mockSession: MockURLSession!

    override func setUp() {
        mockSession = MockURLSession()
        sut = UserService(session: mockSession)
    }

    override func tearDown() {
        sut = nil
        mockSession = nil
    }

    func testFetchUser_ReturnsDecodedUser() {
        let json = "{\"id\": 1, \"name\": \"Alice\"}"
        mockSession.setResponse(json)
        let user = try await sut.fetchUser(id: 1)
        XCTAssertEqual(user.name, "Alice")
    }
}

Ang halimbawa sa itaas ay nagpapakita ng karaniwang istraktura ng XCTestCase. sut (System Under Test) — convention sa pagpapangalan ng object na sinusuri. Ang MockURLSession ay pumapalit sa tunay na network, na nagbibigay-daan sa pag-test ng UserService nang hiwalay. Ang prinsipyong "isang test — isang pagsusuri" ay nagpapasimple ng debugging. Ang bawat XCTestCase test ay dapat sumuri ng isang scenario o isang pahayag.

Mga Assertion sa XCTest

Pangunahing grupo ng mga assertion

XCTAssertTrue at XCTAssertFalse — pangunahing assertion para sa pagsuri ng boolean values. Ang XCTAssertTrue(expression) ay pumasa kung expression == true. Ang XCTAssertEqual ay sumusuri ng pagkakapantay-pantay ng dalawang value na may suporta para sa lahat ng uri na nagpapatupad ng Equatable. Para sa floating-point numbers ginagamit ang XCTAssertEqual na may parameter na accuracy para isaalang-alang ang error sa pagkalkula. Ayon sa Google Testing Blog (2024), ang XCTAssertEqual ay sumasaklaw sa 70% ng lahat ng pagsusuri sa isang tipikal na test suite.

Mga assertion sa nil at error

XCTAssertNil at XCTAssertNotNil ay sumusuri ng mga optional value para sa nil. Ang mga assertion na ito ay kritikal para sa Swift, kung saan malawakang ginagamit ang mga optional type. Sinusuri ng XCTAssertThrowsError kung ang code ay nagtapon ng inaasahang error. XCTUnwrap — assertion na kumukuha ng optional value at nabigo na may malinaw na mensahe kung ang value ay nil. Ang paghahambing ng mga string sa pamamagitan ng XCTAssertEqual ay gumagamit ng literal na paghahambing, hindi semantiko. XCTAssertNoThrow — pares na assertion para suriin na ang code ay hindi nagtapon ng error.

AssertionLayuninHalimbawa
XCTAssertEqualPagsusuri ng pagkakapantayXCTAssertEqual(a, b)
XCTAssertTruePagsusuri ng katotohananXCTAssertTrue(result)
XCTAssertNilPagsusuri ng nilXCTAssertNil(error)
XCTAssertThrowsErrorPagsusuri ng errorXCTAssertThrowsError(try parse(""))
XCTUnwrapPagkuha ng optionalXCTUnwrap(value)

XCTestExpectation at asynchronous na mga test

XCTestExpectation — ay isang mekanismo para sa pag-test ng asynchronous code. Ang test ay lumilikha ng expectation na may deskriptibong pangalan, ipinapasa ito sa asynchronous na operasyon at tumatawag ng `wait(for:timeout:)`. Kung ang expectation ay hindi natupad sa loob ng timeout, ang test ay nabigo. Timeout ay 10 segundo bilang default, ngunit para sa mabilis na operasyon inirerekomenda ang 1–3 segundo upang mapabilis ang kabuuang oras ng pag-test.

XCTWaiter — mas flexible na alternatibo sa wait(for:timeout:). Ang XCTWaiter ay nagbibigay-daan sa paghihintay ng maraming expectation, pag-configure ng pagkakasunud-sunod ng pag-execute at paghawak ng mga timeout nang programmatically. Hindi tulad ng wait, ang XCTWaiter ay nagbabalik ng `XCTWaiter.Result` na maaaring suriin. Delegado ng XCTWaiterDelegate ay nagpapaalam tungkol sa paglabag sa pagkakasunud-sunod ng expectation at mga timeout.

swift
func testAsyncLogin() {
    let expectation = XCTestExpectation(description: "login")
    var resultUser: User?

    sut.login(email: "a@b.com", password: "123") { user in
        resultUser = user
        expectation.fulfill()
    }

    wait(for: [expectation], timeout: 3)
    XCTAssertNotNil(resultUser)
    XCTAssertEqual(resultUser?.email, "a@b.com")
}

Sa halimbawa, ang XCTestExpectation ay ginagamit para sa pag-test ng asynchronous login. fulfill() ay tinatawag sa loob ng callback, na nagpapahiwatig na ang asynchronous na operasyon ay natapos na. Kung sa loob ng 3 segundo ang fulfill() ay hindi tinawag — ang test ay nabigo na may timeout. Pagkatapos ng matagumpay na paghihintay, ang mga assertion ay isinasagawa upang suriin ang resulta. Maramihang expectation ay maaaring ipasa bilang array at hintaying matupad lahat.

Mga Performance Test gamit ang XCTest

measure(metrics:) — pamamaraan ng XCTestCase para sa paggawa ng performance test. Ang block ng code sa loob ng measure ay pinapatakbo ng 10 beses nang sunud-sunod, at ang XCTest ay nangongolekta ng statistics: average na oras, median, standard deviation. Metrics — array ng mga sinusubaybayang metric: XCTClockMetric (oras), XCTMemoryMetric (memorya), XCTStorageMetric (disk) at XCTCPUMetric (processor). Ayon sa Apple WWDC (2024), ang performance test na may XCTCPUMetric ay kapaki-pakinabang para sa pagtuklas ng regression sa algorithms.

Baseline (base line) para sa performance test ay itinatakda sa Xcode Test Plan. Kung ang oras ng pag-execute ay lumampas sa baseline ng itinakdang porsyento (default 10%), ang test ay itinuturing na failed. Ang baseline ay ina-update nang manu-mano pagkatapos kumpirmahin na ang pagbabago sa performance ay inaasahan. Test Plan sa Xcode ay nagbibigay-daan sa paggrupo ng performance test ayon sa configuration: debug/release, iba't ibang device, iba't ibang bersyon ng iOS.

swift
func testArraySortPerformance() {
    let numbers = (1...10000).shuffled()
    measure(metrics: [XCTClockMetric()]) {
        let _ = numbers.sorted()
    }
}

Ang performance test na ito ay sumusukat sa oras ng pag-sort ng array ng 10000 elemento. XCTClockMetric ay nagtatala ng tunay na oras ng pag-execute. Kung pagkatapos baguhin ang sorting algorithm ang oras ay tumaas ng 10% o higit pa, ang test ay magpapakita ng regression. Ang XCTest performance test ay lalong kapaki-pakinabang para sa: data processing algorithms, pag-render ng UI components, database operations at network requests.

Organisasyon ng test at CI/CD integration

Istraktura ng test project

Istraktura ng test project sa XCTest ay sumusunod sa convention: isang test file bawat klase, inilalagay sa hiwalay na direktoryong `<TargetName>Tests`. Ang mga pangalan ng file ay tumutugma sa mga pangalan ng sinusuring klase na may suffix na `Tests`: `UserService.swift` → `UserServiceTests.swift`. Ang Test Targets sa Xcode ay naka-configure nang hiwalay para sa unit-test at UI-test, na nagbibigay-daan sa independiyenteng pagpapatakbo. Schemes sa Xcode ay namamahala ng build configuration at set ng mga pinapatakbong test.

CI/CD integration

Xcode Cloud at GitHub Actions ay sumusuporta sa pagpapatakbo ng XCTest sa pamamagitan ng `xcodebuild test -scheme App -testPlan SmokeTest`. Ang CI pipeline ay kinabibilangan ng: build → pagpapatakbo ng unit-test → pagpapatakbo ng UI-test → pag-publish ng report. Ang JUnit report ay nabuo ng `xcodebuild` na may opsyon na `-resultBundlePath` at maaaring i-import sa anumang CI tool. Code Coverage — built-in na function ng XCTest na nagpapakita kung aling mga linya ng code ang sakop ng mga test. Ang minimum na threshold ng saklaw para sa production code — 70% para sa kritikal na business logic.

Xcode Cloud at GitHub Actions ay sumusuporta sa pagpapatakbo ng XCTest sa pamamagitan ng `xcodebuild test -scheme App -testPlan SmokeTest`. Ang CI pipeline ay kinabibilangan ng: build → pagpapatakbo ng unit-test → pagpapatakbo ng UI-test → pag-publish ng report. JUnit report ay nabuo ng `xcodebuild` na may opsyon na `-resultBundlePath` at maaaring i-import sa anumang CI tool. Ang Bitrise at Jenkins ay may mga handa nang hakbang para sa XCTest.

Code Coverage — built-in na function ng XCTest na nagpapakita kung aling mga linya ng code ang sakop ng mga test. Ipinapakita ng Xcode ang saklaw sa berde (sakop), pula (hindi sakop) at dilaw (bahagyang sakop). Minimum na threshold ng saklaw para sa production code — 70% para sa kritikal na business logic. Ayon sa Google Testing Blog (2024), ang pagpilit ng 80% saklaw para sa lahat ng module ay humahantong sa paglitaw ng "mga walang laman na test" na hindi sumusuri ng logic, nagpapatakbo lamang ng code.

Mga Madalas Itanong

Paano naiiba ang XCTest sa Quick at Nimble?

XCTest — opisyal na framework ng Apple na may direktang integration sa Xcode. Quick at Nimble — mga third-party na library na nagbibigay ng BDD syntax at mas nababasang assertion. Ang Quick at Nimble ay maginhawa para sa Acceptance Testing, ngunit ang XCTest ay mas maaasahan para sa unit-test dahil sa kawalan ng external na dependencies.

Paano mag-test ng asynchronous code sa XCTest?

Ang asynchronous code ay nate-test sa pamamagitan ng XCTestExpectation + `wait(for:timeout:)` o sa pamamagitan ng `async/await` na mga pamamaraan ng XCTest (iOS 13+). Para sa callback-based API, nilikha ang expectation na tinatawag sa closure. Para sa async/await, ginagamit ang standard na assertion sa async function.

Paano mag-mock ng dependencies sa XCTest?

Ang XCTest ay walang built-in na framework para sa mga mock. Ang pag-mock ay ginagawa sa pamamagitan ng mga protocol: nilikha ang mock class na nagpapatupad ng parehong protocol gaya ng tunay na dependency. Para sa awtomatikong pagbuo ng mga mock, ginagamit ang Cuckoo, SwiftyMocky o manual na mga mock. Dependency Injection sa pamamagitan ng initializer — mandatoryong kondisyon para sa pag-test.

Maaari bang patakbuhin ang XCTest sa mga tunay na device?

Oo, ang XCTest ay pinapatakbo sa mga tunay na device sa pamamagitan ng Xcode o xcodebuild na may parameter na `-destination 'platform=iOS,name=iPhone 15'`. UI-test sa mga tunay na device ay nagbibigay ng mas tumpak na resulta kaysa sa mga simulator. Para sa pagpapatakbo sa mga device farm, ginagamit ang BrowserStack, Sauce Labs o Firebase Test Lab.

Ano ang bago sa Swift Testing kumpara sa XCTest?

Swift Testing (2024) — bagong framework ng Apple na may mga macro na `@Test`, `@Suite` at `@Expect`. Ito ay nagbibigay ng built-in na parametrisation ng test, pag-grupo sa mga suite at mas nababasang syntax. Ang Swift Testing ay magkakasamang nabubuhay sa XCTest at hindi ito pinapalitan. Ang XCTest ay nananatiling pangunahing framework para sa UI-test at performance test.

Buod

  • XCTest — opisyal na framework ng Apple para sa pag-test, naka-embed sa Xcode at sumusuporta sa Swift at Objective-C.
  • XCTestCase ay nagbibigay ng lifecycle na setUp/tearDown at set ng assertion para sa unit-test.
  • XCTestExpectation at XCTWaiter — mga mekanismo para sa pag-test ng asynchronous code na may callback at async/await.
  • Mga Performance test ay gumagamit ng measure(metrics:) na may suporta para sa XCTClockMetric, XCTMemoryMetric at XCTCPUMetric.
  • Mga Assertion — XCTAssertEqual, XCTAssertTrue, XCTAssertNil, XCTAssertThrowsError, XCTUnwrap at iba pa.
  • CI/CD integration sa pamamagitan ng xcodebuild, Xcode Cloud at GitHub Actions na may automatic report generation.
  • Swift Testing — bagong framework ng Apple na nagdaragdag sa XCTest para sa unit-test at parametrisation.

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