Swift dosyasını başka bir Swift dosyasından nasıl alabilirim?


154

Swift sınıfımı test gibi başka bir dosyadan eklemek istiyorum

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel { }

PrimeNumberModelTests.swift

import XCTest
import PrimeNumberModel  // gives me "No such module 'PrimeNumberModel'"

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()  // "Use of unresolved identifier 'PrimeNumberModel'"    
}

Her iki hızlı dosya da aynı dizindedir.



2
Apple belgelerine göre, her iki dosya da aynı hedefe sahip olduğunda içe aktarmaya ihtiyacınız yoktur. Ne yazık ki testlerin farklı bir hedefi var. Olası bir çözüm, Modül / PrimeNumberModel kullanarak bir içe aktarma ifadesi yapmak olabilir.
Alex Reynolds

@ joseph.hainline Aynı sorunla karşı karşıyayım. Nasıl çözülecek? Şimdi sıkıştım.
Geliştirici

Yanıtlar:


131

Aynı problemi XCTestCasedosyalarımda da vardı , ama normal proje dosyalarında değil.

Şunlardan kurtulmak için:

Çözümlenmemiş 'PrimeNumberModel' tanımlayıcısının kullanımı

importTest dosyasındaki temel modüle ihtiyacım vardı . Benim durumumda, benim hedef 'myproject' olarak adlandırılan ve ben eklenir import myprojectve sınıf tanındı.


2
Bunun için daha fazla oy gerekiyor. Yalnızca .swift dosyasını test hedefine eklemenizi tavsiye eden cevaplar tam olarak yanlış değildir, ancak yapılması gerektiği gibi değildir
aşağıda

10
Ama içinde yer olan proje adı "Wildlife League" ile ne yapmalıyım?
allenlinli

59
Beta 4'ten başlayarak, erişim kontrolü ayarlarınızın doğru olduğundan da emin olmanız gerekir. Hem test ettiğiniz sınıfı hem de o sınıf içinde test ettiğiniz işlevleri açık bir şekilde ayarlamanız gerekir public. Aksi takdirde XCTestCasealt sınıf neyi test etmeye çalıştığınızı "göremez". Bu dün gece birkaç saat harcadım :)
Erik P. Hansen

2
Yanılmıyorsam, Ürün Modül Adı (hedef oluşturma ayarlarında) her zaman hedefin adıyla aynı değildir ve bu importifadede kullanılması gereken modülün adıdır
csch

3
Swift hedefinin adında boşluk varsa, içe aktarma ifadesindeki boşlukları alt çizgilerle değiştirerek içe aktarabilirsiniz. "Swift Sınıfım", "My_Swift_Class" olur.
Cin316

70

UPDATE Swift 2.x, 3.x, 4.x ve 5.x

Şimdi publictest etmek için yöntemlere eklemenize gerek yok . Swift'in daha yeni sürümlerinde yalnızca @testableanahtar kelimeyi eklemek gerekir .

PrimeNumberModelTests.swift

import XCTest
@testable import MyProject

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()
}

Ve dahili yöntemleriniz Internal

PrimeNumberModel.swift

import Foundation

class PrimeNumberModel {
   init() {
   }
}

Not private(ve fileprivate) sembolleri bile kullanarak mevcut değildir @testable.


Swift 1.x

Swift'ten burada ilgili iki kavram var (Xcode 6 beta 6 olarak).

  1. Swift sınıflarını içe aktarmanıza gerek yoktur, ancak harici modülleri (hedefleri) içe aktarmanız gerekir
  2. Swift'teki Varsayılan Erişim Denetimi düzeyi:Internal access

Üzerinde testler başka hedefte olduklarını düşünürsek PrimeNumberModelTests.swiftGerekirse importsenin eğer, testin istediğiniz sınıfını içeren hedefin hedef denir MyProjecteklemeniz gerekir import MyProjectiçin PrimeNumberModelTests:

PrimeNumberModelTests.swift

import XCTest
import MyProject

class PrimeNumberModelTests: XCTestCase {
    let testObject = PrimeNumberModel()
}

Ancak bu, sınıfınızı test etmek için yeterli değildir PrimeNumberModel, çünkü varsayılan Erişim Kontrolü düzeyiInternal Access sınıfınız test paketi tarafından görülmeyecektir, bu nedenle onu Public Accessve test etmek istediğiniz tüm yöntemleri yapmanız gerekir :

PrimeNumberModel.swift

import Foundation

public class PrimeNumberModel {
   public init() {
   }
}

Erişim Denetimini değiştirmenin bir yolu var mı? Genel değiştirici olmadan çalıştırmak için kullanılan komik bir durum vardı, o zaman test vakalarını hareket ettirdim, aniden çalışmayı bıraktı.
Metaphox

Bence bu mümkün değil, en azından mevcut swift sürümü için.
Diogo T

Teşekkürler. Ve benim sorunum, swift dosyasının test senaryoları ile test hedefine inşa edilmediğini öğrendim.
Metaphox

