Official agent skill

Converting Xctest To Swift Testing

by bitwarden in bitwarden/ios

Convert an XCTest file to Swift Testing framework. An agent skill from bitwarden/ios.

OfficialGPL-3.0Auto-check passedMobile

Install Converting Xctest To Swift Testing

skills CLI
$ npx skills add bitwarden/ios --skill converting-xctest-to-swift-testing -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install bitwarden/ios converting-xctest-to-swift-testing --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/bitwarden/ios.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/converting-xctest-to-swift-testing .claude/skills/converting-xctest-to-swift-testing && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
converting-xctest-to-swift-testing
GitHub stars
699
Token cost
~6k tokens
SKILL.md length
2,382 words
Files
1
Skills in repo
11
Repo updated
First seen
Licence
GPL-3.0

At a glance

Convert an XCTest file to Swift Testing framework. An agent skill from bitwarden/ios.

  • Works in 9 steps: Read the File → Transform the File Header → Convert Properties → …
  • Asked to convert to Swift Testing
  • SKILL.md covers Before You Start — Is This…, Step 1: Read the File, Step 2: Transform the File… and Step 3: Convert Properties, plus 6 more sections
  • Calls swift

What it does

Converting Xctest To Swift Testing is an agent skill from bitwarden/ios, published by the product's own GitHub organization. Convert an XCTest file to Swift Testing framework. Use when asked to "convert to Swift Testing", "migrate XCTest", "convert test file", "xctest to swift testing", "migrate tests to Swift Testing", or when explicitly asked to convert existing XCTest-based tests.

Its SKILL.md is about 6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Mobile, covering iOS development. It works with iOS. The repository describes itself as: Bitwarden mobile apps (Password Manager and Authenticator) for iOS. The licence is GPL-3.0.

When your agent uses it

  • Asked to convert to Swift Testing
  • Convert test file
  • Xctest to swift testing
  • Migrate tests to Swift Testing

Example prompts

  • “convert to Swift Testing”
  • “migrate XCTest”
  • “convert test file”
  • “/converting-xctest-to-swift-testing”

Workflow steps

9 steps, taken from the step headings in SKILL.md.

  1. Read the File
  2. Transform the File Header
  3. Convert Properties
  4. Convert Setup, Teardown, and State Lifecycle
  5. Convert Test Methods
  6. Convert Assertions
  7. Drastically Reduce Boilerplate with Parameterized Tests
  8. Bitwarden-Specific Patterns
  9. Verify

What it can do on your machine

Read from SKILL.md and the folder at commit cd508a5. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • swift

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Converting Xctest To Swift Testing loads about 6k tokens when it runs. Until then it costs about 74 tokens; SKILL.md has 2,382 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~74
When it runs · the whole SKILL.md, loaded when a task matches
~6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from bitwarden/ios at commit cd508a5, republished under its GPL-3.0 licence (© bitwarden). 2,382 words, ~6,028 tokens.

