Swift 测试给出错误 "Undefined symbols for architecture x86_64"
Swift test give error "Undefined symbols for architecture x86_64"
我正在 运行宁 swift test
从命令行到 运行 测试用例。这是测试用例:
import XCTest
@testable import vnk_swift
class KeyMappingTests: XCTestCase {
static var allTests : [(String, (KeyMappingTests) -> () throws -> Void)] {
return [
// ("testExample", testExample),
]
}
func testExample() {
let keyMapping = KeyMapping()
XCTAssertNotNil(keyMapping , "PASS")
}
}
这是输出消息。
如果我删除 KeyMapping
的用法,一切正常:
func testExample() {
// let keyMapping = KeyMapping()
XCTAssertNotNil(true , "PASS")
}
我尝试使用 class 时似乎出现了问题。 我该如何解决这个问题?
(我没有为这个项目使用Xcode,因为我从swift package init
开始,这个项目的源代码在这里:https://github.com/trungdq88/vnk-swift)
我看到在目录中您有 vnk-swift
,但在导入语句和损坏的名称中您有 vnk_swift
。也许这是处理连字符的 Xcode/compiler 错误。尝试在名称中没有连字符的目录和项目上重现,例如 vnkswift
。
希望对您有所帮助
我通过进行以下修改成功地构建和测试了您的程序包:
- 将包名称重命名为
VnkSwift
,由于某些原因,构建工具不喜欢包名称中的破折号,当生成的包名称中包含下划线时它也不起作用(因此将包重命名为 vnk_swift
以确保导入语句和包名称匹配不起作用)
- 将测试文件夹重命名为
VnkSwiftTests
以便 link 人知道 link 反对什么;似乎这是 link 人知道 link 反对包裹 的先决条件
- 最后,将
main.swift
重命名为其他名称(我使用 utils.swift
)。问题是 main.swift
的存在指示构建工具生成可执行文件,而针对可执行文件的 linking 效果不佳。重命名后,不得不注释if
代码,因为全局运行代码只能属于main.swift
.
总结:
- 避免使用非字母数字包名称
- 包名和测试目录名必须同步
- 确保您没有
main.swift
文件以确保包可以 linked against
为什么单元测试不能针对 link 可执行文件?
这是因为测试包和可执行包都有全局执行代码(又名 main 函数),所以 linker 不知道该选择哪一个。从 Xcode 进行测试时,测试包会进入应用程序的上下文 - 它不会 link 反对它,就像这里的情况一样。
Xcode 在创建命令行工具时也有这个问题 - 你不能对该目标进行单元测试,如果你想对代码进行单元测试,那么你必须创建一个库 link由工具和单元测试目标编辑(或在两个目标中包含文件)
根据@Cristik 的回答,真正归结为您的 Sources
文件夹中的内容。对我来说,我在 Sources
中有一个文件夹需要 完全 与 Tests
中的相同,只是需要 Tests
中的内容以 Tests
为后缀。所以,如果你有 Sources
-> Foo-Bar
,你必须有 Tests
-> Foo-BarTests
。 没有例外。
另一个注意事项:所有破折号都将转换为下划线,因此您必须在测试文件的顶部添加 @testable import Foo_Bar
。
这似乎是因为我在您的模块目录中有一个 main.swift
。这会生成一个可执行文件,而不是一个可以链接您的测试用例的库。
我通过将我的代码分成两个模块解决了这个问题。我有测试用例的库和仅包含 main.swift
:
的应用程序
Package.swift
Sources\FooBarLib\
Sources\FooBarLib\Something.swift
Sources\FooBarLib\MoreStuff.swift
Sources\FooBarApp\main.swift
Tests\FooBarLibTests\TestSomething.swift
然后在我的 Package.swift
中确保 FooBarApp
依赖于 FooBarLib
:
import PackageDescription
let package = Package(
name: "FooBar",
targets: [
.target(name: "FooBarLib"),
.target(name: "FooBarApp", dependencies: ["FooBarLib"])
],
)
然后在 TestSomething.swift
中导入 FooBarLib
模块:
@testable import FooBarLib
import XCTest
class TestSomething: XCTestCase {
func testFunc() {
}
}
在我的例子中,我通过在 Xcode 中显示测试导航器来启用测试,右键单击并启用测试。它奏效了。
在Swift4中,检查你的.testTarget
是否依赖于FooBarLib
。
.testTarget(
name: "FooBarLibTests",
dependencies: ["FooBarLib"]),
如果您在创建 pod 文件后添加 TestTarget。那么 pod 文件中可能缺少以下代码。
target 'DemoTests' do
inherit! :search_paths
# Pods for testing
end
在目标结束前添加上面的代码,如下所示。
target 'Demo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for DocsDemo
target 'DemoTests' do
inherit! :search_paths
# Pods for testing
end
end
在我的例子中,在将框架项目迁移到 link 其他框架(如 XCFramework 而不是通用框架)后,某些测试无法在 linking 步骤中编译。
我的修复是将那些失败的 objc 测试转换为 Swift,问题已解决。
我正在 运行宁 swift test
从命令行到 运行 测试用例。这是测试用例:
import XCTest
@testable import vnk_swift
class KeyMappingTests: XCTestCase {
static var allTests : [(String, (KeyMappingTests) -> () throws -> Void)] {
return [
// ("testExample", testExample),
]
}
func testExample() {
let keyMapping = KeyMapping()
XCTAssertNotNil(keyMapping , "PASS")
}
}
这是输出消息。
如果我删除 KeyMapping
的用法,一切正常:
func testExample() {
// let keyMapping = KeyMapping()
XCTAssertNotNil(true , "PASS")
}
我尝试使用 class 时似乎出现了问题。 我该如何解决这个问题?
(我没有为这个项目使用Xcode,因为我从swift package init
开始,这个项目的源代码在这里:https://github.com/trungdq88/vnk-swift)
我看到在目录中您有 vnk-swift
,但在导入语句和损坏的名称中您有 vnk_swift
。也许这是处理连字符的 Xcode/compiler 错误。尝试在名称中没有连字符的目录和项目上重现,例如 vnkswift
。
希望对您有所帮助
我通过进行以下修改成功地构建和测试了您的程序包:
- 将包名称重命名为
VnkSwift
,由于某些原因,构建工具不喜欢包名称中的破折号,当生成的包名称中包含下划线时它也不起作用(因此将包重命名为vnk_swift
以确保导入语句和包名称匹配不起作用) - 将测试文件夹重命名为
VnkSwiftTests
以便 link 人知道 link 反对什么;似乎这是 link 人知道 link 反对包裹 的先决条件
- 最后,将
main.swift
重命名为其他名称(我使用utils.swift
)。问题是main.swift
的存在指示构建工具生成可执行文件,而针对可执行文件的 linking 效果不佳。重命名后,不得不注释if
代码,因为全局运行代码只能属于main.swift
.
总结:
- 避免使用非字母数字包名称
- 包名和测试目录名必须同步
- 确保您没有
main.swift
文件以确保包可以 linked against
为什么单元测试不能针对 link 可执行文件?
这是因为测试包和可执行包都有全局执行代码(又名 main 函数),所以 linker 不知道该选择哪一个。从 Xcode 进行测试时,测试包会进入应用程序的上下文 - 它不会 link 反对它,就像这里的情况一样。
Xcode 在创建命令行工具时也有这个问题 - 你不能对该目标进行单元测试,如果你想对代码进行单元测试,那么你必须创建一个库 link由工具和单元测试目标编辑(或在两个目标中包含文件)
根据@Cristik 的回答,真正归结为您的 Sources
文件夹中的内容。对我来说,我在 Sources
中有一个文件夹需要 完全 与 Tests
中的相同,只是需要 Tests
中的内容以 Tests
为后缀。所以,如果你有 Sources
-> Foo-Bar
,你必须有 Tests
-> Foo-BarTests
。 没有例外。
另一个注意事项:所有破折号都将转换为下划线,因此您必须在测试文件的顶部添加 @testable import Foo_Bar
。
这似乎是因为我在您的模块目录中有一个 main.swift
。这会生成一个可执行文件,而不是一个可以链接您的测试用例的库。
我通过将我的代码分成两个模块解决了这个问题。我有测试用例的库和仅包含 main.swift
:
Package.swift
Sources\FooBarLib\
Sources\FooBarLib\Something.swift
Sources\FooBarLib\MoreStuff.swift
Sources\FooBarApp\main.swift
Tests\FooBarLibTests\TestSomething.swift
然后在我的 Package.swift
中确保 FooBarApp
依赖于 FooBarLib
:
import PackageDescription
let package = Package(
name: "FooBar",
targets: [
.target(name: "FooBarLib"),
.target(name: "FooBarApp", dependencies: ["FooBarLib"])
],
)
然后在 TestSomething.swift
中导入 FooBarLib
模块:
@testable import FooBarLib
import XCTest
class TestSomething: XCTestCase {
func testFunc() {
}
}
在我的例子中,我通过在 Xcode 中显示测试导航器来启用测试,右键单击并启用测试。它奏效了。
在Swift4中,检查你的.testTarget
是否依赖于FooBarLib
。
.testTarget(
name: "FooBarLibTests",
dependencies: ["FooBarLib"]),
如果您在创建 pod 文件后添加 TestTarget。那么 pod 文件中可能缺少以下代码。
target 'DemoTests' do
inherit! :search_paths
# Pods for testing
end
在目标结束前添加上面的代码,如下所示。
target 'Demo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for DocsDemo
target 'DemoTests' do
inherit! :search_paths
# Pods for testing
end
end
在我的例子中,在将框架项目迁移到 link 其他框架(如 XCFramework 而不是通用框架)后,某些测试无法在 linking 步骤中编译。
我的修复是将那些失败的 objc 测试转换为 Swift,问题已解决。