1
evet, tam olarak kendimi yanlış hissettiğim yerdi - sınıf swift dosyasını test senaryosu hedefine kurmamalıydım. güzel blog yazısı! Teşekkürler.
Metaforx

1
Xcode 5 veya daha yenisi ile oluşturulmuş bir projeniz varsa ve "genel erişim, içe aktarma hedef modülü" yaklaşımını tercih ediyorsanız, test hedefiniz için modül adını ana hedefle aynı olabileceği için iki kez kontrol edin. No such module <moduleName>Test durumunuzda bir derleme hatası alıyorsanız PRODUCT_MODULE_NAME, test hedefini kontrol etmek isteyebilirsiniz . Harika cevap Diogo.
Chris

48

Gelen Belgeler o Swift hiçbir ithalat ifadeleri olduğunu söyledi.

resim açıklamasını buraya girin

Basitçe kullanın:

let primNumber = PrimeNumberModel()

2
Bu işe yaradı ama sınıfın sonunda görünmesi için Xcode 6.0'ı kapatıp yeniden açmak zorunda kaldım. Projeyi de temizlemeyi ve inşa etmeyi deneyin.
user3344977

Bu, en son XCode 6.3 beta sürümlerinde yeni (veya bir sorun) gibi görünüyor, bu nedenle içe aktarma ifadesi şimdi gerekli. Ayrıca Swift'te modülleri almak için bir içe aktarma ifadesi var.
Augunrik

Sağlanan belgelere göre, "İçe aktarma bildirimi yok" içeren bu tablo "Aynı hedeften içe aktar" durumu ile ilgilidir. Farklı (test) hedef kullandığınız XCTest'lerde, makalenin "Dış Çerçeveleri İçe Aktarma" bölümüne bakın, başka bir tablo daha vardır: Herhangi bir dil çerçevesi -> Swift'e İçe Aktar -> içe aktarma "FrameworkName" gereklidir
Igor Vasilev

Editörde bir sorun görürseniz, genellikle sınıfa dahil olmayan bir test hedefi vardır. Yani muhtemelen çalıştırılabilir para cezanızı inşa edersiniz, ancak hedeflerden herhangi birinde bir sorun varsa, yine de hatayı gösterir. Bu diğer hedeflerden birini seçmiş olsaydınız, derlemenize izin vermezdi.
Joel Teply

34

Test hedefinizde PrimeNumberModel.swift'in hedef üyeliğini kontrol edin.


1
lütfen bunu yorum olarak ekleyin.
4dgaurav

8
Bu kişi yapamaz, bunu yapmak için 9 temsilciye daha ihtiyacı vardır (yazarken).
AlbertEngelB

1
Hedef nedir?
Kullanıcı

Teşekkürler bu benim için çalıştı. Sınıf dosyasını tıklayın. Sağdaki denetçi sütununun ilk sekmesini kontrol edin. İkinci bölüm "Hedef Üyelik" dir. Sınıfı eklemeye çalıştığınız hedefin / ürünün seçili olduğundan emin olun.
Hairgami_Master

1
Bu "nasıl içe aktarılırım ..." sorusuna kesinlikle bir cevap değil, ama beni buraya getiren soruya cevap verdi (Hedefe yeni bir dosya eklemeyi unuttum). Yani ben ve "hızlı çözümlenmemiş tanımlayıcı sınıfının" için ilk google sonucu izleyerek buraya gelecek diğerleri için, bu ise bir cevap (ve bir açıklama).
noamtm

17

Objective-C'de, bir sınıfı başka bir dosyada kullanmak istiyorsanız, içe aktarmanız gerekiyordu:

#import "SomeClass.h"

Ancak Swift'te hiç içe aktarmanıza gerek yok. Zaten içe aktarılmış gibi kullanın.

Misal

// This is a file named SomeClass.swift

class SomeClass : NSObject {

}

// This is a different file, named OtherClass.swift

class OtherClass : NSObject {
    let object = SomeClass()
}

Gördüğünüz gibi, içe aktarmaya gerek yoktu. Bu yardımcı olur umarım.


Teşekkürler! Swift'teki tüm bu yeni şeyleri hala dolaşıyorum.
Felipe

5

Apple'a göre, Aynı Hedef'teki hızlı dosyalar için bir içe aktarmaya ihtiyacınız yoktur. Sonunda hızlı dosyamı hem normal hedefime hem de test hedefime ekleyerek çalıştım. Ardından, normal köprüleme üstbilgimde başvurduğum ObjC dosyalarımın kullanılabilir olduğundan emin olmak için köprüleme başlığını test için kullandım. Şimdi bir cazibe gibi koştu.

import XCTest
//Optionally you can import the whole Objc Module by doing #import ModuleName

