运行macOS应用XCTest时意外触发系统深色模式问题求助
macOS XCTest 运行时意外切换系统主题至深色模式的解决方案
问题描述
我为macOS应用编写了多组XCTest测试用例,运行最后一个测试时会意外将整个系统主题切换为深色模式,每次都需手动前往系统设置改回,但我并未编写任何切换主题的逻辑。
环境:macOS Sequoia 15.2、Xcode 16.2
测试代码如下:
单元测试代码
import XCTest @testable import TipCalculatorMac final class TipCalculatorAppTests: XCTestCase { func testRemoveRow() { let viewModel = BillViewModel() viewModel.rows = [ BillRow(billAmount: 100, tipPercentage: 10), BillRow(billAmount: 200, tipPercentage: 20), ] let initialCount = viewModel.rows.count viewModel.rows.remove(at: 0) XCTAssertEqual(viewModel.rows.count, initialCount - 1, "Removing a row should decrease the count of rows by 1") } }
UI测试代码
import XCTest final class TipCalculatorMacUITestsLaunchTests: XCTestCase { override class var runsForEachTargetApplicationUIConfiguration: Bool { true } override func setUpWithError() throws { continueAfterFailure = false } @MainActor func testLaunch() throws { let app = XCUIApplication() app.launch() let attachment = XCTAttachment(screenshot: app.screenshot()) attachment.name = "Launch Screen" attachment.lifetime = .keepAlways add(attachment) } }
问题原因
核心原因在于UI测试类中的runsForEachTargetApplicationUIConfiguration = true配置:这个属性会让测试针对应用支持的所有UI配置(包括浅色、深色模式)分别执行一次。测试过程中系统会临时切换全局主题来适配测试场景,但在测试结束后可能没有正确恢复到原有主题。
解决方法
1. 关闭多UI配置自动测试
如果不需要针对不同主题分别测试,直接将该属性改为false即可阻止系统自动切换主题:
override class var runsForEachTargetApplicationUIConfiguration: Bool { false }
2. 强制测试使用指定主题
若需要保留多配置测试,但不想影响系统全局主题,可以在启动应用时通过参数强制指定应用的外观模式,避免系统全局切换:
override func setUpWithError() throws { continueAfterFailure = false let app = XCUIApplication() // 强制设置为浅色模式,如需深色则改为"Dark" app.launchArguments += ["-AppleInterfaceStyle", "Light"] app.launch() }
3. 测试结束后手动恢复系统主题
如果必须依赖系统主题切换完成测试,可以在测试结束后通过AppleScript调用系统设置恢复原有主题:
override func tearDownWithError() throws { // 恢复为浅色模式,需要深色则改为true let script = """ tell application "System Events" tell appearance preferences set dark mode to false end tell end tell """ let task = Process() task.launchPath = "/usr/bin/osascript" task.arguments = ["-e", script] task.launch() task.waitUntilExit() try super.tearDownWithError() }
注意:使用此方法需要给Xcode开启「辅助功能」权限,路径为:系统设置 → 隐私与安全性 → 辅助功能,勾选Xcode。
内容的提问来源于stack exchange,提问作者user185929
相关产品推荐
相关产品推荐

