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 — 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 — 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.
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.
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.
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.
| Assertion | Layunin | Halimbawa |
|---|---|---|
| XCTAssertEqual | Pagsusuri ng pagkakapantay | XCTAssertEqual(a, b) |
| XCTAssertTrue | Pagsusuri ng katotohanan | XCTAssertTrue(result) |
| XCTAssertNil | Pagsusuri ng nil | XCTAssertNil(error) |
| XCTAssertThrowsError | Pagsusuri ng error | XCTAssertThrowsError(try parse("")) |
| XCTUnwrap | Pagkuha ng optional | XCTUnwrap(value) |
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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
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.
Basahin din