iOS: no se encuentra el archivo 'MyProject-Swift.h' al ejecutar Pruebas unitarias para Swift

94

Estoy intentando configurar Unit Testing para mi proyecto. Es una aplicación Objective-C existente, a la que recientemente agregué una clase Swift. He configurado los archivos 'MyProject-Swift.h' y Swift Bridging (tanto 'MyProject' como 'MyProjectTest') y puedo compilar y ejecutar la aplicación sin problemas con Objective-C y código Swift.

Sin embargo, ahora quiero ejecutar algunas pruebas unitarias en la nueva clase Swift. Configuré mi archivo de prueba y se parece a lo siguiente:

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

}

Recibo este error al ejecutar la aplicación como prueba:

'MyProject-Swift.h' file not found

No estoy seguro de por qué sucede esto solo cuando intento ejecutar las pruebas. ¿Alguna sugerencia?

JimmyJammed
fuente
1
¿Agregar actualizaciones sobre esto? Estoy enfrentando el mismo problema ...
hyouuu
1
@Coveloper - ¿Cómo puede establecer los objetivos para el archivo '-Swift.h'? No es un archivo real que se encuentra en el proyecto, sino que lo compila Xcode en la compilación.
JimmyJammed
1
Aquí hay una actualización de mi comentario anterior "También obtengo el error 'MyProject-Swift.h' archivo no encontrado ...": Encontré una solución estableciendo el Nombre del módulo de producto del objetivo de MyProjectTests en MyProject en lugar de MyProjectTests. Entonces, ahora ambos destinos (MyProject y MyProjectTests) tienen el mismo nombre de módulo de producto. Eso es extraño, pero funciona y es de bajo riesgo ya que es el objetivo de la prueba. Debo mencionar que el nombre de mi proyecto es en realidad como My-Project, por lo que My_Project es el nombre del módulo real.)
finneycanhelp
6
El archivo "MyProject-Swift.h" se genera en "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources". Termino agregando esto a las rutas de búsqueda de encabezado para mi objetivo de prueba unitaria.
gagarwal
1
@gagarwal Agregar "$ (TARGET_TEMP_DIR) /../$ (PROJECT_NAME) .build / DerivedSources" a las rutas de búsqueda de encabezado para mi objetivo de prueba unitaria funcionó. :) Haga una respuesta SO de ese comentario y puedo otorgarle la recompensa y dejar en claro para los demás la gran respuesta que es.
finneycanhelp

Respuestas:

148

El archivo "MyProject-Swift.h" se genera en la siguiente ruta:

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

Termino agregando esto a las rutas de búsqueda de encabezado para mi objetivo de prueba unitaria.

Además, como @hyouuu señaló sobre ser el problema conocido, es de esperar que Apple proporcione una buena solución al final. Hasta que crea que tenemos que utilizar esta solución anterior.

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

Gagarwal
fuente
¡Trabajado como un encanto!
DonnaLea
¡Increíble! No sé por qué Apple no menciona esto como una solución. También me sorprende que no haya más personas que tengan este problema. Cualquiera con un proyecto Obj-C existente que convierta cosas a Swift gradualmente encontrará este problema.
mluisbrown
@fabb no es cierto: TARGET_NAME es generalmente algo parecido <Product Name> Testsa su objetivo de prueba. Sin embargo, esta solución no funciona si el nombre de su producto tiene espacios. Vea mi respuesta a continuación para obtener una solución.
Christopher Pickslay
2
Solo una nota, tuve que agregar la ruta de búsqueda y configurarla como "recursiva" específicamente. Puede ser obvio, pero algunas veces no funcionó hasta que hice eso; Entonces supongo que va a subcarpetas.
Miro
1
Para mi proyecto, $(TARGET_TEMP_DIR)no funcionó. Terminé usando$CONFIGURATION_TEMP_DIR/{myTargetName}.build/DerivedSources
Jordan Bondo
32

Gracias a @gagarwal por resolver esto. En nuestro caso, el nombre del producto tiene un espacio, que está contraído $PROJECT_NAME, así que tuve que codificarlo. Además, al usar en $CONFIGURATION_TEMP_DIRlugar de $TARGET_TEMP_DIR, puede eliminar el directorio principal ( ../) de la ruta. Entonces, la solución es agregar lo siguiente a las Rutas de búsqueda de encabezado en su objetivo de prueba:

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

O, si su producto no contiene espacios:

"$(CONFIGURATION_TEMP_DIR)/$(PROJECT_NAME).build/DerivedSources"
Christopher Pickslay
fuente
También resuelve el problema de las clases de codegen Core Data de prueba unitaria.
Elise van Looij
14

