{"id":51086,"date":"2026-02-24T16:50:38","date_gmt":"2026-02-24T21:50:38","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=51086"},"modified":"2026-02-24T16:50:38","modified_gmt":"2026-02-24T21:50:38","slug":"swift-testing-with-event-streams","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2026\/02\/24\/swift-testing-with-event-streams\/","title":{"rendered":"Swift Testing With Event Streams"},"content":{"rendered":"<p><a href=\"https:\/\/www.massicotte.org\/blog\/testing-event-stream\/\">Matt Massicotte<\/a>:<\/p>\n<blockquote cite=\"https:\/\/www.massicotte.org\/blog\/testing-event-stream\/\">\n<p>The original implementation used <a href=\"https:\/\/developer.apple.com\/documentation\/xctest\/xctestexpectation\">XCTestExpectation<\/a> to do it. [&#8230;] At first, I thought that I could use Swift Testing&rsquo;s <a href=\"https:\/\/developer.apple.com\/documentation\/testing\/confirmation(_:expectedcount:isolation:sourcelocation:_:)-5mqz2\"><code>confirmation<\/code><\/a> system to handle this.<\/p>\n<p>[&#8230;]<\/p>\n<p>But this had two problems. The obvious one is the nesting. I couldn&rsquo;t figure out an easy way to avoid it. And in fact, my real code had even more callbacks than this.<\/p>\n<p>The second was about ordering. As far as I can tell, there&rsquo;s no way for me to distinguish here between &ldquo;a-b&rdquo; and &ldquo;b-a&rdquo;.<\/p>\n<p>[&#8230;]<\/p>\n<p>Eventually, someone else suggested I use an <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/asyncstream\"><code>AsyncStream<\/code><\/a> to capture events.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/12\/17\/issues-adopting-swift-testing\/\">Issues Adopting Swift Testing<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Matt Massicotte: The original implementation used XCTestExpectation to do it. [&#8230;] At first, I thought that I could use Swift Testing&rsquo;s confirmation system to handle this. [&#8230;] But this had two problems. The obvious one is the nesting. I couldn&rsquo;t figure out an easy way to avoid it. And in fact, my real code had [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2026-02-24T21:50:41Z","apple_news_api_id":"64c75d79-4cfe-446b-9426-4aea0b1720f6","apple_news_api_modified_at":"2026-02-24T21:50:41Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/AZMddeUz-RGuUJkrqCxcg9g","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[71,2200,901,2796,268],"class_list":["post-51086","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-programming","tag-swift-concurrency","tag-swift-programming-language","tag-swift-testing","tag-testing"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51086","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=51086"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51086\/revisions"}],"predecessor-version":[{"id":51087,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/51086\/revisions\/51087"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=51086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=51086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=51086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}