【问题标题】:iOS - 'MyProject-Swift.h' file not found when running Unit Tests for SwiftiOS - 运行 Swift 单元测试时找不到“MyProject-Swift.h”文件
【发布时间】:2014-12-15 20:56:44
【问题描述】:

我正在尝试为我的项目设置单元测试。 这是一个现有的 Objective-C 应用程序,我最近添加了一个 Swift 类。我已经设置了“MyProject-Swift.h”和 Swift Bridging 文件(“MyProject”和“MyProjectTest”),并且能够使用 Objective-C 和 Swift 代码构建和运行该应用程序。

但是,现在我想在新的 Swift 类上运行一些单元测试。 我设置了我的测试文件,它如下所示:

MySwiftClassTests.swift:

import UIKit
import XCTest
import MyProject

class MySwiftClassTests: XCTestCase {

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample() {
        // This is an example of a functional test case.
        XCTAssert(true, "Pass")
    }

    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measureBlock() {
            // Put the code you want to measure the time of here.
        }
    }

}

以测试方式运行应用程序时出现此错误:

'MyProject-Swift.h' file not found

我不确定为什么只有在尝试运行测试时才会发生这种情况。 有什么建议吗?

【问题讨论】:

  • 添加更新?我也面临同样的问题...
  • @Coveloper - 您如何设置“-Swift.h”文件的目标?它不是项目中的真实文件,而是由 Xcode 在构建时编译的。
  • 这是对我的“我也得到 'MyProject-Swift.h' 文件未找到错误..”的更新:我通过将 MyProjectTests 目标的产品模块名称设置为 MyProject 找到了一种解决方法反对 MyProjectTests。因此,现在两个目标(MyProject 和 MyProjectTests)具有相同的产品模块名称。这很奇怪,但它是有效的,而且风险很低,因为它是测试目标。我应该提到我的项目名称实际上就像 My-Project 因此 My_Project 是实际的模块名称。)
  • “MyProject-Swift.h”文件在“$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources”中生成。我最终将此添加到我的单元测试目标的标题搜索路径中。
  • @gagarwal 将“$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources”添加到我的单元测试目标的标题搜索路径中有效。 :) 从该评论中做出一个 SO 答案,我可以奖励您赏金,并让其他人清楚这是一个多么棒的答案。

标签: ios unit-testing swift header


【解决方案1】:

“MyProject-Swift.h”文件在以下路径生成:

"$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources"

我最终将此添加到我的单元测试目标的标题搜索路径中。

正如@hyouuu 指出的已知问题一样,希望Apple 最终能提供一些好的解决方案。直到我相信我们需要使用上述解决方案。

https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html

【讨论】:

  • 太棒了!不知道为什么 Apple 不将此作为一种解决方法。也很惊讶没有更多的人遇到这个问题。任何拥有现有 Obj-C 项目的人逐渐将事物转换为 Swift 都会遇到这个问题。
  • @fabb 不正确——在您的测试目标中,TARGET_NAME 通常类似于 <Product Name> Tests。但是,如果您的产品名称包含空格,则此解决方案不起作用。请参阅my answer below 以获得解决方案。
  • 请注意,我必须添加搜索路径,并将其设置为“递归”。可能很明显,但在我这样做之前它没有工作几次;我假设它会进入子文件夹。
  • 对于我的项目,$(TARGET_TEMP_DIR) 不起作用。我最终使用了$CONFIGURATION_TEMP_DIR/{myTargetName}.build/DerivedSources
  • 我目前遇到了这个问题,但似乎仍然无法解决。我已经在这个线程上尝试了所有方法,但我仍然遇到问题 - 运行所有最新版本。
【解决方案2】:

感谢@gagarwal 解决这个问题。在我们的例子中,产品名称有一个空格,它在$PROJECT_NAME 中折叠,所以我不得不对其进行硬编码。此外,通过使用 $CONFIGURATION_TEMP_DIR 而不是 $TARGET_TEMP_DIR,您可以从路径中删除父目录 (../)。所以解决方案是在你的测试目标的Header Search Paths中添加以下内容:

"$(CONFIGURATION_TEMP_DIR)/Product Name With Spaces.build/DerivedSources"

或者,如果您的产品不包含空格:

"$(CONFIGURATION_TEMP_DIR)/$(PROJECT_NAME).build/DerivedSources"

【讨论】:

  • 也解决了单元测试Core Data代码生成类的问题。
【解决方案3】:

在 Xcode 6.1 发行说明中看到,这是一个已知问题...签名... 在发行说明https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html中搜索“-swift.h”

