Tengo problemas para que las pruebas unitarias se ejecuten en proyectos Swift creados con el Administrador de paquetes Swift (es decir, cualquier prueba unitaria creada por el Administrador de paquetes... las que creo desde Xcode funcionan bien desde Xcode). Recibo el mismo error en todos los proyectos generados desde el Administrador de paquetes. Para mantenerlo simple, probé un proyecto de prueba muy básico con la menor modificación posible de la configuración predeterminada, pero aún obtenía el error. Estos son los pasos para reproducir:
swift package init --type executable
(el nombre del módulo es Hello
)swift package generate-xcodeproj
import Foundation let message = "Hello, world!" print(message)
import XCTest @testable import Hello class HelloTests: XCTestCase { func testExample() { XCTAssert(message == "Hello, world!") } static var allTests = [ ("testExample", testExample), ] }
swift build
swift run Hello
(también desde Xcode).swift test
o ejecutar cualquier prueba en Xcode, la compilación falla con el siguiente mensaje de error: Undefined symbols for architecture x86_64: "Hello.message.unsafeMutableAddressor : Swift.String", referenced from: implicit closure #1 : @autoclosure () throws -> Swift.Bool in HelloTests.HelloTests.testExample() -> () in HelloTests.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
De alguna manera, parece que no se puede vincular el módulo principal, por lo que no se reconocen los símbolos. Sin embargo, no puedo decir qué está mal o cómo solucionarlo.
Descargué uno de los proyectos de muestra de GitHub y generé el proyecto Xcode. Las pruebas de este proyecto funcionan perfectamente en Xcode y en la terminal. He comparado cuidadosamente el proyecto de muestra con el mío y no puedo decir qué es diferente. Casi todo el código de instalación (Package.swift, estructura de archivos, etc.) y la configuración del proyecto son casi idénticos. La única diferencia significativa que puedo decir es que el proyecto de muestra es una biblioteca/marco y el mío es un ejecutable (pero parece que la vinculación debería funcionar igual para ambos tipos). De lo contrario, no puedo decir lo que están haciendo bien y lo que estoy haciendo mal.
Lo descubrí (gracias a la ayuda de Cristik ). Los módulos ejecutables no se pueden probar (al menos por ahora), por lo que la solución fue mover todas las definiciones a un módulo de biblioteca y dejar solo el archivo main.swift en el módulo ejecutable. De esa forma, todas las pruebas unitarias se ejecutaron con la biblioteca como dependencia frente al ejecutable. El paquete.swift ahora se ve así:
let package = Package( name: "HighestNumberPairing", products: [ .executable(name: "HighestNumberPairing", targets: ["HighestNumberPairing"]), .library(name: "NumberPairing", targets: ["NumberPairing"]), ], dependencies: [], targets: [ .target( name: "HighestNumberPairing", dependencies: ["NumberPairing"]), .target( name: "NumberPairing", dependencies: []), .testTarget( name: "NumberPairingTests", dependencies: ["NumberPairing"]), ] )
El programa completo está aquí en Github .