【问题标题】:Swift Unit Test Error: symbol(s) not found for architecture x86_64 (Swift Package Manager)Swift 单元测试错误:未找到架构 x86_64 的符号(Swift 包管理器)
【发布时间】:2019-06-24 12:58:03
【问题描述】:

我无法让单元测试在使用 Swift 包管理器创建的 Swift 项目中运行(也就是说,由包管理器创建的任何单元测试......我在 Xcode 中创建的那些在 Xcode 中都可以正常工作)。我在包管理器生成的所有项目上都收到相同的错误。为了简单起见,我尝试了一个非常基本的测试项目,尽可能少地修改默认设置,但仍然出现错误。以下是重现的步骤:

  1. 使用swift package init --type executable 创建一个新项目(模块名称为Hello
  2. 添加 Xcode 项目:swift package generate-xcodeproj
  3. 在 Xcode 构建设置中,确保 Enable Testability 为 Yes
  4. 在 swift.main 中输入这个简单的测试代码:
import Foundation

let message = "Hello, world!"
print(message)
  1. 在 HelloTests.swift 中:
import XCTest
@testable import Hello

class HelloTests: XCTestCase {
    func testExample() {
        XCTAssert(message == "Hello, world!")
    }

    static var allTests = [
        ("testExample", testExample),
    ]
}
  1. Package.swift 和 XCTestManifests.swift 保持原样。
  2. 使用swift buildswift run Hello(也可以从Xcode 内部)构建和运行良好。
  3. 但是,当运行 swift test 或在 Xcode 中运行任何测试时,构建失败并显示以下错误消息:
Undefined symbols for architecture x86_64:
  "Hello.message.unsafeMutableAddressor : Swift.String", referenced from:
      implicit closure #1 : @autoclosure () throws -> Swift.Bool in HelloTests.HelloTests.testExample() -> () in HelloTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

不知何故,似乎无法链接主模块,因此无法识别符号。但是,我不知道出了什么问题或如何解决它。

我下载了one of the sample projects from GitHub,并生成了 Xcode 项目。该项目的测试在 Xcode 和终端中完美运行。我已经仔细地将示例项目与我的项目进行了比较,但无法分辨出有什么不同。几乎所有设置代码(Package.swift、文件结构等)和项目设置几乎相同。我能说的唯一有意义的区别是示例项目是一个库/框架,而我的是一个可执行文件(但似乎链接对于这两种类型应该是一样的)。否则,我分不清他们做对了什么,我做错了什么。

【问题讨论】:

  • 情况和stackoverflow.com/questions/41322034/…的情况很相似。
  • 所以,我从中得到的是……您无法测试可执行文件。做到这一点的方法是将您的项目分解为一个或多个(可测试的)库模块......然后是一个(不可测试的)可执行文件,它几乎只包含 main.swift 文件?
  • 似乎如此。常规 Xcode 项目允许为单元测试设置宿主应用程序,从而允许直接测试应用程序代码,但不确定是否可以通过 SPM。
  • 酷...我可以使用它。我猜想在不久的将来将主机应用程序设置为 SPM。现在,这将起作用!谢谢!
  • 成功了!谢谢!

标签: swift unit-testing linker clang swift4


【解决方案1】:

我想通了(感谢Cristik 的帮助)。可执行模块是不可测试的(至少现在是这样),所以解决方案是将所有定义移动到库模块中,只将 main.swift 文件留在可执行模块中。这样,所有单元测试都使用库作为依赖项与可执行文件一起运行。 package.swift 现在看起来像这样:

let package = Package(
    name: "HighestNumberPairing",
    products: [
        .executable(name: "HighestNumberPairing", targets: ["HighestNumberPairing"]),
        .library(name: "NumberPairing", targets: ["NumberPairing"]),
    ],
    dependencies: [],
    targets: [
        .target(
            name: "HighestNumberPairing",
            dependencies: ["NumberPairing"]),
        .target(
            name: "NumberPairing",
            dependencies: []),
        .testTarget(
            name: "NumberPairingTests",
            dependencies: ["NumberPairing"]),
    ]
)

完整程序是here on Github

【讨论】:

  • 你应该把它标记为绿色!你自己的答案,完全正确:)
  • 我自己也设法解决了这个问题 - 没想到 SO 会回答 SPM 问题。
猜你喜欢
  • 1970-01-01
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 2021-03-12
  • 1970-01-01
相关资源
最近更新 更多