iOS - файл MyProject-Swift.h не найден при запуске модульных тестов для Swift

95

Я пытаюсь настроить модульное тестирование для своего проекта. Это существующее приложение 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.
        }
    }

}

Я получаю эту ошибку при запуске приложения как Test:

'MyProject-Swift.h' file not found

Я не уверен, почему это происходит только при попытке запустить тесты. Какие-либо предложения?

Джимми
источник
1
Добавить обновления по этому поводу? У меня та же проблема ...
hyouuu
1
@Coveloper - Как вы можете установить цели для файла '-Swift.h'? Это не настоящий файл, который находится в проекте, а скомпилирован Xcode при сборке.
JimmyJammed
1
Вот обновление моего комментария «Я также получаю сообщение об ошибке« MyProject-Swift.h »не найден ...» выше: Я нашел обходной путь, установив для имени модуля продукта MyProjectTests значение MyProject, а не MyProjectTests. Итак, теперь обе цели (MyProject и MyProjectTests) имеют одинаковое имя модуля продукта. Это странно, но это работает и имеет низкий риск, так как это цель Test. Я должен упомянуть, что имя моего проекта на самом деле похоже на My-Project, поэтому My_Project - это фактическое имя модуля.)
finneycanhelp
6
Файл «MyProject-Swift.h» создается по адресу «$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources». В конечном итоге я добавляю это в пути поиска заголовков для моей цели модульного теста.
gagarwal
1
@gagarwal Добавление «$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources» в пути поиска заголовков для моей цели модульного теста сработало. :) Сделайте ТАК ответ из этого комментария, и я могу наградить вас наградой, плюс дать понять другим, какой это отличный ответ.
finneycanhelp

Ответы:

148

Файл "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

Gagarwal
источник
Работал как шарм!
DonnaLea
Потрясающие! Не знаю, почему Apple не упоминает об этом как об обходном пути. Также удивлен, что больше людей не страдают этой проблемой. Любой, у кого есть существующий проект Obj-C, постепенно конвертирующий вещи в Swift, столкнется с этой проблемой.
mluisbrown
@fabb неверно - TARGET_NAME обычно выглядит как <Product Name> Testsв вашей тестовой цели. Однако это решение не работает, если в названии вашего продукта есть пробелы. См. Мой ответ ниже для решения.
Кристофер Пикслей,
2
Просто примечание, мне пришлось добавить путь поиска и конкретно установить его как «рекурсивный». Может быть очевидно, но несколько раз это не сработало, пока я не сделал это; Тогда я предполагаю, что он попадает в подпапки.
Miro
1
Для моего проекта $(TARGET_TEMP_DIR)не сработало. Я закончил употребление$CONFIGURATION_TEMP_DIR/{myTargetName}.build/DerivedSources
Джордан Бондо
33

Спасибо @gagarwal за выяснение этого. В нашем случае в названии продукта есть пробел, который свернут $PROJECT_NAME, поэтому мне пришлось его жестко закодировать. Кроме того, используя $CONFIGURATION_TEMP_DIRвместо $TARGET_TEMP_DIR, вы можете удалить родительский каталог ( ../) из пути. Итак, решение состоит в том, чтобы добавить следующее к путям поиска заголовков в вашей тестовой цели:

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

Или, если в вашем продукте нет пробелов:

"$(CONFIGURATION_TEMP_DIR)/$(PROJECT_NAME).build/DerivedSources"
Кристофер Пикслей
источник
Также решает проблему модульного тестирования классов кодогенерации Core Data.
Elise van Looij
14

В примечании к выпуску Xcode 6.1 видел, что это известная проблема ... знак ... Найдите "-swift.h" в примечании к выпуску https://developer.apple.com/library/content/documentation/Xcode /Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html

Тесты, написанные на Objective-C, не могут импортировать сгенерированный Swift заголовок интерфейсов ($ (PRODUCT_MODULE_NAME) -Swift.h) для целей приложения и, следовательно, не могут использоваться для тестирования кода, которому требуется этот заголовок.

Тесты для кода Swift должны быть написаны на Swift. Тесты, написанные на Objective-C для целей фреймворка, могут получить доступ к интерфейсам, созданным Swift, путем импорта модуля фреймворка с помощью @import FrameworkName ;. (16931027)

См. Обходной путь @ gagarwal ниже, который РАБОТАЕТ!

Хёуу
источник
8

Думаю, у меня была проблема, похожая на вашу; вот моя установка.

У меня был объект, определенный в 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.

Надеюсь это поможет!

dpassage
источник
Ваше решение не позволяет использовать FooAPI внутри Bar.m.
Евгений Дубинин
2
Конечно, есть - это то, что дает вам включение MyProject-Swift.hв .mфайл.
dpassage
4

После того, как я опробовал все, что смог найти по этой теме, то, что у меня сработало, было на самом деле запускать приложение, хотя оно все еще показывало ошибку «ModuleName-Swift.h file not found».

Он исчез, и мое приложение работает отлично. Думаю, мне следовало подумать об этом раньше ... Ошибка продолжает повторяться, но после запуска приложения она всегда снова исчезает. Так что проблема для меня не совсем решена, но пока я могу продолжить работу над другими темами ...

Шрульнц
источник
Да, это решение, позволяющее избавиться от ошибки «не найдено».
Виджай Кумар Канта
Даже сейчас Build не работает, а приложение работает. Исправь это, Apple!
ScottyB
1

Просто

@testable import MyProject

сделал всю работу за меня.

ниггеулиман
источник
0

Как ни странно, я видел ту же ошибку, но только при нацеливании на устройство (а не на симулятор). Перед запуском теста я бы увидел красный восклицательный знак рядом с оператором импорта для «MyProjectNameTests-Swift.h».

Однако забавно то, что если я все равно запускаю тест (несмотря на эту очевидную ошибку сборки), то во время фазы сборки, которая происходит после этого, XCode действительно генерирует файл «MyProjectNameTests-Swift.h», а тест работает отлично!

Так что, по крайней мере, в моем случае, очевидно, что здесь не было необходимости в других решениях, хотя я считаю, что они тоже работают.

Я также должен отметить, что я удалил свой каталог DerivedData до этого, так что, возможно, этот шаг также стоит попробовать.

CommaToast
источник
-1

mySwiftClassTests(и любые другие быстрые классы, которые вы хотите использовать в objective-c) должны быть отмечены @objc:

@objc class MySwiftClassTests: XCTestCase
кто знает
источник
-1

Мне не удалось заставить его работать, добавив этот путь к файлу, упомянутый в других ответах, но я понял, что файл, в котором он жаловался, даже не тестировался. Мне просто нужно было удалить его с тестовой цели с помощью правой боковой панели служебных программ.

терадил
источник
-2

Добавление файла .swift к этой цели устраняет проблему с ней.

Дмитрий
источник