web-dev-qa-db-ja.com

Swiftテストでエラー「アーキテクチャ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

クラスを使用しようとすると問題があるようです。 これをどのように修正しますか?

Swift package init、このプロジェクトのソースコードは次のとおりです: https://github.com/trungdq88/vnk-Swift

30
TrungDQ

次の変更を行うことで、パッケージのビルドとテストに成功しました。

  • パッケージ名をVnkSwiftに変更しました。いくつかの理由により、ビルドツールはパッケージ名のダッシュが好きではないか、生成されたパッケージ名にアンダースコアが含まれている場合は機能しません(したがって、パッケージの名前をvnk_Swiftに変更します) importステートメントとパッケージ名の一致が機能しないことを確認するため)
  • リンカがリンク先を認識できるように、テストフォルダの名前をVnkSwiftTestsに変更しました。これは、リンカがパッケージに対してリンクすることを知るための前提条件のようです
  • 最後に、main.Swiftを別の名前に変更しました(私はutils.Swiftを使用しました)。問題は、main.Swiftの存在がビルドツールに実行可能ファイルを生成するように指示し、実行可能ファイルへのリンクがうまく機能しないことです。名前の変更後、グローバル実行コードはmain.Swiftにのみ属することができるため、ifコードをコメント化する必要がありました。

結論として:

  • 英数字以外のパッケージ名は避けてください
  • パッケージ名とテストディレクトリ名は同期している必要があります
  • main.Swiftファイルがないことを確認して、パッケージをリンクできることを確認してください

実行可能ファイルに対してターゲットテストのリンクをユニットテストできないのはなぜですか?

これは、テストバンドルと実行可能バンドルの両方にグローバル実行コード(別名main関数)が含まれているため、リンカーがどちらを選択するかがわからないためです。 Xcodeからテストする場合、テストバンドルはアプリケーションのコンテキストで実行されます-ここのような状況ではリンクされません。

Xcodeには、コマンドラインツールを作成するときにこの問題もあります。そのターゲットを単体テストすることはできません。コードを単体テストする場合は、ツールと単体テストターゲットの両方によってリンクされるライブラリを作成する必要があります(または両方のターゲットにファイルを含めます)

32
Cristik

これは、モジュールディレクトリにmain.Swiftがあることが原因と思われます。これにより、テストケースをリンクできるライブラリではなく、実行可能ファイルがビルドされます。

この問題を解決するには、コードを2つのモジュールに分割しました。私がテストケースを持っているライブラリと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() {
    }
}
16
Frank

@フランクの回答に追加してください。

Swift 4で、あなたの.testTargetFooBarLibに依存します。

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

私の場合、Xcodeでテストナビゲーターを表示し、右クリックしてテストを有効にして、テストを有効にします。そしてそれはうまくいった。

0
Cao Văn An

@Cristikの答えを基にして、実際にはSourcesフォルダーにあるものが原因です。私にとっては、Sourcesにあるフォルダが必要でした正確にTestsにあるものと同じですが、Testsにあるものが必要ですTestsを接尾辞として付けます。したがって、Sources-> Foo-Barがある場合、Tests-> Foo-BarTestsが必要でした。 例外なし

もう1つの注意:すべてのダッシュはアンダースコアに変換されるため、テストファイルの先頭に@testable import Foo_Barを追加する必要があります。

0

私はあなたが持っているディレクトリにvnk-Swift、ただしimportステートメントとマングル名にはvnk_Swift。たぶん、これはハイフンを処理するXcode /コンパイラのバグです。名前にハイフンを含まないディレクトリとプロジェクトで再現してみてください。たとえば、vnkswiftだけです。

それが役に立てば幸い

0
Alistra

ポッドファイルの作成後にTestTargetを追加する場合。次に、以下のコードがpodファイルで欠落している可能性があります。

target 'DemoTests' do
  inherit! :search_paths
  # Pods for testing
end

以下のようにターゲットの終わりの前に上記のコードを追加します。

target 'Demo' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for DocsDemo

  target 'DemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

end
0
Yogendra Singh