Using GitHub Copilot to rewrite your XCTest tests to use Swift Testing

I love the new Swift Testing framework and have been using it whenever I can. However, I still have a lot of legacy code that uses XCTest 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 XCTest and Swift Testing code, or stubbornly stuck to XCTest even when I asked it to use Swift Testing.

This of course is related to training data the Claude Sonnet 3.5 model I use with Copilot. The Claude Sonnet 3.5 model is dated 18th of June 2025. This is after Swift Testing was introduced, but the fact remains that a lot more swift code still uses XCTest. So naturally, it has a bias towards that.

So how to force Copilot to use Swift Testing instead of XCTest? I found that the best way is to use a set of custom instructions for Copilot to do that. Create a new folder in the root of your project called .github. Inside that folder put a file called copilot-instructions.md. In that file, you can add the custom prompts for all of your languages. I added the following for Swift:

-   When creating or refactoring unit tests use the new Swift Testing framework instead of XCTest
-   To import the Swift Testing framework use `import Testing`
-   A test suite is represented by a struct instead of a class
-   All test methods should be annotated with the @Test macro
-   A test suite is annotated with the @Suite macro, add a newline after the @Suite macro
-   Change XCTAssertEqual(expectedCondition, testCondition) to #expect(expectedCondition == testCondition)
-   Change XCTAssertNotEqual(expectedCondition, testCondition) to #expect(expectedCondition != testCondition)
-   Change XCTAssertNotNil(expression) to #require(expression)
-   Instead of using XCTFail use Issue.record with a return statement.
-   When a selection is present, only refactor the selected function do not refactor the other functions.
-   Keep the code as close to the original as possible, do not change the structure of the code.
-   Change all XCTAssertEqual using a tolerance to #expect(abs(expectedCondition - testCondition) < tolerance)
-   Change all XCTAssertEqual using an accuracy to #expect(abs(expectedCondition - testCondition) < accuracy)

To check whether Copilot is using the Custom Instructions or not, you can use the Copilot Chat window. If you ask it to refactor a test case, it will show you when it is using the Custom Instructions. It shows the references used to generate the code. If it is using the Custom Instructions, it will show the file copilot-instructions.md as a reference, just like this:

Making sure copilot is using your custom instructions

Making sure copilot is using your custom instructions

After that, Copilot generated much more accurate code that used the Swift Testing framework instead of XCTest. Of course, sometimes it is still stubborn and uses XCTest anyway, but it is much less frequent.

The nice thing is that this also works for other concepts than unit tests. For example, you can add prompts to generate code in a specific style, or to use a specific framework. You can also use it to generate documentation or comments in a specific style. And more importantly, this is also not limited to Swift, you can use it for any language that Copilot supports. For more information on how to use Custom Instructions, check out the GitHub Copilot documentation.