<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Swift Testing on ThinkPractice: Smart Solutions to Practical Problems</title>
    <link>https://thinkpractice.nl/tags/swift-testing/</link>
    <description>Recent content in Swift Testing on ThinkPractice: Smart Solutions to Practical Problems</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 09 Sep 2025 13:21:13 +0200</lastBuildDate>
    <atom:link href="https://thinkpractice.nl/tags/swift-testing/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Capturing values in Swift Testing in strict concurrency mode</title>
      <link>https://thinkpractice.nl/post/capturing_values_in_swift_testing/</link>
      <pubDate>Tue, 09 Sep 2025 13:21:13 +0200</pubDate>
      <guid>https://thinkpractice.nl/post/capturing_values_in_swift_testing/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently turned on Swift 6.0 mode on of my projects and that means migrating all code to strict concurrency. I had some tests that used mocks to capture values and then using an &lt;code&gt;#expect&lt;/code&gt; macro to&#xA;check whether the captured values were the correct ones. One such test looked like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@Test&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;loginWithNoAccountsAndSuccessfulLoginSavesTokenInCredentialManager&lt;/span&gt;() async &lt;span style=&#34;color:#ff79c6&#34;&gt;throws&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;expectedCredentials&lt;/span&gt; = AccountCredentials(account: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;test@instance.social&amp;#34;&lt;/span&gt;,server: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;instance.social&amp;#34;&lt;/span&gt;, token: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;mynewaccesstoken&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;instanceUrlCalled&lt;/span&gt;: URL?&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;storedCredentials&lt;/span&gt;: AccountCredentials?&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;appModel&lt;/span&gt; = withDependencies {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$0&lt;/span&gt;.defaultDatabase = &lt;span style=&#34;color:#ff79c6&#34;&gt;try&lt;/span&gt;! appDatabase()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$0&lt;/span&gt;.socialMediaClient = MockSocialMediaServer(connectToInstance:  { url &lt;span style=&#34;color:#ff79c6&#34;&gt;in&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            instanceUrlCalled = url&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; expectedCredentials&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$0&lt;/span&gt;.accountCredentialsStorage.storeCredentials = { credentials &lt;span style=&#34;color:#ff79c6&#34;&gt;in&lt;/span&gt; storedCredentials = credentials&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } operation: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        AppModel()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #expect(appModel.destination == &lt;span style=&#34;color:#ff79c6&#34;&gt;nil&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;try&lt;/span&gt; await appModel.login()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;expectedUrl&lt;/span&gt; = URL(string: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;https://instance.social&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#ff79c6&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Issue.record(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Failed to creater URL from string&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #expect(appModel.destination.&lt;span style=&#34;color:#ff79c6&#34;&gt;is&lt;/span&gt;(\.onboardingScreen))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #expect(expectedUrl == instanceUrlCalled)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #expect(expectedCredentials == storedCredentials)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, capturing these variables caused problems in strict concurrency mode. I could lead to potential&#xA;data races and therefore swift 6.0 does not allow it. It took me some time to figure out how to fix this, and it turned out you shouldn&amp;rsquo;t capture any values at all! The fix was as easy as putting the &lt;code&gt;#expect&lt;/code&gt; macros in the closures passed to the mock, like this:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Using GitHub Copilot to rewrite your XCTest tests to use Swift Testing</title>
      <link>https://thinkpractice.nl/post/copilot_1/</link>
      <pubDate>Wed, 18 Jun 2025 11:50:43 +0200</pubDate>
      <guid>https://thinkpractice.nl/post/copilot_1/</guid>
      <description>&lt;p&gt;I love the new &lt;code&gt;Swift Testing&lt;/code&gt; framework and have been using it whenever I can. However, I still have a lot of legacy code that uses &lt;code&gt;XCTest&lt;/code&gt; and I want to convert it to the new framework. This includes a lot of grunt work that I was thinking I hopefully could automate with GitHub Copilot. However, when I tried to do this, I found that Copilot often would create a mingle of &lt;code&gt;XCTest&lt;/code&gt; and &lt;code&gt;Swift Testing&lt;/code&gt; code, or stubbornly stuck to &lt;code&gt;XCTest&lt;/code&gt; even when I asked it to use &lt;code&gt;Swift Testing&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
