Power Assert(也称为图解断言)通过提供条件评估过程中产生的值的信息来增强断言失败信息,并以易于理解的形式呈现。 Power Assert是 Spock(以及后来的整个独立于Spock的 Groovy 语言),ScalaTest 和 Expecty 中流行的功能。
Power Assert 为你的测试提供描述性的断言信息,如下面的例子所示:
#assert(numbers[2] == 4)
│ ││ │ │
│ │3 │ 4
│ 2 false
[1, 2, 3, 4, 5]
--- [Int] numbers[2]
+++ [Int] 4
–3
+4
[Int] numbers[2]
=> 3
[Int] 4
=> 4
#assert(numbers.contains(6))
│ │ │
│ false 6
[1, 2, 3, 4, 5]
#assert(string1 == string2)
│ │ │
│ │ "Hello, Swift!"
│ false
"Hello, world!"
--- [String] string1
+++ [String] string2
Hello, {+S+}w[-orld-]{+ift+}!
[String] string1
=> "Hello, world!"
[String] string2
=> "Hello, Swift!"
通过我们的在线 Playground 体验该库的功能! ✨ 点击这里访问交互式演示。
在编写测试时,我们需要使用不同的断言函数。使用 Power Assert,你只需使用 #assert()
函数。 无需记住众多的断言 API。只需创建一个返回布尔值的表达式,Power Assert 将自动显示丰富的错误信息。
要求
要查看 PowerAssert 的实际效果,请转到 Examples 目录并运行 xcodebuild test ...
。
$ cd Examples/XcodeProject/
$ xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=17.0' -parallel-testing-enabled NO
需要参数 -parallel-testing-enabled NO
。 由于 Xcode 最近的更改,并行测试现在默认开启,测试信息不再输出到控制台。 因此,要查看控制台中的断言信息,请禁用并行测试。 启用并行测试后,所有控制台日志都可以从结果包中查看。
或者设置以下 UserDefaults。 此选项允许控制台输出,即使启用了并行测试。
defaults write com.apple.dt.xcodebuild ParallelTestRunnerStdoutMirroringEnabled -bool YES
要查看 PowerAssert 的实际效果,请转到 Examples 目录并运行 swift test
。
$ cd Examples/SwiftPackage/
$ swift test
看到以下结果了吗?
...
Test Suite 'All tests' started at 2023-04-05 07:17:58.800
Test Suite 'swift-power-assert-examplePackageTests.xctest' started at 2023-04-05 07:17:58.801
Test Suite 'PowerAssertTests' started at 2023-04-05 07:17:58.801
Test Case '-[ExampleTests.PowerAssertTests testExample]' started.
/swift-power-assert/Example/"ExampleTests/ExampleTests.swift":8: error: -[ExampleTests.PowerAssertTests testExample] : failed -
#assert(a * b == 91)
│ │ │ │ │
│ │ 9 │ 91
│ 90 false
10
[Int] a
=> 10
[Int] b
=> 9
[Int] a * b
=> 90
[Int] 91
=> 91
/swift-power-assert/Example/"ExampleTests/ExampleTests.swift":11: error: -[ExampleTests.PowerAssertTests testExample] : failed -
#assert(xs.contains(4))
│ │ │
│ false 4
[1, 2, 3]
...
修改 Example/Tests/ExampleTests.swift
中的代码以尝试你喜欢的不同模式。
要在你的库或应用程序中使用 Swift Power Assert,首先将 swift-power-assert 添加到你的项目。
对于 Xcode 项目,将 swift-power-assert 库作为包依赖项添加。
选择 PowerAssert 作为 Package Product,并指定 Test Bundle 作为要添加的目标。
对于 Swift 包,请按如下方式配置 Package.swift
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "MyLibrary",
dependencies: [
...,
.package(
url: "https://github.com/kishikawakatsumi/swift-power-assert.git",
from: "0.12.0"
),
],
targets: [
...,
.testTarget(
name: "MyLibraryTests",
dependencies: [
...,
.product(name: "PowerAssert", package: "swift-power-assert"),
]
),
]
)
接下来,你可以在测试中使用 #assert()
宏来使用 Power Assert。
// MyLibraryTests.swift
import XCTest
import PowerAssert
@testable import MyLibrary
final class MyLibraryTests: XCTestCase {
func testExample() {
let a = 7
let b = 4
let c = 12
#assert(max(a, b) == c)
}
}
Swift Power Assert 库允许你直接使用 async/await
表达式编写断言。 这是演示其对 async/await
无缝支持的示例代码
func testConcurrency() async {
let ok = "OK"
#assert(await upload(content: "example") == ok)
}
对于无人值守的使用(例如,在 CI 上),你可以通过以下方式禁用包验证对话框
-skipMacroValidation
传递给 xcodebuild
或defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES
。问:断言失败消息未显示。
如果你使用 xcodebuild test ...
命令从命令行运行测试,请禁用并行测试。 由于 Xcode 最近的更改,启用并行测试后,详细的测试日志不会输出到控制台。 使用以下选项禁用并行测试
-parallel-testing-enabled NO
或者,设置以下 UserDefaults。 此选项即使启用了并行测试,也能将详细的消息输出到控制台。
defaults write com.apple.dt.xcodebuild ParallelTestRunnerStdoutMirroringEnabled -bool YES
问:即使测试成功(即 #assert()
函数中的表达式的计算结果为 true
),我也想显示结果。
答:默认情况下,如果表达式的计算结果为 true
,则 #assert()
函数不会显示结果,因为测试已成功。 要始终打印结果,请将 verbose
参数设置为 true。
例如
#assert(x == y, verbose: true)
问:我想知道编译器实际上是如何扩展宏的。
答:你可以使用 -dump-macro-expansions
选项来转储宏扩展。
例如
$ cd Examples/SwiftPackage/
$ swift test -Xswiftc -Xfrontend -Xswiftc -dump-macro-expansions
如果你使用 -dump-macro-expansions
选项运行上述命令,你将获得以下输出。
...
@__swiftmacro_12ExampleTests011PowerAssertB0C04testA0yyF6assertfMf_.swift as ()
------------------------------
PowerAssert.Assertion("#assert(a * b == 91)", message: "", file: #""ExampleTests/ExampleTests.swift""#, line: 8, verbose: false, binaryExpressions: [0: "a", 2: "a * b", 3: "91", 1: "b"]) {
$0.capture($0.capture($0.capture(a .self, column: 8, id: 0) * $0.capture(b .self, column: 12, id: 1), column: 10, id: 2) == $0.capture(91, column: 17, id: 3), column: 14, id: 4)
}
.render()
------------------------------
...
开源项目的蓬勃发展离不开像你这样的人的慷慨支持。 如果你觉得这个项目有价值,请考虑扩展你的支持。 贡献项目不仅可以维持其增长,还可以帮助推动创新并改进其功能。
要支持此项目,你可以通过 GitHub Sponsors 成为赞助商。 你的贡献将不胜感激,并将有助于保持项目的活力和发展。 感谢你的考虑! ❤️
该项目在 MIT 许可证 下发布