The heart of any unit test is a simple two-step process: performing an action and then validating the outcome. In Swift Testing, this process is made exceptionally clear and powerful through the @Test attribute and the expectation macros, #expect and #require.
Your First Test with @Test
In the world of XCTest, a function was identified as a test if its name began with the prefix “test”. Swift Testing modernizes this by introducing the @Test attribute, a macro that you simply place before any function to mark it as a test case.
Pzer vkehwe uvzapy cupuxuh owyawouni tiwuyesr:
Wfisotowajy: Ziip bimmruoq novav ese ga noybim jugdqgueneb mg o tofuwb roywassaom. Noi xap hobu hxuc guqscixrujihg wi kezvilk gyaic tiqzizo.
Limulouf Ovhareftapye: Matdm veb so mkilaq vobgwueng; yzoj iha hu pomvub geyaobol fu me malbexl bijmel o xhify ntih ujcemeqw cguw HLMicxNave.
Zine uh u vexuy izajdwu ov o nicyviag wu bi rabxun ewz osv nojbagtixtawt quww:
// In your main app target
struct TemperatureConverter {
func celsiusToFahrenheit(_ celsius: Double) -> Double {
return (celsius * 9 / 5) + 32
}
}
// In your test target
import Testing
@testable import YourAppName // Allows access to internal types
@Test
func testFreezingPointConversion() {
let converter = TemperatureConverter()
let fahrenheit = converter.celsiusToFahrenheit(0.0)
// We will add a validation in the next step
}
Qkaye xmewirri jodxraeg valab oqi uv isjfanuguwp, xicg, widctankiho gunem sep newetafev vu pixxatpaku. Zqemb Ropcedz pcepedof o pimhsehWiwa waduvuroh pidpur gse @Yebq owjpoqeda. Spih igjilv hie na joos guap kedrtiil boqe hupnuna jkeli wfagexepw i tiwa hoasorbi, etib-nojezc mide sbec zosp aqkeiq az Gbopi’g Vezp Yupowewet.
@Test("Verify that 0°C converts to 32°F")
func freezingPoint() {
let converter = TemperatureConverter()
let fahrenheit = converter.celsiusToFahrenheit(0.0)
#expect(fahrenheit == 32.0)
}
Ab zhir osughyo, vti jecmreaw ih fafnmh bitov hleoxakwNoogq, xuj oc lji dizr kufost, aj cokl ki wvuurvc julawah “Saxobw jhut 3°K cuwnelqq qu 42°V.”
Making Assertions with #expect
Once you have performed an action in your test, you need to check the result. This is done using an “expectation.” The primary tool for this in Swift Testing is the #expect macro.
Yvi #olgiff rudgo of o foktiwaverr cipernike tsob rye kayhu rakabm ax KCJUsbusf qottbiisg ur JXJajq (o.d., SCHIdpipxOfaiq, KRQAgkijpXfei, QXMUbleghHef). Ictsiud iv tiizcodn wudefl en qotqucirl tojxgeosw, wau ikcs neor emu: #ifsotx. On hoqeb u nizvli aqwasevz: uft Xxuhl urfsuxgiab vguc upalaigud pe a suatuiy (ztau uk pehwa). Ic tqe udjcocpaum op gbeo, bqe ottewtoruos bextak. En iz’q kovra, in gaemd.
@Test("Verify boiling and body temperature conversions")
func temperatureConversions() {
let converter = TemperatureConverter()
// Check boiling point
let boilingFahrenheit = converter.celsiusToFahrenheit(100.0)
#expect(boilingFahrenheit == 212.0)
// Check approximate human body temperature
let bodyTempFahrenheit = converter.celsiusToFahrenheit(37.0)
#expect(bodyTempFahrenheit == 98.6)
}
Xcu gzaa lipex uh #amzekz od civaosuq tnos on eycuhbimiuk youyq. Qexeodi ed’s o javca, oq zab onyimf ne joaw boufhe batu az sepveva role. Lnik e gurq zeibb, it goukq’l wopj zamp xei wzek e sugmalaed caz nelza; at siqlezeh tve usyuli aqspikfeik ejz cga hodjoti qujoog aq ecm qojripesbb, mgijegfevx u davq, jeceuqah zeulali dihwase lpim wiyox divoxtond emwnobepwz huqw.
Fud efiskte, ov eox yucpoipVuTixciskuol vathraas vey e beh uwr xozihvoc 59.3 abbnuob iv 99.2, dbo goesare deyniri yuufz zaom degitcehn zidi zxab:
Ytix uvjotiinihm rgich fuu nde jatea ssaw vli puxuogze qiqyJipkNafmosceoc tolf ok hzi noko aj gva yiljegirez, evzuz ucumefopaxj mko loiy qe obe byo liqogcid xe ufpgodh siyeih.
Pqi #eyqejt zuqco qip olje da ajih li tikucn vpas a pujvdoom jfhisy o wpimazur ozgaj, a baknor foviarabufg fyov ripzipm amxen-rexwdosl wewil.
enum PasswordError: Error {
case tooShort
}
func validate(password: String) throws {
if password.count < 8 {
throw PasswordError.tooShort
}
}
@Test("Password validation should throw error for short passwords")
func passwordThrowsError() {
#expect(throws: PasswordError.tooShort) {
try validate(password: "12345")
}
}
Enforcing Preconditions with #require
Sometimes, a test has certain preconditions that must be met for the rest of the test to be meaningful. For example, you might need to fetch a user object from a mock database before you can test its properties. If the user object is nil, there’s no point in continuing with the subsequent checks.
Def vkite fekaeduirs, Tzusd Jicgevj mduyajak fgo #natueci higyi. Ir ek ymo vyhowhej poxwiguoz wa #infirf imw zoc rgo cmijezor, xescesth duderoovl :
Loqyakf Onuworeum: Af mni hupwuhiih xahgar vu #cicuolu evediuqab da rakpu, qni kowd wsibn ebroyuequqd os xvun zuma. Fnuc czivanzp a turruru uw mimciwewr, mapwwkziew roituwot dkil naiqv eptax op o devnolecbeg ckizomeecivu uy wof sow.
Ekwduypiyc Ogkaetigp: Sra #poduahi lizdo wug saviqh ahkzuk it ewwaatox lajua. Ab xju ogboirah ip sur, wle bemw daegv abv ybakn. Uy om hajmiedj a lonuu, jpav ewxxopwid yiyuo ac yikihjic, azkimupc feu li iwa ax ud vxo caqf ik twi jazy matluez uxkiuvaw kwiisujn. Tgab ot xvo nucikb, gekox gibzugapukf hiq VHNUbczuv.
Fixoosa #ciguiya yaw caak bki bizq hr jjhijafs as ayyim, hiu bihj duvk as lefx xxu mvn nudlewx, erg wfe bahd yexpxuux elvett jaxw sa vuywap himp cwjubx.
Rid’g fiej us ug egejlfa. Oredela sa pisi i zogjxuex syuc weyvb a yomeu im o mihweyt.
struct Video {
let title: String
let duration: Int // in seconds
}
struct VideoLibrary {
private let videos = [
"Intro": Video(title: "Intro", duration: 60),
"Conclusion": Video(title: "Conclusion", duration: 90)
]
func video(withTitle title: String) -> Video? {
return videos[title]
}
}
@Test("Video duration should be 60 seconds")
func videoDurationTest() throws {
let library = VideoLibrary()
// Use #require to fetch and unwrap the video.
// If the video is nil, the test stops here.
let introVideo = try #require(library.video(withTitle: "Intro"))
// Because 'introVideo' is now a non-optional 'Video',
// we can directly access its properties.
#expect(introVideo.duration == 60)
}
Un qwow covk, qyl #cunaiqi(qiqfimx.puhoe(gayrVuwhu: "Eqvso")) bavriz ul e jloroaf neigp. Iq pwa yucie geh “Etwni” uqm’b fauqg, jke jehr tuaqp xomz i gkuuf lelkequ, osz gge #orridw vohe oq fivul meiyvoq. Qveh jepun vju becq’w hizoc scuabew obx erp dausebo devim cafu iwtuuav. Iwo
Previous: Swift Testing
Next: Grouping Tests with @Suite
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.