iOS: file "MyProject-Swift.h" non trovato durante l'esecuzione di Unit Tests for Swift


94

Sto provando a configurare Unit Testing per il mio progetto. È un'app Objective-C esistente, a cui ho recentemente aggiunto una classe Swift. Ho configurato i file "MyProject-Swift.h" e Swift Bridging (sia "MyProject" che "MyProjectTest") e sono in grado di creare ed eseguire l'app senza problemi utilizzando sia Objective-C che il codice Swift.

Tuttavia, ora voglio eseguire alcuni test unitari sulla nuova classe Swift. Ho impostato il mio file di prova e sembra il seguente:

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

}

Ricevo questo errore quando eseguo l'app come Test:

'MyProject-Swift.h' file not found

Non sono sicuro del motivo per cui ciò accade solo quando si tenta di eseguire i test. Eventuali suggerimenti?


1
Aggiungere aggiornamenti su questo? Sto affrontando lo stesso problema ...
hyouuu

1
@Coveloper - Come sei in grado di impostare gli obiettivi per il file "-Swift.h"? Non è un file reale che si trova nel progetto, ma invece compilato da Xcode in build.
JimmyJammed

1
Ecco un aggiornamento al mio commento "Ho anche ricevuto l'errore di file 'MyProject-Swift.h' non trovato .." sopra: Ho trovato una soluzione alternativa impostando il nome del modulo del prodotto del target MyProjectTests su MyProject invece di MyProjectTests. Quindi, ora entrambi i target (MyProject e MyProjectTests) hanno lo stesso nome del modulo del prodotto. È strano, ma funziona ed è a basso rischio poiché è l'obiettivo del test. Dovrei menzionare che il nome del mio progetto è in realtà come My-Project, quindi My_Project è il nome effettivo del modulo.)
finneycanhelp

6
Il file "MyProject-Swift.h" viene generato in "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources". Finisco per aggiungerlo ai percorsi di ricerca delle intestazioni per il mio obiettivo di unit test.
gagarwal

1
@gagarwal L'aggiunta di "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources" ai percorsi di ricerca delle intestazioni per il mio obiettivo di Unit Test ha funzionato. :) Fai una risposta SO da quel commento e posso premiarti con la taglia e chiarire agli altri che ottima risposta è.
finneycanhelp

Risposte:


148

Il file "MyProject-Swift.h" viene generato nel seguente percorso:

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

Finisco per aggiungerlo ai percorsi di ricerca delle intestazioni per il mio obiettivo di unit test.

Inoltre, come @hyouuu ha sottolineato che è il problema noto, si spera che Apple fornisca una buona soluzione alla loro fine. Fino a quando non credo che dobbiamo usare questa soluzione di cui sopra.

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


Ha funzionato come un fascino!
DonnaLea

Eccezionale! Non so perché Apple non lo menziona come soluzione alternativa. Sono anche stupito che non ci siano più persone che hanno questo problema. Chiunque abbia un progetto Obj-C esistente che converte le cose in Swift gradualmente colpirà questo problema.
mluisbrown

@fabb non è vero: TARGET_NAME è generalmente qualcosa di simile <Product Name> Testsnel tuo obiettivo di test. Tuttavia, questa soluzione non funziona se il nome del prodotto contiene spazi. Vedi la mia risposta di seguito per una soluzione.
Christopher Pickslay

2
Solo una nota, ho dovuto aggiungere il percorso di ricerca e impostarlo come "ricorsivo" in modo specifico. Potrebbe essere ovvio, ma non ha funzionato alcune volte fino a quando non l'ho fatto; Quindi presumo che vada nelle sottocartelle.
Miro

1
Per il mio progetto, $(TARGET_TEMP_DIR)non ha funzionato. Ho finito per usare$CONFIGURATION_TEMP_DIR/{myTargetName}.build/DerivedSources
Jordan Bondo il

32

Grazie a @gagarwal per aver capito. Nel nostro caso il nome del prodotto ha uno spazio, che è compresso $PROJECT_NAME, quindi ho dovuto codificarlo. Inoltre, utilizzando $CONFIGURATION_TEMP_DIRinvece di $TARGET_TEMP_DIR, è possibile rimuovere la directory padre ( ../) dal percorso. Quindi la soluzione è aggiungere quanto segue ai percorsi di ricerca delle intestazioni nel target di test:

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

