iOS - Die Datei 'MyProject-Swift.h' wurde beim Ausführen von Unit Tests für Swift nicht gefunden

94

Ich versuche, Unit Testing für mein Projekt einzurichten. Es ist eine vorhandene Objective-C-App, zu der ich kürzlich eine Swift-Klasse hinzugefügt habe. Ich habe die Dateien 'MyProject-Swift.h' und Swift Bridging (beide 'MyProject' und 'MyProjectTest') eingerichtet und kann die App mit Objective-C- und Swift-Code problemlos erstellen und ausführen.

Jetzt möchte ich jedoch einige Unit-Tests für die neue Swift-Klasse ausführen. Ich habe meine Testdatei eingerichtet und sie sieht folgendermaßen aus:

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.
        }
    }

}

Ich erhalte diesen Fehler, wenn ich die App als Test ausführe:

'MyProject-Swift.h' file not found

Ich bin nicht sicher, warum dies nur passiert, wenn versucht wird, die Tests auszuführen. Irgendwelche Vorschläge?

JimmyJammed
quelle
1
Updates dazu hinzufügen? Ich
stehe
1
@Coveloper - Wie können Sie die Ziele für die Datei '-Swift.h' festlegen? Es ist keine echte Datei, die sich im Projekt befindet, sondern beim Erstellen von Xcode kompiliert wird.
JimmyJammed
1
Hier ist ein Update für meinen Kommentar "Ich erhalte auch den Fehler 'MyProject-Swift.h' nicht gefunden." Oben: Ich habe eine Problemumgehung gefunden, indem ich den Produktmodulnamen des MyProjectTests-Ziels auf MyProject im Gegensatz zu MyProjectTests gesetzt habe. Jetzt haben beide Ziele (MyProject und MyProjectTests) denselben Produktmodulnamen. Das ist seltsam, aber es funktioniert und ist risikoarm, da es das Testziel ist. Ich sollte erwähnen, dass mein Projektname tatsächlich wie My-Project ist, daher ist My_Project der tatsächliche
Modulname
6
Die Datei "MyProject-Swift.h" wird unter "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources" generiert. Am Ende füge ich dies zu den Header-Suchpfaden für mein Unit-Test-Ziel hinzu.
Gagarwal
1
@gagarwal Das Hinzufügen von "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources" zu den Header-Suchpfaden für mein Unit-Test-Ziel hat funktioniert. :) Machen Sie eine SO-Antwort aus diesem Kommentar und ich kann Ihnen das Kopfgeld verleihen und anderen klar machen, was für eine großartige Antwort es ist.
Finneycanhelp

Antworten:

148

Die Datei "MyProject-Swift.h" wird unter folgendem Pfad generiert:

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

Am Ende füge ich dies zu den Header-Suchpfaden für mein Unit-Test-Ziel hinzu.

Auch als @hyouuu darauf hinwies, dass es sich um das bekannte Problem handelt, wird Apple hoffentlich am Ende eine gute Lösung anbieten. Bis ich glaube, dass wir diese obige Lösung verwenden müssen.

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

gagarwal
quelle
Lief wie am Schnürchen!
DonnaLea
Genial! Ich weiß nicht, warum Apple dies nicht als Problemumgehung erwähnt. Ich bin auch erstaunt, dass es nicht mehr Leute gibt, die dieses Problem haben. Jeder, der bereits ein Obj-C-Projekt hat und die Dinge schrittweise in Swift konvertiert, wird dieses Problem lösen.
mluisbrown
@fabb nicht wahr - der TARGET_NAME ist im Allgemeinen so etwas wie <Product Name> Testsin Ihrem Testziel . Diese Lösung funktioniert jedoch nicht, wenn Ihr Produktname Leerzeichen enthält. Siehe meine Antwort unten für eine Lösung.
Christopher Pickslay
2
Nur eine Anmerkung, ich musste den Suchpfad hinzufügen und ihn speziell als "rekursiv" festlegen. Könnte offensichtlich sein, aber es hat ein paar Mal nicht funktioniert, bis ich das getan habe; Ich gehe davon aus, dass es dann in Unterordner geht.
Miro
1
Für mein Projekt hat $(TARGET_TEMP_DIR)es nicht funktioniert. Ich endete mit$CONFIGURATION_TEMP_DIR/{myTargetName}.build/DerivedSources
Jordan Bondo
32

Vielen Dank an @gagarwal, dass Sie das herausgefunden haben. In unserem Fall hat der Produktname ein Leerzeichen, das eingeblendet ist $PROJECT_NAME, also musste ich es hart codieren. Darüber hinaus können Sie mit $CONFIGURATION_TEMP_DIRanstelle von $TARGET_TEMP_DIRdas übergeordnete Verzeichnis ( ../) aus dem Pfad entfernen . Die Lösung besteht also darin, den Header-Suchpfaden in Ihrem Testziel Folgendes hinzuzufügen:

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

Oder wenn Ihr Produkt keine Leerzeichen enthält:

"$(CONFIGURATION_TEMP_DIR)/$(PROJECT_NAME).build/DerivedSources"
Christopher Pickslay
quelle
Löst auch das Problem des Unit-Tests von Core Data-Codegenklassen.
Elise van Looij
14

