惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
A
Arctic Wolf
Scott Helme
Scott Helme
S
Securelist
Schneier on Security
Schneier on Security
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
Security Latest
Security Latest
Project Zero
Project Zero
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
Check Point Blog
F
Full Disclosure
Stack Overflow Blog
Stack Overflow Blog
H
Hacker News: Front Page
T
The Blog of Author Tim Ferriss
TaoSecurity Blog
TaoSecurity Blog
Vercel News
Vercel News
A
About on SuperTechFans
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security Affairs
Y
Y Combinator Blog
T
The Exploit Database - CXSecurity.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Forbes - Security
Forbes - Security
IT之家
IT之家
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
The Register - Security
The Register - Security
Jina AI
Jina AI
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
K
Kaspersky official blog
Hacker News: Ask HN
Hacker News: Ask HN
C
Cisco Blogs
MyScale Blog
MyScale Blog
博客园 - 【当耐特】
T
Threat Research - Cisco Blogs
D
Docker
G
GRAHAM CLULEY

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
WWDC 2026 - Migrate to Swift Testing: What Actually Means for Your Test Suite
ArshTechPro · 2026-06-16 · via DEV Community

Swift Testing shipped with Xcode 16 back in 2024.

Swift Testing was built from the ground up for Swift. That means Swift concurrency is a first-class citizen, test cases run in parallel by default, and the API surface is dramatically smaller than XCTest's forty-plus assertion functions. One macro, #expect, replaces most of them.

If you are still on XCTest, you have probably felt the friction: class inheritance for every test suite, function names that must start with test, assertion messages that tell you what the values were but not where the expression came from. Swift Testing fixes all of this.

That said, you do not need to migrate everything at once, and WWDC 2026 is emphatic about this.


The Migration Strategy: Small Chunks, No Big Bang

The session opens with something refreshing: permission to be slow about this.

The recommended approach is to leave your existing XCTests where they are and start using Swift Testing only for new tests. Both frameworks can coexist in the same target and even the same file. You do not need a separate test target, and you do not need a migration sprint.

The one rule: Swift Testing tests cannot live inside XCTestCase subclasses. Everything else is fair game.


Raw Identifiers for Readable Test Names

One small quality-of-life improvement worth knowing about from the start: Swift supports raw identifiers using backticks, and Swift Testing takes full advantage of this.

import Testing

@testable import DemoApp

@Test func `Default climate: tropical`() async throws {
    let fruit = Fruit(name: "Coconut")
    #expect(fruit.climate == .tropical)
}

No more testDefaultClimateTropical or dealing with camelCase names in test output. The test name is the test name.


Interoperability: The Key to Reusing Your Helper Code

This is the main new story in WWDC 2026 and the feature that makes incremental migration actually work.

The problem: you have test helper functions that wrap XCTFail. You want to call them from new Swift Testing tests. Previously, this was messy. Now, it works by design.

Interoperability is a feature that lets you safely call API from one test framework inside a test written in the other. So a Swift Testing test can call a helper that internally uses XCTFail, and XCTest tests can use Swift Testing's Issue.record and expectation macros.

Three Interoperability Modes

The session introduces three modes, and understanding them is important for knowing what level of strictness you want:

Limited mode -- Cross-framework issues from XCTest become warnings, not errors. Tests still pass. This is the default for test plans created before Xcode 27.

Complete mode -- Those same warnings become errors. The test will fail. This is the default for new projects in Xcode 27.

Strict mode -- Cross-framework issues from XCTest cause a fatal error and stop the test immediately at the point of the bad call. This is useful when you want to systematically find every place you need to replace XCTest API.

You can change modes in your Test Plan settings under "Test Execution," or for Swift Package projects using an environment variable:

SWIFT_TESTING_XCTEST_INTEROP_MODE=strict swift test

For SPM projects, complete mode requires bumping to swift-tools-version: 6.4 or newer.

Migrating a Helper Function

Here is a typical helper before migration:

func assertUnique(_ fruits: [Fruit], file: StaticString = #filePath, line: UInt = #line) {
    var uniqueNames = Set<String>()
    for name in fruits.map(\.name) {
        if !uniqueNames.insert(name).inserted {
            XCTFail("Duplicate name: \(name)", file: file, line: line)
        }
    }
}

After migrating to Swift Testing:

import Testing

