Swift 测试给出错误“架构 x86_64 的未定义符号”
Posted
技术标签:
【中文标题】Swift 测试给出错误“架构 x86_64 的未定义符号”【英文标题】:Swift test give error "Undefined symbols for architecture x86_64" 【发布时间】:2016-12-25 14:42:24 【问题描述】:我正在从命令行运行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")
我在尝试使用课程时似乎出现了问题。 我该如何解决这个问题?
(我没有为这个项目使用 Xcode,因为我从 swift package init
开始,这个项目的源代码在这里:https://github.com/trungdq88/vnk-swift)
【问题讨论】:
如果你构建项目,你能找到 KeyMapping.swift 的 .o 文件吗? 这里有一份您可能已经看过的单元测试指南,但也许对您有所帮助:riis.com/blog/swift-unit-testing @JochenBedersdorfer 是的,我可以在.build/vnk_swift
目录中找到KeyMapping.swift.o
。
【参考方案1】:
通过进行以下修改,我成功地构建和测试了您的包:
将包名重命名为VnkSwift
,由于某些原因,构建工具不喜欢包名中的破折号,当生成的包名中有下划线时也不起作用(因此将包重命名为vnk_swift
确保导入语句和包名匹配不起作用)
将测试文件夹重命名为VnkSwiftTests
,以便链接器知道要链接的对象;似乎这是链接器知道链接到包的先决条件
最后,将main.swift
重命名为其他名称(我使用了utils.swift
)。问题是main.swift
的存在指示构建工具生成可执行文件,并且链接到可执行文件效果不佳。改名后,必须注释if
代码,因为全局运行代码只能属于main.swift
。
总结:
避免使用非字母数字的包名称 包名和测试目录名必须同步 确保您没有main.swift
文件以确保可以链接包
为什么不能针对可执行文件进行单元测试目标链接?
这是因为测试包和可执行包都有全局执行代码(也就是主函数),所以链接器不知道选择哪一个。从 Xcode 进行测试时,测试包会运行到应用程序的上下文中——它不会链接到应用程序,就像这里的情况一样。
Xcode 在创建命令行工具时也有这个问题 - 你不能对那个目标进行单元测试,如果你想对代码进行单元测试,那么你必须创建一个库,该库将由工具和单元链接测试目标(或在两个目标中都包含文件)
【讨论】:
谢谢,它有效。但是链接可执行文件有什么问题?所以现在我无法在 OSX 上测试可执行包,因为 swift 错误?Package name and test directory name must be in sync
对我来说一点也不明显——这解决了我的问题!!谢谢!
不是一个好的解决方案。重命名 main.swift
会使包变成别的东西,而不是 executable
。你不能在这个包上运行swift run
。尽管@Frank 的回答并不优雅,但目前它似乎是最简单的方法,拥有一个带有测试的可执行 Swift 包。真的很伤心。
@RostyslavDruzhchenko Frank 的解决方案与此类似,不同之处在于他保留了 app 模块,但对于单元测试使用了相同的方法,使用库。底线是您无法测试可执行二进制文件,这不是 SPM 的错。【参考方案2】:
这似乎是因为我在您的模块目录中有一个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()
【讨论】:
这确实帮助我解决了这个问题。给其他人的一个注意事项,如果您按照建议构建代码,这也意味着您必须将FooBarLib
“库”编码为库。因此,您的类、结构、方法等必须先公开,然后才能在 main.swift 文件中使用它们。
我也是having a main.swift in your module directory
。谢谢!【参考方案3】:
在 Swift 4 中,检查您的 .testTarget
是否依赖于 FooBarLib
。
.testTarget(
name: "FooBarLibTests",
dependencies: ["FooBarLib"]),
【讨论】:
【参考方案4】:以@Cristik 的回答为基础,实际上归结为您的Sources
文件夹中的内容。对我来说,我在Sources
中有一个文件夹,它需要与Tests
中的内容完全相同 相同,只是Tests
中的内容需要以Tests
为后缀。所以,如果你有Sources
-> Foo-Bar
,你必须有Tests
-> Foo-BarTests
。 没有例外。
另一个注意事项:所有破折号都将转换为下划线,因此您必须在测试文件的顶部添加@testable import Foo_Bar
。
【讨论】:
【参考方案5】:我看到在目录中你有vnk-swift
,但在导入语句和损坏的名称中你有vnk_swift
。也许这是一个处理连字符的 Xcode/编译器错误。尝试在名称中没有连字符的目录和项目上重现,例如 vnkswift
。
希望对你有帮助
【讨论】:
是的,我也注意到了,我尝试使用 VnkSwift 但没有运气:( 将在新分支中再次使用vnkswift
名称。【参考方案6】:
在我的例子中,我通过 go to show test navigator 在 Xcode 中启用测试,右键单击并启用测试。它奏效了。
【讨论】:
【参考方案7】:在我的情况下,在迁移框架项目以将其他框架链接为 XCFramework 而不是通用框架后,某些测试无法在链接步骤中编译。
我的解决方法是将那些失败的 objc 测试转换为 Swift,问题就解决了。
【讨论】:
【参考方案8】:如果您在创建 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
【讨论】:
这个问题是关于 Swift Package Manager,而不是 CocoaPods。以上是关于Swift 测试给出错误“架构 x86_64 的未定义符号”的主要内容,如果未能解决你的问题,请参考以下文章
如何解决 NSScanner 上的“架构 x86_64 的未定义符号”? react-native 中的 Swift pod