Swift test дают ошибку "Undefined символы для архитектуры x86_64"

Я запускаю swift test из командной строки для запуска тестовых случаев. Это тестовый пример:

import XCTest
@testable import vnk_swift

class KeyMappingTests: XCTestCase {
    static var allTests : [(String, (KeyMappingTests) -> () throws -> Void)] {
        return [
            // ("testExample", testExample),
        ]
    }

    func testExample() {
        let keyMapping = KeyMapping()
        XCTAssertNotNil(keyMapping , "PASS")
    }
}

А вот и выходное сообщение.

image

Если я уберу использование KeyMapping, все будет работать нормально:

    func testExample() {
        // let keyMapping = KeyMapping()
        XCTAssertNotNil(true , "PASS")
    }

image

Похоже, есть проблема, когда я пытаюсь использовать класс. Как мне это исправить?

(Я не использовал Xcode для этого проекта, так как начал с swift package init, исходный код этого проекта находится здесь: https://github.com/trungdq88/vnk-swift)

Ответы

Ответ 1

Мне удалось успешно собрать и протестировать ваш пакет, выполнив следующие изменения:

  • переименовал имя пакета в VnkSwift, по некоторым причинам инструмент сборки не любит тире в имени пакета и не работает, когда у вас есть подчеркивание в имени сгенерированного пакета (поэтому переименуйте пакет в vnk_swift чтобы убедиться, что оператор импорта и пакет совпадение имен не сработало)
  • переименовал тестовую папку в VnkSwiftTests чтобы компоновщик знал, с чем связываться; кажется, что это обязательное условие для компоновщика, чтобы знать, чтобы связать с пакетом
  • наконец, переименовал main.swift во что-то другое (я использовал utils.swift). Дело в том, что наличие main.swift инструктирует инструмент компоновки генерировать исполняемый файл, и связывание с исполняемым файлом работает не очень хорошо. После переименования пришлось комментировать код if, так как глобально работающий код может принадлежать только main.swift.

Заключить:

  • Избегайте не алфавитно-цифровых имен пакетов
  • Имя пакета и имя тестового каталога должны быть синхронизированы
  • Убедитесь, что у вас нет файла main.swift чтобы убедиться, что пакет может быть связан с

Почему нельзя проверить целевую ссылку модульного тестирования на исполняемые файлы?

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

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

Ответ 2

Кажется, это вызвано тем, что у меня в каталоге модулей есть main.swift. Это приводит к сборке исполняемого файла, а не библиотеки, с которой могут быть связаны ваши тесты.

Я решил эту проблему, разделив мой код на два модуля. Библиотека, для которой у меня есть тестовые случаи, и приложение, которое содержит только main.swift:

Package.swift
Sources\FooBarLib\
Sources\FooBarLib\Something.swift
Sources\FooBarLib\MoreStuff.swift
Sources\FooBarApp\main.swift
Tests\FooBarLibTests\TestSomething.swift

Затем в моем Package.swift убедитесь, что FooBarApp зависит от FooBarLib:

import PackageDescription

let package = Package(
    name: "FooBar",
    targets: [
        .target(name: "FooBarLib"),
        .target(name: "FooBarApp", dependencies: ["FooBarLib"])
    ],
)

Затем в TestSomething.swift вы импортируете модуль FooBarLib:

@testable import FooBarLib
import XCTest

class TestSomething: XCTestCase {
    func testFunc() {
    }
}

Ответ 3

Добавить в ответ @Frank.

В Swift 4 проверьте, зависит ли ваш .testTarget от FooBarLib.

    .testTarget(
        name: "FooBarLibTests",
        dependencies: ["FooBarLib"]),

Ответ 4

Я вижу, что в каталогах у вас есть vnk-swift, но в операторах импорта и в искаженном имени у вас есть vnk_swift. Может быть, это ошибка Xcode/компилятора при обработке дефисов. Попробуйте воспроизвести в каталоге и проектировать без дефиса в имени, например vnkswift.

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

Ответ 5

Построение ответа @Cristik на самом деле сводится к тому, что находится в вашей папке Sources. Для меня у меня была папка в Sources, которая должна была быть точно такой же, как и в Tests, за исключением того, что то, что находится в Tests, должно быть суффиксным с Tests. Итак, если у вас есть SourcesFoo-Bar, вы должны иметь TestsFoo-BarTests. НЕТ ИСКЛЮЧЕНИЙ.

Еще одно примечание: все тире будут преобразованы в подчеркивания, поэтому в верхней части тестовых файлов вам нужно будет добавить @testable import Foo_Bar.

Ответ 6

В моем случае я включаю тест, чтобы перейти к показу тестового навигатора в XCode, щелкнуть правой кнопкой мыши и включить тест. И это сработало.