Oppure, se il tuo prodotto non contiene spazi:

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

Risolve anche il problema del test delle classi Core Data codegen.
Elise van Looij

14

Ho visto nella nota di rilascio di Xcode 6.1 che si tratta di un problema noto ... segno ... Cerca "-swift.h" nella nota di rilascio https://developer.apple.com/library/content/documentation/Xcode /Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html

I test scritti in Objective-C non possono importare l'intestazione delle interfacce generate da Swift ($ (PRODUCT_MODULE_NAME) -Swift.h) per le destinazioni dell'applicazione e quindi non possono essere utilizzate per testare il codice che richiede questa intestazione.

I test per il codice Swift devono essere scritti in Swift. I test scritti in Objective-C per i target del framework possono accedere alle interfacce generate da Swift importando il modulo del framework usando @import FrameworkName ;. (16931027)

Si prega di vedere la soluzione alternativa di @ gagarwal sotto la quale FUNZIONA!


8

Ho avuto un problema simile al tuo, credo; ecco il mio setup.

Avevo un oggetto definito in Swift:

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

Questa classe è stata quindi utilizzata nell'inizializzatore di un oggetto Objective-C:

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

@interface Bar: NSObject

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

@end

Ciò ha impedito la Barcompilazione dei miei unit test , poiché l' MyProject-Swift.hintestazione non è reale e l'obiettivo dello unit test non può vederlo. La nota di rilascio condivisa da @hyouuu è giusta, ma non sto testando una classe Swift, sto testando una classe Objective-C!

Sono stato in grado di risolvere questo problema modificando il file di intestazione per Barutilizzare invece un riferimento di classe in avanti:

// file Bar.h
@class Foo;

@interface Bar: NSObject

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

@end

Ho poi incluso MyProject-Swift.hin Bar.m, e tutto ha funzionato - i miei test di Objective-C oggetti scritti in Objective-C compilato correttamente e ha continuato la corsa, e ho potuto scrivere nuovi test per Swift oggetti a Swift.

Spero che questo ti aiuti!


La tua soluzione non consente di utilizzare Fool'API di all'interno Bar.m.
Yevhen Dubinin

2
Certo che lo fa - questo è ciò che ti offre l'inclusione MyProject-Swift.hnel .mfile.
dpassage

4

Dopo aver provato tutto ciò che potevo trovare sull'argomento, la cosa che ha funzionato per me in realtà era l' esecuzione dell'app anche se mostrava ancora l'errore "ModuleName-Swift.h file not found".

È andato via e la mia app funziona perfettamente. Immagino che avrei dovuto considerarlo prima ... L' errore continua a tornare , ma dopo aver eseguito l'app scompare sempre di nuovo. Quindi il problema non è davvero risolto per me, ma posso continuare a lavorare su altri argomenti per ora ...


Sì, è una soluzione per eliminare l'errore "non trovato".
Vijay Kumar Kanta

Anche ora, Build non riesce mentre funziona solo l'esecuzione dell'app. Risolvi il problema, Apple!
ScottyB


0

Stranamente, stavo vedendo lo stesso errore, ma solo quando miravo a un dispositivo (non al simulatore). Prima di eseguire il test vedrei il punto esclamativo rosso accanto all'istruzione di importazione per "MyProjectNameTests-Swift.h".

Tuttavia, la cosa divertente è che, se vado avanti ed eseguo comunque il test (nonostante questo apparente errore di build), durante la fase di build che si verifica successivamente, XCode genera effettivamente il file "MyProjectNameTests-Swift.h" e il test funziona bene!

Quindi, almeno nel mio caso, non c'era bisogno delle altre soluzioni qui, evidentemente, anche se credo che funzionino anche loro.

Dovrei anche notare che ho cancellato la mia directory DerivedData prima di questo, quindi forse anche questo è un passaggio che vale la pena provare.


-1

mySwiftClassTests(e qualsiasi altra classe rapida che desideri utilizzare nell'obiettivo-c) deve essere contrassegnata @objc:

@objc class MySwiftClassTests: XCTestCase

-1

Non sono riuscito a farlo funzionare aggiungendo quel percorso file menzionato da altre risposte, ma mi sono reso conto che il file in cui si lamentava non era nemmeno in fase di test. Dovevo solo rimuoverlo dal target di prova usando la barra laterale Right Utilities.


-2

L'aggiunta di un file .swift a quella destinazione risolve il problema su di esso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.