Im Versionshinweis zu Xcode 6.1 wurde festgestellt, dass dies ein bekanntes Problem ist ... Zeichen ... Suchen Sie im Versionshinweis https://developer.apple.com/library/content/documentation/Xcode nach "-swift.h" /Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html

In Objective-C geschriebene Tests können den von Swift generierten Schnittstellenheader ($ (PRODUCT_MODULE_NAME) -Swift.h) für Anwendungsziele nicht importieren und können daher nicht zum Testen von Code verwendet werden, für den dieser Header erforderlich ist.

Tests für Swift-Code sollten in Swift geschrieben werden. In Objective-C geschriebene Tests für Framework-Ziele können auf die von Swift generierten Schnittstellen zugreifen, indem das Framework-Modul mit @import FrameworkName; importiert wird. (16931027)

Bitte beachten Sie die Problemumgehung von @ gagarwal, unter der WORKS!

Hyouuu
quelle
8

Ich hatte ein ähnliches Problem wie Sie, denke ich. Hier war mein Setup.

Ich hatte ein Objekt in Swift definiert:

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

Diese Klasse wurde dann im Initialisierer eines Objective-C-Objekts verwendet:

// file Bar.h
#import "MyProject-Swift.h"

@interface Bar: NSObject

- (instancetype)initWithFoo:(Foo *)foo;

@end

Dies führte dazu, dass meine Unit-Tests Barnicht kompiliert wurden, da der MyProject-Swift.hHeader nicht real ist und das Unit-Test-Ziel ihn nicht sehen kann. Der von @hyouuu geteilte Versionshinweis ist zutreffend - aber ich teste keine Swift-Klasse, sondern eine Objective-C-Klasse!

Ich konnte dies beheben, indem ich die Header-Datei so änderte, dass Barstattdessen eine Forward-Klassenreferenz verwendet wurde:

// file Bar.h
@class Foo;

@interface Bar: NSObject

- (instancetype)initWithFoo:(Foo *)foo;

@end

Ich habe dann eingeschlossen MyProject-Swift.hin Bar.m, und alles funktionierte - meine Tests von Objective-C - Objekten in Objective-C geschrieben zusammengestellt richtig und fortgesetzt ausgeführt wird , und ich kann neue Tests schreibt für Swift in Swift - Objekten.

Hoffe das hilft!

dpassage
quelle
Ihre Lösung erlaubt es nicht, die FooAPI im Inneren zu verwenden Bar.m.
Yevhen Dubinin
2
Sicher tut es das - das bringt es Ihnen , wenn Sie es MyProject-Swift.hin die .mDatei aufnehmen.
Passage
4

Nachdem ich alles versuchte , konnte ich zu dem Thema finden, das , was für mich gearbeitet wurde tatsächlich läuft die App , obwohl es nach wie vor die ‚Module-Swift.h Datei nicht gefunden‘ Fehler zeigt wurde.

Es ging weg und meine App funktioniert einwandfrei. Ich denke, ich hätte früher darüber nachdenken sollen ... Der Fehler tritt immer wieder auf , aber nach dem Ausführen der App verschwindet er immer wieder. Das Problem ist für mich also nicht wirklich gelöst, aber ich kann vorerst weiter an anderen Themen arbeiten ...

schrulnz
quelle
Ja, es ist eine Lösung, um den Fehler "nicht gefunden" zu beheben.
Vijay Kumar Kanta
Selbst jetzt schlägt Build fehl, während nur die App ausgeführt wird. Repariere das, Apple!
ScottyB
1

Eine einfache

@testable import MyProject

hat den Job für mich gemacht.

Niggeulimann
quelle
0

Seltsamerweise sah ich denselben Fehler, aber nur beim Targeting eines Geräts (nicht des Simulators). Vor dem Ausführen des Tests würde das rote Ausrufezeichen neben der Importanweisung für "MyProjectNameTests-Swift.h" angezeigt.

Komisch ist jedoch, dass XCode während der darauf folgenden Erstellungsphase tatsächlich die Datei "MyProjectNameTests-Swift.h" und den Test generiert, wenn ich den Test trotzdem ausführe (trotz dieses offensichtlichen Erstellungsfehlers) läuft gut!

Zumindest in meinem Fall waren die anderen Lösungen hier offensichtlich nicht erforderlich, obwohl ich glaube, dass sie auch funktionieren.

Ich sollte auch beachten, dass ich zuvor mein DerivedData-Verzeichnis gelöscht habe. Vielleicht ist das auch ein Schritt, den es sich zu versuchen lohnt.

CommaToast
quelle
-1

mySwiftClassTests(und alle anderen schnellen Klassen, die Sie in Ziel-c verwenden möchten) müssen markiert werden @objc:

@objc class MySwiftClassTests: XCTestCase
Wer weiß
quelle
-1

Ich konnte es nicht zum Laufen bringen, indem ich den in anderen Antworten erwähnten Dateipfad hinzufügte, aber mir wurde klar, dass die Datei, in der sie sich beschwerte, nicht einmal getestet wurde. Ich musste es nur mithilfe der rechten Seitenleiste des Dienstprogramms vom Testziel entfernen.

Teradyl
quelle
-2

Das Hinzufügen einer .swift-Datei zu diesem Ziel behebt das Problem.

Dmitry
quelle