用 Objective-C 编写的测试无法为应用程序目标导入 Swift 生成的接口标头 ($(PRODUCT_MODULE_NAME)-Swift.h),因此不能用于测试需要此标头的代码。

Swift 代码的测试应该用 Swift 编写。用 Objective-C 为框架目标编写的测试可以通过使用 @import FrameworkName; 导入框架模块来访问 Swift 生成的接口。 (16931027)

请查看@gagarwal 的解决方法,其中有效!

【讨论】:

    【解决方案4】:

    我想我遇到了和你类似的问题;这是我的设置。

    我在 Swift 中定义了一个对象:

    // file Foo.swift
    @objc public class Foo {
        // ...
    }
    

    这个类随后被用在了一个 Objective-C 对象的初始化器中:

    // file Bar.h
    #import "MyProject-Swift.h"
    
    @interface Bar: NSObject
    
    - (instancetype)initWithFoo:(Foo *)foo;
    
    @end
    

    这使得我对Bar 的单元测试无法编译,因为MyProject-Swift.h 标头不是真实的并且单元测试目标看不到它。 @hyouuu 分享的发行说明很重要——但我不是在测试 Swift 类,而是在测试一个 Objective-C 类!

    我可以通过将 Bar 的头文件更改为使用前向类引用来解决此问题:

    // file Bar.h
    @class Foo;
    
    @interface Bar: NSObject
    
    - (instancetype)initWithFoo:(Foo *)foo;
    
    @end
    

    然后我将MyProject-Swift.h 包含在Bar.m 中,一切正常 - 我对用 Objective-C 编写的 Objective-C 对象的测试正确编译并继续运行,我可以在 Swift 中为 Swift 对象编写新的测试。

    希望这会有所帮助!

    【讨论】:

    • 您的解决方案不允许在Bar.m 中使用Foo 的API。
    • 当然可以 - 这就是在 .m 文件中包含 MyProject-Swift.h 的原因。
    • 现在我知道@class 可以使用 Swift 类名,即使没有导入 Swift.h 文件。
    【解决方案5】:

    在我尝试了我能找到的关于该主题的所有内容后,对我有用的东西实际上正在运行该应用程序,尽管它仍然显示“ModuleName-Swift.h 文件不是”发现'错误。

    它消失了,我的应用程序运行良好。我想我应该早点考虑到这一点...... 错误不断出现,但在运行应用程序后它总是又消失了。所以这个问题对我来说并没有真正解决,但我现在可以继续研究其他主题......

    【讨论】:

    • 是的,这是消除“未找到”错误的解决方案。
    • 即使是现在,在运行应用程序时构建也会失败。解决这个问题,Apple!
    【解决方案6】:

    一个简单的

    @testable import MyProject
    

    为我完成了这项工作。

    【讨论】:

      【解决方案7】:

      奇怪的是,我看到了同样的错误,但仅在针对设备(而不是模拟器)时。在运行测试之前,我会在“MyProjectNameTests-Swift.h”的导入语句旁边看到红色感叹号。

      然而,有趣的是,如果我继续运行测试(尽管存在明显的构建错误),那么在随后发生的构建阶段,XCode 实际上确实生成了“MyProjectNameTests-Swift.h”文件,并且测试运行良好!

      因此,至少在我的情况下,这里显然不需要其他解决方案,尽管我相信它们也确实有效。

      我还应该注意,我在此之前删除了我的 DerivedData 目录,所以也许这也是一个值得尝试的步骤。

      【讨论】:

        【解决方案8】:

        在我的一个客户项目中,他们直接在项目中添加了框架。我解决了这样的错误;

        • 命令 1
        • 选项命令J
        • 现在在过滤器中输入框架名称(给出错误)
        • 选择框架
        • 选项命令1
        • 在 Target Membership 中选择您的 *UITests 目标

        【讨论】:

          【解决方案9】:

          mySwiftClassTests(以及您想在 Objective-c 中使用的任何其他 swift 类)需要标记为 @objc

          @objc class MySwiftClassTests: XCTestCase
          

          【讨论】:

            【解决方案10】:

            我无法通过添加其他答案提到的文件路径来使其工作,但我意识到它抱怨的文件甚至没有经过测试。我只需要使用 Right Utilities Side Bar 将其从测试目标中删除。

            【讨论】:

              【解决方案11】:

              将 .swift 文件添加到该目标可以解决问题。

              【讨论】:

                猜你喜欢
                • 2022-11-25
                • 1970-01-01
                • 2019-02-23
                • 2015-10-11
                • 2021-11-25
                • 2011-05-07
                • 2020-01-25
                • 1970-01-01
                • 2016-03-24
                相关资源
                最近更新 更多