func assertUnique(_ fruits: [Fruit], sourceLocation: SourceLocation = #sourceLocation) {
    var uniqueNames = Set<String>()
    for name in fruits.map(\.name) {
        if !uniqueNames.insert(name).inserted {
            Issue.record("Duplicate name: \(name)", sourceLocation: sourceLocation)
        }
    }
}

XCTFail becomes Issue.record. The file and line parameters become a single SourceLocation parameter. The helper can now be called cleanly from both Swift Testing tests and existing XCTests.


Common Migration Patterns

The session walks through two patterns that come up in almost every migration.

Skipping Tests

XCTest uses XCTSkipIf. In Swift Testing, the direct replacement is Test.cancel, but the preferred approach is a trait:

let isFall = false

// XCTest
func testSwallowFallMigration() async throws {
    try XCTSkipIf(!isFall, "Wrong season for migration")
}

// Swift Testing via Test.cancel (works but not ideal)
func testSwallowFallMigration() async throws {
    if !isFall {
        try Test.cancel("Wrong season for migration")
    }
}

// Preferred: use a trait
@Test(.enabled(if: isFall, "Wrong season for migration"))
func `Swallow fall migration`() async throws {
    // ...
}

Moving the condition into a trait keeps the test body clean and makes the enablement logic visible at a glance.

Halting After Failures

In XCTest, you set continueAfterFailure = false to stop on the first failure. In Swift Testing, you use #require instead of #expect for the assertions where failure should halt the test:

func testExample() async throws {
    #expect(Fruit.banana.climate == .temperate)

    // If this fails, the test stops here
    try #require(Fruit.banana == Fruit.plantain)

    // This line is only reached if #require passed
}

The benefit over XCTest's approach: you get fine-grained control over which expectations are fatal and which are not, rather than a single global flag.


What You Unlock After Migrating

The second half of the session is about capabilities that simply do not exist in XCTest.

Parameterized Tests

This is one of the most impactful changes for test suites that have grown unwieldy with repetitive test methods.

Before, you might write a nested loop inside a single test:

@Test func `Birds flap wings successfully`() async throws {
    for bird in Aviary.birds {
        for count in (40...100) {
            try await bird.flapWings(count: count)
        }
    }
}

The problem: when it fails, you do not know which bird or which count triggered the failure. The whole loop is one test case.

After converting to a parameterized test:

@Test(arguments: Aviary.birds, 40...100)
func `Birds flap wings successfully`(bird: Bird, count: Int) async throws {
    try await bird.flapWings(count: count)
}

Swift Testing generates a separate test case for every combination of bird and count. All cases run in parallel. When something fails, the Test navigator shows you exactly which inputs caused the failure. In the session's demo, the refactored test also finished significantly faster because of parallel execution.

Exit Tests

Exit tests let you write coverage for code that is expected to crash -- preconditionFailure, fatalError, and similar calls that have historically been impossible to test without crashing your entire test process.

Given this code in a Bird initializer:

if name.isEmpty {
    preconditionFailure("Bird name cannot be empty")
}

You can now write:

@Test func `Bird with empty name crashes`() async throws {
    await #expect(processExitsWith: .failure) {
        _ = Bird(name: "")
    }
}

Swift Testing runs the body of the exit test in a child process. If that process exits with the expected condition, the test passes. The crash is isolated, so it cannot affect any other test. Exit tests are supported on macOS, Linux, FreeBSD, and Windows.

This finally gives you a way to get code coverage on defensive guards that were previously invisible to your test suite.


What Stays in XCTest

The session is clear about what not to migrate:

  • UI automation tests using XCUIApplication
  • Performance tests using XCTMetric
  • Tests that catch Objective-C exceptions (only Objective-C code can handle these safely)

For everything else, Swift Testing is the better home.


Xcode's Migration Assistance

One practical note from the session: Xcode 27's Coding Assistant is aware of the migration documentation and can help formulate a strategy, review your work, and automate parts of the migration. If you are staring at a large test suite and not sure where to start, that is worth exploring.


The Summary

The path forward is clear and low-risk:

  1. Keep your existing XCTests where they are. Do not touch them until you are ready.
  2. Write all new tests using Swift Testing.
  3. Enable interoperability and start with limited mode. Gradually move to complete or strict as you migrate individual helpers.
  4. When you update a helper, replace XCTFail with Issue.record and update the source location parameter.
  5. Look for nested loops in your tests -- those are candidates for parameterized tests.
  6. Add exit tests anywhere you have preconditionFailure or fatalError with no coverage.

The migration is not a one-time event. It is a gradual shift that Xcode 27 is explicitly designed to support.