class HHASettings_Tests: XCTestCase {

override func setUp() {
    let x : SettingsTableViewController = SettingsTableViewController()

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

}

Bu yüzden PrimeNumberModel'in test Hedefinizin bir hedefine sahip olduğundan emin olun. Veya tüm modülünüzü içe aktarmanın High6 çözümü işe yarayacaktır


Bu yalnızca mantık / model sınıfları için mi çalışıyor yoksa Uygulama Temsilcisi için de kullanabilir miyim?
Nicolas Miari

5

Yapımımı temizleyerek bu sorunu çözebildim.

Üst menü -> Ürün -> Temizle Veya klavye kısayolu: Shift+ Cmd+K


4

Swift 2.0'dan itibaren en iyi uygulama:

Satırı @testable import MyApp, test uygulamanızın üstüne ekleyin; burada "Uygulamam", uygulama hedefinizin Ürün Modülü Adı'dır ( uygulama hedefinizin oluşturma ayarlarında görüntülenebilir). Bu kadar.

(Uygulama hedefinizin adı alt çizgilerle değiştirilecek boşluklar içermiyorsa, ürün modülü adının uygulama hedefinizin adıyla aynı olacağını unutmayın. Örneğin, uygulama hedefime "Eğlence Oyunu" adı verilirse @testable import Fun_Game, testlerimin başında.)


1

Derleyicinin bir giriş noktası olarak başvurması için bir yordam eklemeniz gerekir, bu nedenle bir main.swift dosyası ekleyin; bu durumda test dosyanızın bir örneğini oluşturur:

main.swift

PrimeNumberModelTests()

Sonra komut satırında derleyin (El Capitan ve Swift 2.2 kullanıyorum):

xcrun -sdk macosx swiftc -emit-executable -o PrimeNumberMain PrimeNumberModel.swift PrimeNumberModelTests.swift main.swift

Bu durumda, bir uyarı alırsınız: başlatıcı sonucu kullanılmaz , ancak program derlenir ve yürütülebilir:

./PrimeNumberMain

CAVEAT: Kolaylık sağlamak için içe aktarılan XCTest ve XCTestCase türünü kaldırdım.


1

Kontrol edin PrimeNumberModelTestsHedef Ayarlarınızı .

Derlemede PrimeNumberModel.swiftdosyayı göremiyorsanız Phases/Compile Sourcesekleyin.


Bunu yapmanın doğru yolu bu değil, High6 yanıtını kontrol edin.
Diogo T

0

Yani, ihtiyacın var

  1. Kullanmak istediğiniz harici modülleri içe aktarın
  2. Sınıfta ve kullanmak istediğiniz yöntemlerde doğru erişim değiştiricilerine sahip olduğunuzdan emin olun.

Benim durumumda, birim testi yapmak istediğim hızlı bir dosyam vardı ve birim test dosyası da hızlı bir sınıftı. Erişim değiştiricilerin doğru olduğundan emin oldum, ancak ifade

import stMobile

(diyelim ki stMobile hedef adımız)

hala işe yaramadı (hala 'Böyle bir modül yok' hatası alıyordum), hedefimi kontrol ettim ve adı gerçekten stMobile idi. Bu yüzden, Paketleme altında Yapı Ayarları'na gittim ve Ürün Modülü Adını buldum ve bir nedenle buna St_Mobile denildi, bu yüzden içe aktarma ifademi değiştirdim

import St_Mobile

( Ürün Modülü Adıdır) ) ve her şey işe yaradı.

Özetlemek gerekirse:

  1. Ürün Modülü Adınızı kontrol edin ve birim test sınıfınızda aşağıdaki içe aktarma ifadesini kullanın

    import myProductModuleName
  2. Erişim değiştiricilerinizin doğru olduğundan emin olun (sınıf düzeyi ve yöntemleriniz).


0

Swift derleyicisi, açıkça içe aktarma gerektirmek yerine, dolaylı olarak .swiftmodule Swift kütüphanelerinin bağımlılık dosyalarını .

Xcode sizin için hızlı modüller oluşturabilir veya komut satırı talimatları için railsware bloguna bakın swiftc.


0

@ High6 tarafından verilen cevapta @ high6 ve @ erik-p-hansen'in işaret ettiği gibi, bu basit bir projede muhtemelen projenizle aynı isim olan PrimeNumberModel sınıfının bulunduğu modülün hedefinin içe aktarılmasıyla aşılabilir. .

Buna bakarken, Clayton'daki ilk Birim Testini Swift'teki Swift McIlrath tarafından swiftcast.tv'ye yaz. Erişim değiştiricileri tartışır, karşılaştığınız aynı sorunun bir örneğini gösterir (ancak bir model dosyası yerine bir ViewController için) ve hedef dosyayı hedefe ekleyerek hem hedefi nasıl içe aktaracağınızı hem de erişim değiştirici sorununu nasıl çözeceğinizi gösterir. gerçekten yapmak istemediğiniz sürece, test etmeye çalıştığınız sınıfı herkese açık hale getirmek zorunda değilsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.