Download SKILL.mdSave it as .claude/skills/converting-xctest-to-swift-testing/SKILL.md (or your agent's skills folder).
name
converting-xctest-to-swift-testing
description
Convert an XCTest file to Swift Testing framework. Use when asked to "convert to Swift Testing", "migrate XCTest", "convert test file", "xctest to swift testing", "migrate tests to Swift Testing", or when explicitly asked to convert existing XCTest-based tests.

Converting XCTest to Swift Testing

Use this skill to convert an existing XCTest file to the Swift Testing framework following Bitwarden iOS patterns.

Before You Start — Is This File Convertible?

Do NOT convert the following; leave them in XCTest:

PatternWhy
ViewInspector testsimports ViewInspector; requires XCTest infrastructure
Snapshot testsFunctions named disabletest_*, uses assertSnapshot or SnapshotTesting; depends on BitwardenTestCase
UI automation testsUses XCUIApplication
Performance testsUses measure { ... } or XCTMetric
Objective-C testsCannot use Swift Testing
Tests asserting on alert displayUses coordinator.alertShown; alert presentation requires UI.animated = false, which BitwardenTestCase.setUp() sets
Tests asserting on loading overlay displayUses coordinator.loadingOverlaysShown; same dependency on UI.animated = false

Stop and flag the issue before proceeding.

Step 1: Read the File

Read the entire test file first. Understand:

  • What type is under test (processor, coordinator, service, etc.)
  • Whether any methods have @MainActor (and which)
  • Whether any tests use addTeardownBlock
  • Any non-mechanical patterns that may need judgment calls

Step 2: Transform the File Header

Imports

Replace import XCTest with import Testing. Keep all other imports unchanged:

swift
// Before:
import XCTest
@testable import BitwardenShared

// After:
import Testing
@testable import BitwardenShared

XCTest implicitly re-exports Foundation, so removing it can cause missing-symbol build errors if the file uses Foundation types directly. If the build fails after conversion, add import Foundation.

Class → Struct
BeforeAfter
class FooTests: BitwardenTestCase {struct FooTests {
final class FooTests: BitwardenTestCase {struct FooTests {
@MainActor placement

If test methods had @MainActor (processor tests, coordinator tests), move it to the struct declaration:

swift
// Before: @MainActor on individual methods
// After:
@MainActor
struct FooProcessorTests {

Service tests typically do not need @MainActor — do NOT add it unless the service dispatches to main.

Step 3: Convert Properties

Change force-unwrapped var properties (those ending in !) to let non-optionals:

swift
// Before:
var coordinator: MockCoordinator<FooRoute, FooEvent>!
var errorReporter: MockErrorReporter!
var subject: FooProcessor!

// After:
let coordinator: MockCoordinator<FooRoute, FooEvent>
let errorReporter: MockErrorReporter
let subject: FooProcessor

services property: Remove it if it is only used inside setUp() to construct the subject — it does not need to be a stored property in Swift Testing. Keep it as let services: MockServiceContainer if test methods reference it directly for assertions.

Step 4: Convert Setup, Teardown, and State Lifecycle

Swift Testing replaces setUpWithError and tearDownWithError with a more natural, type-safe lifecycle using init() and deinit.

The Core Concept: A fresh, new instance of the test suite (struct or class) is created for each test function it contains. This is the cornerstone of test isolation, guaranteeing that state from one test cannot leak into another.

MethodReplaces...Behavior
init()setUpWithError()The initializer for your suite. Put all setup code here. It can be async and throws.
deinittearDownWithError()The deinitializer. Put cleanup code here. It runs automatically after each test. Note: deinit is only available on class or actor suite types, not structs. This is a common reason to choose a class for your suite.
setUp() → init()

Move all setup code into init(), removing the super.setUp() call:

swift
// Before:
override func setUp() {
    super.setUp()

    coordinator = MockCoordinator()
    errorReporter = MockErrorReporter()
    subject = FooProcessor(
        coordinator: coordinator.asAnyCoordinator(),
        services: ServiceContainer.withMocks(errorReporter: errorReporter),
        state: FooState(),
    )
}

// After:
init() {
    coordinator = MockCoordinator()
    errorReporter = MockErrorReporter()
    subject = FooProcessor(
        coordinator: coordinator.asAnyCoordinator(),
        services: ServiceContainer.withMocks(errorReporter: errorReporter),
        state: FooState(),
    )
}
tearDown() → delete

Remove the entire tearDown() override. Swift Testing creates a fresh struct instance for every test — all properties are discarded automatically. No nilling out is needed.

addTeardownBlock { ... }
  • If the block just nils out properties: delete it (struct isolation handles this).
  • If the block cleans up external resources (e.g., temp files, keychain entries): convert to deinit and change the struct to a class. deinit is not available on struct.
Action Items
  • Convert test classes from XCTestCase to structs (preferred for automatic state isolation) or final classes.
  • Move setUp logic into the suite's init().
  • Move tearDown logic into the suite's deinit (and use a class or actor if needed).
  • Define the SUT and its dependencies as let properties, initialized in init().

Step 5: Convert Test Methods

Rename and annotate

Remove the test_ prefix. Add @Test attribute. Remove @MainActor from individual methods (it's now on the struct):

swift
// Before:
@MainActor
func test_receive_valueChanged_updatesState() { ... }

// After:
@Test
func receive_valueChanged_updatesState() { ... }

async throws signatures are unchanged:

swift
// Before:
@MainActor
func test_perform_appeared_loadsData() async throws { ... }

// After:
@Test
func perform_appeared_loadsData() async throws { ... }
Add DocC comments

Every @Test function must have a /// doc comment. The comment must start with the backtick-wrapped symbol name of the function under test (including parameter labels), followed by a plain-English description of the behaviour being verified:

swift
/// `receive(_:)` updates the state when the value changes.
@Test
func receive_valueChanged_updatesState() { ... }

/// `perform(_:)` loads data when the view appears.
@Test
func perform_appeared_loadsData() async throws { ... }

For parameterized tests the same rule applies — the symbol name comes first:

swift
/// `parseCard(lines:)` extracts card numbers across space-separated, dash-separated, and multi-segment formats.
@Test(arguments: zip(inputs, expectedNumbers))
func parseCard_extractsCardNumber(lines: [String], expectedNumber: String) { ... }

Step 6: Convert Assertions

Replace the entire XCTAssert family with two powerful, expressive macros. They accept regular Swift expressions, eliminating the need for dozens of specialized XCTAssert functions.

MacroUse Case & Behavior
#expect(expression)Soft Check. Use for most validations. If the expression is false, the issue is recorded, but the test function continues executing. This allows you to find multiple failures in a single run.
#require(expression)Hard Check. Use for critical preconditions (e.g., unwrapping an optional). If the expression is false or throws, the test is immediately aborted. This prevents cascading failures from an invalid state.
Power Move: Visual Failure Diagnostics

Unlike XCTAssert, which often only reports that a comparison failed, #expect shows you the exact values that caused the failure, directly in the IDE and logs. This visual feedback is a massive productivity boost.

Code:

swift
@Test("User count meets minimum requirement")
func userCount_minimum() {
    let userCount = 5
    // This check will fail
    #expect(userCount > 10)
}

Failure Output in Xcode:

▽ Expected expression to be true
#expect(userCount > 10)
      |         | |
      5         | 10
                false
Power Move: Optional-Safe Unwrapping

#require is the new, safer replacement for XCTUnwrap. It not only checks for nil but also unwraps the value for subsequent use.

Before: The XCTest Way

swift
// In an XCTestCase subclass...
func testFetchUser_succeeds_XCTest() async throws {
    let user = try XCTUnwrap(await fetchUser(id: "123"), "Fetching user should not return nil")
    XCTAssertEqual(user.id, "123")
}

After: The Swift Testing Way

swift
@Test("Fetching a valid user succeeds")
func fetchUser_succeeds() async throws {
    // #require both checks for nil and unwraps `user` in one step.
    // If fetchUser returns nil, the test stops here and fails.
    let user = try #require(await fetchUser(id: "123"))

    // `user` is now a non-optional User, ready for further assertions.
    #expect(user.id == "123")
    #expect(user.age == 37)
}
Common Assertion Conversions Quick Reference

Use this table as a cheat sheet when migrating your XCTest assertions.

XCTest AssertionSwift Testing EquivalentNotes
XCTAssert(expr)#expect(expr)Direct replacement for a boolean expression.
XCTAssertEqual(a, b)#expect(a == b)Use the standard == operator.
XCTAssertNotEqual(a, b)#expect(a != b)Use the standard != operator.
XCTAssertNil(a)#expect(a == nil)Direct comparison to nil.
XCTAssertNotNil(a)#expect(a != nil)Direct comparison to nil.
XCTAssertTrue(a)#expect(a)No change needed if a is already a Bool.
XCTAssertFalse(a)#expect(!a)Use the ! operator to negate the expression.
XCTAssertGreaterThan(a, b)#expect(a > b)Use any standard comparison operator: >, <, >=, <=
try XCTUnwrap(a)try #require(a)The preferred, safer way to unwrap optionals.
try XCTUnwrap(a, "msg")try #require(a)drop the message, the macro output is self-explanatory.
Basic XCTAssertThrowsError(expr)#expect(throws: (any Error).self) { try expr }The basic form for checking any error.
Typed XCTAssertThrowsError(expr)#expect(throws: BitwardenTestError.self)Ensures an error of a specific type is thrown.
Specific Error XCTAssertThrowsError(expr)#expect(throws: BitwardenTestError.example)Validates a specific error value is thrown. Error type must conform to Equatable.
XCTAssertNoThrow(try expr)#expect(throws: Never.self) { try expr }The explicit way to assert that no error is thrown.
assertAsyncThrows(error: e) { try await expr }await #expect(throws: e) { try await expr }Bitwarden-specific helper; note that await moves to the front of #expect for async closures.
XCTFail("message")Issue.record("message")Direct replacement for unconditional test failure.
Action Items
  • Run grep -R "XCTAssert\|XCTUnwrap" . to find all legacy assertions.
  • Convert try XCTUnwrap() calls to try #require(). This is a direct and superior replacement.
  • Convert most XCTAssert...() calls to #expect(). Use #require() only for preconditions where continuing the test makes no sense.
  • Group related checks logically within a test. Since #expect continues on failure, you can naturally check multiple properties of an object in a single test.

Step 7: Drastically Reduce Boilerplate with Parameterized Tests

Run a single test function with multiple argument sets to maximize coverage with minimal code. This is superior to a for-in loop because each argument set runs as an independent test, can be run in parallel, and failures are reported individually.

PatternHow to Use It & When
Single Collection@Test(arguments: [0, 100, -40]) <br> The simplest form. Pass a collection of inputs.
Zipped Collections@Test(arguments: zip(inputs, expectedOutputs)) <br> The most common and powerful pattern. Use zip to pair inputs and expected outputs, ensuring a one-to-one correspondence.
Multiple Collections@Test(arguments: ["USD", "EUR"], [1, 10, 100]) <br> ⚠️ Caution: Cartesian Product. This creates a test case for every possible combination of arguments. Use it deliberately when you need to test all combinations.
Example: Migrating Repetitive Tests to a Parameterized One

Before: The XCTest Way

swift
func test_flavorVanilla_containsNoNuts() {
    let flavor = Flavor.vanilla
    XCTAssertFalse(flavor.containsNuts)
}
func test_flavorPistachio_containsNuts() {
    let flavor = Flavor.pistachio
    XCTAssertTrue(flavor.containsNuts)
}
func test_flavorChocolate_containsNoNuts() {
    let flavor = Flavor.chocolate
    XCTAssertFalse(flavor.containsNuts)
}

After: The Swift Testing Way using zip

swift
@Test("Flavor nut content is correct", arguments: zip(
    [Flavor.vanilla, .pistachio, .chocolate],
    [false, true, false]
))
func flavor_containsNuts(flavor: Flavor, expected: Bool) {
    #expect(flavor.containsNuts == expected)
}
Action Items
  • Combine multiple tests with matching boilerplate into a single parameterized test

Step 8: Bitwarden-Specific Patterns

Unchanged patterns

These work identically in both frameworks — do not modify them:

  • coordinator.asAnyCoordinator()
  • ServiceContainer.withMocks(...)
  • BitwardenTestError.example / .mock("desc")
  • coordinator.alertShown, coordinator.routes
  • errorReporter.errors
Cast assertions
swift
// Before:
XCTAssertEqual(errorReporter.errors.last as? BitwardenTestError, .example)

// After:
#expect(errorReporter.errors.last as? BitwardenTestError == .example)
coordinator.alertShown nil check
swift
// Before:
XCTAssertNotNil(coordinator.alertShown.last)

// After:
#expect(coordinator.alertShown.last != nil)
Optional unwrap then assert
swift
// Before:
let action = try XCTUnwrap(stackNavigator.actions.last)
XCTAssertEqual(action.type, .pushed)

// After:
let action = try #require(stackNavigator.actions.last)
#expect(action.type == .pushed)

Step 9: Verify

Run these checks after conversion:

  1. No XCTest remnants: grep for XCTAssert, setUp, tearDown, XCTestCase, import XCTest — all should be gone.
  2. All tests annotated: every former test_ function has @Test.
  3. No forced optionals: no force-unwrapped var properties remain.
  4. Build passes: run mint run swiftformat . and build the target.
  5. Tests pass: run the converted test file.

Reference Material

This is additional information about Swift Testing that doesn't neatly fit into steps above.

Conditional Execution & Skipping

Dynamically control which tests run based on feature flags, environment, or known issues.

TraitWhat It Does & How to Use It
.disabled("Reason")Unconditionally skips a test. The test is not run, but it is still compiled. Always provide a descriptive reason for CI visibility (e.g., "Flaky on CI, see FB12345").
.enabled(if: condition)Conditionally runs a test. The test only runs if the boolean condition is true. This is perfect for tests tied to feature flags or specific environments. <br> swift @Test(.enabled(if: FeatureFlags.isNewAPIEnabled)) func newAPI() { /* ... */ }
@available(...)OS Version-Specific Tests. Apply this attribute directly to the test function. It's better than a runtime #available check because it allows the test runner to know the test is skipped for platform reasons, which is cleaner in test reports.
Show full SKILL.md (897 more words)Show less
Writing Assertions with Standard Swift

Swift Testing's philosophy is to use plain Swift expressions for assertions. For more complex checks like unordered collections or floating-point numbers, use the power of the Swift standard library.

Assertion TypeHow to Write It
Comparing Collections (Unordered)A simple == check on arrays fails if elements are the same but the order is different. To check for equality while ignoring order, convert both collections to a Set. <br><br> Brittle: #expect(tags == ["ios", "swift"]) // Fails if tags are ["swift", "ios"] <br> Robust: #expect(Set(tags) == Set(["swift", "ios"])) // Passes
Floating-Point AccuracyFloating-point math is imprecise. #expect(0.1 + 0.2 == 0.3) will fail. To ensure tests are robust, check that the absolute difference between the values is within an acceptable tolerance. <br><br> Fails: #expect(result == 0.3) <br> Passes: #expect(abs(result - 0.3) < 0.0001)
Structure and Organization at Scale

Use suites and tags to manage large and complex test bases.

Suites and Nested Suites

A @Suite groups related tests and can be nested for a clear hierarchy. Traits applied to a suite are inherited by all tests and nested suites within it.

Tags for Cross-Cutting Concerns

Tags associate tests with common characteristics (e.g., .network, .ui, .regression) regardless of their suite. This is invaluable for filtering.

  1. Define Tags in a Central File:
    swift
    // /Tests/Support/TestTags.swift
    import Testing
    
    extension Tag {
        @Tag static var fast: Self
        @Tag static var regression: Self
        @Tag static var flaky: Self
        @Tag static var networking: Self
    }
  2. Apply Tags & Filter:
    swift
    // Apply to a test or suite
    @Test("Username validation", .tags(.fast, .regression))
    func username_validation() { /* ... */ }
    
    // Run from CLI
    // swift test --filter .fast
    // swift test --skip .flaky
    // swift test --filter .networking --filter .regression
    
    // Filter in Xcode Test Plan
    // Add "fast" to the "Include Tags" field or "flaky" to the "Exclude Tags" field.
Power Move: Xcode UI Integration for Tags

Xcode deeply integrates with tags, turning them into a powerful organizational tool.

  • Grouping by Tag in Test Navigator: In the Test Navigator (Cmd-6), click the tag icon at the top. This switches the view from the file hierarchy to one where tests are grouped by their tags. It's a fantastic way to visualize and run all tests related to a specific feature.
  • Test Report Insights: After a test run, the Test Report can automatically find patterns. Go to the Insights tab to see messages like "All 7 tests with the 'networking' tag failed." This immediately points you to systemic issues, saving significant debugging time.
Concurrency and Asynchronous Testing
Async/Await and Confirmations
  • Async Tests: Simply mark your test function async and use await.
  • Confirmations: To test APIs with completion handlers or that fire multiple times (like delegates or notifications), use the confirmation global function. It wraps the entire asynchronous operation and implicitly waits.
swift
@Test("Delegate is notified 3 times")
func delegate_notifications() async {
    // The test operation is wrapped in an `await confirmation` call.
    // It will automatically wait or fail if the count isn't met in time.
    await confirmation("delegate.didUpdate was called", expectedCount: 3) { confirm in
        // `confirm` is a function passed to your closure. Call it when the event happens.
        let delegate = MockDelegate {
            confirm() // Call the confirmation
        }
        let sut = SystemUnderTest(delegate: delegate)

        // The action that triggers the events happens *inside* the closure.
        sut.performActionThatNotifiesThreeTimes()
    }
}
Advanced Asynchronous Patterns
Asserting an Event Never Happens

Use a confirmation with expectedCount: 0 to verify that a callback or delegate method is never called during an operation. If confirm() is called, the test will fail.

swift
@Test("Logging out does not trigger a data sync")
func logout_doesNotSync() async {
    await confirmation("data sync was triggered", expectedCount: 0) { confirm in
        let mockSyncEngine = MockSyncEngine {
            // If this is ever called, the test will automatically fail.
            confirm()
        }
        let sut = AccountManager(syncEngine: mockSyncEngine)
    
        sut.logout()
    }
}
Bridging Legacy Completion Handlers

For older asynchronous code that uses completion handlers, use withCheckedThrowingContinuation to wrap it in a modern async/await call that Swift Testing can work with.

swift
func legacyFetch(completion: @escaping (Result<Data, Error>) -> Void) {
    // ... legacy async code ...
}

@Test func legacyFetch() async throws {
    let data = try await withCheckedThrowingContinuation { continuation in
        legacyFetch { result in
            continuation.resume(with: result)
        }
    }
    #expect(!data.isEmpty)
}
Controlling Parallelism
  • .serialized: Apply this trait to a @Test or @Suite to force its contents to run serially (one at a time). Use this as a temporary measure for legacy tests that are not thread-safe or have hidden state dependencies. The goal should be to refactor them to run in parallel.
  • .timeLimit: A safety net to prevent hung tests from stalling CI. The more restrictive (shorter) duration wins when applied at both the suite and test level.
Advanced API Cookbook
FeatureWhat it Does & How to Use It
withKnownIssueMarks a test as an Expected Failure. It's better than .disabled for known bugs. The test still runs but won't fail the suite. Crucially, if the underlying bug gets fixed and the test passes, withKnownIssue will fail, alerting you to remove it.
CustomTestStringConvertibleProvides custom, readable descriptions for your types in test failure logs. Conform your key models to this protocol to make debugging much easier.
.bug(id: "JIRA-123") TraitAssociates a test directly with a ticket in your issue tracker. This adds invaluable context to test reports in Xcode and Xcode Cloud.
Test.currentA static property (Test.current) that gives you runtime access to the current test's metadata, such as its name, tags, and source location. Useful for advanced custom logging.
Multiple #expect CallsUnlike XCTest where a failure might stop a test, #expect allows execution to continue. You can place multiple #expect calls in a single test to validate different properties of an object, and all failures will be reported together. There is no need for a special grouping macro.

Appendix: Evergreen Testing Principles (The F.I.R.S.T. Principles)

These foundational principles are framework-agnostic, and Swift Testing is designed to make adhering to them easier than ever.

PrincipleMeaningSwift Testing Application
FastTests must execute in milliseconds.Lean on default parallelism. Use .serialized sparingly.
IsolatedTests must not depend on each other.Swift Testing enforces this by creating a new suite instance for every test. Random execution order helps surface violations.
RepeatableA test must produce the same result every time.Control all inputs (dates, network responses) with mocks/stubs. Reset state in init/deinit.
Self-ValidatingThe test must automatically report pass or fail.Use #expect and #require. Never rely on print() for validation.
TimelyWrite tests alongside the production code.Use parameterized tests (@Test(arguments:)) to easily cover edge cases as you write code.

© bitwarden, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/converting-xctest-to-swift-testing of bitwarden/ios.

Open the folder on GitHubat commit cd508a5

Compare with similar skills

Converting Xctest To Swift Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Converting Xctest To Swift Testing compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Converting Xctest To Swift Testing this skillbitwarden/ios699—~6kAutomated safety check: PassGPL-3.0
Hig Project Contextraintree-technology/hig-doctor1435 repos~1.2kAutomated safety check: PassMIT
Hig Components Contentraintree-technology/hig-doctor1435 repos~1.3kAutomated safety check: PassMIT
iOS Simulator Skilln0an/VivaDicta1301 repos~2.5kAutomated safety check: PassMIT
Inspector Implementationipedro/Inspector170—~729Automated safety check: PassMIT
Device InteractionInfomaniak/desktop-kDrive1201 repos~1.9kAutomated safety check: PassGPL-3.0

Similar skills

  • Hig Project Context

    raintree-technology/hig-doctor

    Create or update a shared Apple design context document that other HIG skills use to tailor guidance.

    143 GitHub starsUsed in 5 repos~1.2k tokens
    MobileAuto-check passed
  • Hig Components Content

    raintree-technology/hig-doctor

    Apple Human Interface Guidelines for content display components.

    143 GitHub starsUsed in 5 repos~1.3k tokens
    MobileAuto-check passed
  • iOS Simulator Skill

    n0an/VivaDicta

    21 production-ready scripts for iOS app testing, building, and automation.

    130 GitHub starsUsed in 1 repo~2.5k tokens
    MobileAuto-check passed
  • Inspector Implementation

    ipedro/Inspector

    A skill your agent uses when an agent needs to implement or modify the Inspector library itself — panel UI, hierarchy/runtime behavior, custom property models, macros, or Example-app dogfooding.

    170 GitHub stars~729 tokensUpdated 5 mo ago
    MobileAuto-check passed
  • Device Interaction

    Infomaniak/desktop-kDrive

    Verify iOS app behavior on device or simulator via screenshots, UI hierarchy, and touch interactions.

    120 GitHub starsUsed in 1 repo~1.9k tokens
    MobileAuto-check passed
  • Run iOS Simulator

    iPlug2/iPlug2OOS

    Build and run an iPlug2 iOS app in the iOS Simulator. An agent skill from iPlug2/iPlug2OOS.

    158 GitHub stars~711 tokensUpdated 25 days ago
    MobileAuto-check passed

More from bitwarden/ios

All 11 skills in this repo
  • Testing iOS Code

    bitwarden/ios

    Official

    Write tests, add test coverage, unit test, or add missing tests for Bitwarden iOS.

    699 GitHub stars~1.8k tokensUpdated today
    Auto-check passed
  • Official

    Build the Bitwarden iOS app, capture all compiler and lint warnings, categorize them into Swift 6 concurrency vs actionable, and interactively fix the actionable ones.

    699 GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Build Test Verify

    bitwarden/ios

    Official

    Build the project, run tests, lint, format, spell check, generate mocks, or verify the build passes for Bitwarden iOS.

    699 GitHub stars~1.3k tokensUpdated today
    Auto-check passed
  • Official

    Convert a hand-written bespoke mock to a Sourcery AutoMockable-generated mock.

    699 GitHub stars~3.5k tokensUpdated today
    Auto-check passed
  • Official

    Evaluates a bitwarden/ios "Update SDK to" PR against the sdk-swift commit range for compile-time, runtime and serialization breaking changes, maps affected symbols to iOS call sites, and applies…

    699 GitHub stars~2.6k tokensUpdated today
    Auto-check passed
  • Fixing Flaky Tests

    bitwarden/ios

    Official

    Diagnose and fix flaky (intermittently failing) tests in Bitwarden iOS.

    699 GitHub stars~2.3k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Converting Xctest To Swift Testing

What does Converting Xctest To Swift Testing do?

Convert an XCTest file to Swift Testing framework. An agent skill from bitwarden/ios. Converting Xctest To Swift Testing is an agent skill from bitwarden/ios, published by the product's own GitHub organization. Convert an XCTest file to Swift Testing framework.

When should I use Converting Xctest To Swift Testing?

Converting Xctest To Swift Testing fits situations like: asked to convert to Swift Testing; convert test file; xctest to swift testing; migrate tests to Swift Testing.

How do I install Converting Xctest To Swift Testing in Claude Code?

Run `npx skills add bitwarden/ios --skill converting-xctest-to-swift-testing -a claude-code`. Or copy the skill folder (.claude/skills/converting-xctest-to-swift-testing in bitwarden/ios) into .claude/skills/converting-xctest-to-swift-testing in your project. Claude Code loads it when a task matches its description.

How do I install Converting Xctest To Swift Testing in Codex?

Run `npx skills add bitwarden/ios --skill converting-xctest-to-swift-testing -a codex`. Or copy the skill folder (.claude/skills/converting-xctest-to-swift-testing in bitwarden/ios) into .agents/skills/converting-xctest-to-swift-testing in your project. Codex loads it when a task matches its description.

Can I use Converting Xctest To Swift Testing in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add bitwarden/ios --skill converting-xctest-to-swift-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/converting-xctest-to-swift-testing, .gemini/skills/converting-xctest-to-swift-testing, .github/skills/converting-xctest-to-swift-testing and .opencode/skills/converting-xctest-to-swift-testing in your project.

What does Converting Xctest To Swift Testing need to run?

Going by SKILL.md and its folder, Converting Xctest To Swift Testing needs the command-line tools its instructions call (swift).

Does Converting Xctest To Swift Testing access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Converting Xctest To Swift Testing safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Converting Xctest To Swift Testing use?

Converting Xctest To Swift Testing is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Converting Xctest To Swift Testing use?

About 6k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Converting Xctest To Swift Testing?

Skills that share tags, products or a category with Converting Xctest To Swift Testing: Hig Project Context (raintree-technology/hig-doctor, 143 stars), Hig Components Content (raintree-technology/hig-doctor, 143 stars), iOS Simulator Skill (n0an/VivaDicta, 130 stars) and Inspector Implementation (ipedro/Inspector, 170 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Converting Xctest To Swift Testing?

bitwarden (a GitHub organization, an official publisher) maintains it in bitwarden/ios, which has 699 GitHub stars. The repository holds 11 skills in this directory. The repository was last updated on October 9, 2026.

Source: bitwarden/ios on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.