我目前正在开发一个项目,试图确定不同的排序算法对不同大小的数组进行排序所需的时间。为了测量时间,我决定在 Swift Playgrounds 中使用 XCTest,因为它可以自动执行多次运行算法并求平均值的过程。但我对这种方法有一个问题,因为我必须以 5 个元素间隔(即 15 个元素、20 个元素、25 个元素...)测试从 15 个元素到 1500 个左右的各种数组大小。
我能够通过一次测试做到这一点的唯一方法是具有不同大小的多个函数并测量性能。这是一个示例:
class insertionSortPerformanceTest: XCTestCase {
func testMeasure10() {
measure {
_ = insertionSort(arrLen: 10)
}
}
func testMeasure15() {
measure {
_ = insertionSort(arrLen: 15)
}
}
func testMeasure20() {
measure {
_ = insertionSort(arrLen: 20)
}
}
}
insertionSort()
的工作原理是生成一个长度为 arrLen
的数组并用随机数填充它。
有没有办法以某种方式自动化这个过程?
另外,有没有办法获取控制台中的输出并将其保存为字符串,以便我稍后可以解析它以获取相关信息?
XCTest 不像其他测试框架那样内置对参数化测试的支持,但您可以在测试函数中使用循环来模拟此功能。
这是一个迭代数组长度的数组并调用insertionSort(arrLen:)的示例对于每个一个:
class insertionSortPerformanceTest: XCTestCase {
func testInsertionSortPerformance() {
let arrayLengths = Array(stride(from: 15, through: 1500, by: 5))
for arrLen in arrayLengths {
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
startMeasuring()
_ = insertionSort(arrLen: arrLen)
stopMeasuring()
}
}
}
}
使用automaticStartMeasuring: false 允许您手动控制测量过程。您可以使用 startMeasuring() 开始测量,并使用 stopMeasuring() 停止测量。
捕获控制台输出 捕获控制台输出有点棘手,因为 XCTest 本身不提供将测试日志保存到字符串的直接方法。但是,您可以使用多种方法在 Swift 中捕获 stdout 和 stderr 来收集这些日志。
这是一个临时捕获标准输出的示例函数:
func captureStandardOutput(closure: () -> ()) -> String {
let originalStdout = dup(STDOUT_FILENO)
let pipe = Pipe()
dup2(pipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)
closure()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
if let output = String(data: data, encoding: .utf8) {
dup2(originalStdout, STDOUT_FILENO)
close(originalStdout)
return output
}
return ""
}
您可以像这样使用此功能:
class insertionSortPerformanceTest: XCTestCase {
func testInsertionSortPerformance() {
// Your code
let output = captureStandardOutput {
// Your test logic here
}
print("Captured output: \(output)")
}
}
使用此方法时请务必小心,因为它涉及更改 stdout 的文件描述符,这在多线程环境中可能存在风险。捕获输出后始终恢复原始的 stdout 文件描述符,以避免影响应用程序的其他部分。
然后您可以解析输出字符串以提取您想要收集的信息。