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 的未定义符号”的主要内容,如果未能解决你的问题,请参考以下文章

C++ 错误:架构 x86_64 的未定义符号

如何解决 NSScanner 上的“架构 x86_64 的未定义符号”? react-native 中的 Swift pod

Quickblox:架构 x86_64 的未定义符号:错误

架构 x86_64 的未定义符号:“_OBJC_CLASS_$_RCTImageLoader”

编译时错误“架构 x86_64 的未定义符号”是啥意思?

使用 openCV 构建 Bazel,错误:架构 x86_64 的未定义符号