Vi en la nota de lanzamiento de Xcode 6.1, que este es un problema conocido ... firmar ... Busque "-swift.h" en la nota de lanzamiento https://developer.apple.com/library/content/documentation/Xcode /Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html

Las pruebas escritas en Objective-C no pueden importar el encabezado de interfaces generado por Swift ($ (PRODUCT_MODULE_NAME) -Swift.h) para los objetivos de la aplicación y, por lo tanto, no se pueden usar para probar el código que requiere este encabezado.

Las pruebas para el código Swift deben escribirse en Swift. Las pruebas escritas en Objective-C para los objetivos del marco pueden acceder a las interfaces generadas por Swift importando el módulo del marco usando @import FrameworkName ;. (16931027)

¡Vea la solución alternativa de @gagarwal a continuación que FUNCIONA!

hyouuu
fuente
8

Creo que tuve un problema similar al tuyo; aquí estaba mi configuración.

Tenía un objeto definido en Swift:

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

Esta clase luego se usó en el inicializador de un objeto Objective-C:

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

@interface Bar: NSObject

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

@end

Esto hizo que mis pruebas unitarias Barno se compilaran, ya que el MyProject-Swift.hencabezado no es real y el objetivo de la prueba unitaria no puede verlo. La nota de lanzamiento compartida por @hyouuu está en el punto, pero no estoy probando una clase Swift, ¡estoy probando una clase Objective-C!

Pude solucionar esto cambiando el archivo de encabezado para Barusar una referencia de clase directa en su lugar:

// file Bar.h
@class Foo;

@interface Bar: NSObject

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

@end

A continuación, he incluido MyProject-Swift.hen Bar.m, y todo funcionaba - mis pruebas de Objective-C objetos escritos en Objective-C compilado correctamente y siguieron corriendo, y yo podría escribir nuevas pruebas para objetos Swift en Swift.

¡Espero que esto ayude!

pasaje
fuente
Su solución no permite usar Foola API dentro Bar.m.
Yevhen Dubinin
2
Claro que sí, eso es lo que le ofrece la inclusión MyProject-Swift.hen el .marchivo.
Dpassage
4

Después de probar todo lo que pude encontrar sobre el tema, lo que funcionó para mí fue ejecutar la aplicación, aunque todavía mostraba el error 'ModuleName-Swift.h file not found'.

Desapareció y mi aplicación funciona perfectamente bien. Supongo que debería haberlo considerado antes ... El error sigue apareciendo , pero después de ejecutar la aplicación siempre desaparece. Entonces el problema no está realmente resuelto para mí, pero puedo seguir trabajando en otros temas por ahora ...

Schrulnz
fuente
Sí, es una solución para que desaparezca el error "no encontrado".
Vijay Kumar Kanta
Incluso ahora, Build falla mientras solo funciona la aplicación. ¡Arregla esto, Apple!
ScottyB
1

Un simple

@testable import MyProject

ha hecho el trabajo por mí.

niggeulimann
fuente
0

Curiosamente, estaba viendo este mismo error, pero solo cuando apuntaba a un dispositivo (no al simulador). Antes de ejecutar la prueba, vería el signo de exclamación rojo junto a la declaración de importación para "MyProjectNameTests-Swift.h".

Sin embargo, lo curioso es que si sigo adelante y ejecuto la prueba de todos modos (a pesar de este aparente error de compilación), durante la fase de compilación que ocurre a partir de entonces, XCode realmente genera el archivo "MyProjectNameTests-Swift.h", y la prueba funciona muy bien!

Entonces, al menos en mi caso, no hubo necesidad de las otras soluciones aquí, evidentemente, aunque creo que también funcionan.

También debo tener en cuenta que eliminé mi directorio DerivedData antes de esto, por lo que tal vez ese sea un paso que también valga la pena intentar.

CommaToast
fuente
-1

mySwiftClassTests(y cualquier otra clase rápida que desee utilizar en el objetivo-c) debe marcarse @objc:

@objc class MySwiftClassTests: XCTestCase
quién sabe
fuente
-1

No pude hacer que funcionara agregando esa ruta de archivo mencionada en otras respuestas, pero me di cuenta de que el archivo donde se quejaba ni siquiera se estaba probando. Solo tuve que eliminarlo del objetivo de prueba usando la barra lateral de utilidades derecha.

teradilo
fuente
-2

Agregar un archivo .swift a ese objetivo soluciona el problema.

Dmitry
fuente