কেন ইউনিট পরীক্ষার অভ্যন্তরীণ কোডগুলি বান্ডিল সংস্থানগুলি খুঁজে পাবে না?


183

কিছু ইউনিট আমি ইউনিট পরীক্ষার জন্য একটি সংস্থান ফাইল লোড করা প্রয়োজন। এটিতে নিম্নলিখিত লাইনটি রয়েছে:

NSString *path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"txt"];

অ্যাপ্লিকেশনে এটি ঠিক সূক্ষ্মভাবে চালিত হয়, তবে ইউনিট দ্বারা চালিত হলে কাঠামোটি pathForResource:শূন্য করে দেয়, যার অর্থ এটি সনাক্ত করতে পারে না foo.txt

আমি নিশ্চিত করেছি যে ইউনিট পরীক্ষার টার্গেটের কপি বান্ডিল রিসোর্সস বিল্ড ফেজের foo.txtঅন্তর্ভুক্ত রয়েছে , সুতরাং এটি ফাইলটি কেন খুঁজে পাবে না?

উত্তর:


316

ইউনিট পরীক্ষা সাজ আপনার কোড রান করেন তখন আপনার ইউনিট পরীক্ষা বান্ডিল না প্রধান বান্ডিল।

যদিও আপনি পরীক্ষা চালাচ্ছেন, আপনার অ্যাপ্লিকেশন নয়, আপনার অ্যাপ্লিকেশন বান্ডিলটি এখনও মূল বান্ডিল। (সম্ভবতঃ, এটি ভুল বান্ডেলটি অনুসন্ধান করা কোডটি আটকাচ্ছে)) সুতরাং, আপনি ইউনিট পরীক্ষার বান্ডেলে কোনও সংস্থান ফাইল যুক্ত করলে মূল বান্ডেলটি অনুসন্ধান করলে এটি খুঁজে পাবেন না। আপনি যদি উপরের লাইনটি এর সাথে প্রতিস্থাপন করেন:

NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"foo" ofType:@"txt"];

তারপরে আপনার কোডটি আপনার ইউনিট পরীক্ষার শ্রেণিতে যে বান্ডিলটি রয়েছে তা অনুসন্ধান করবে এবং সবকিছু ঠিক থাকবে।


আমার জন্য কাজ করে না। এখনও বিল্ড বান্ডেল নয় পরীক্ষার বান্ডিল।
ক্রিস

1
@ ক্রিস নমুনা লাইনে আমি ধরে নিচ্ছি যে selfপরীক্ষার কেস ক্লাস নয়, মূল বান্ডেলের একটি শ্রেণিকে বোঝায়। [self class]আপনার মূল বান্ডিলের যে কোনও শ্রেণীর সাথে প্রতিস্থাপন করুন । আমি আমার উদাহরণ সম্পাদনা করব।
বেনজাদো

@ বেনজাদো বান্ডিলটি এখনও একই (বিল্ড), যা সঠিক বলে আমি মনে করি। কারণ যখন আমি স্ব বা অ্যাপডেলিগেট ব্যবহার করছি তখন দুটিই মূল বান্ডলে অবস্থিত। যখন আমি প্রধান টার্গেটের বিল্ড পর্যায়গুলি পরীক্ষা করি তখন উভয় ফাইলই থাকে But আমার যে কোডটি বান্ডিল দরকার তা মূল বান্ডেলে রয়েছে। আমার নিম্নলিখিত সমস্যা আছে। আমি একটি পিএনজি ফাইল লোড করছি। ব্যবহারকারী কোনও সার্ভার থেকে ডাউনলোড করার কারণে সাধারণত এই ফাইলটি মূল বান্ডলে থাকে না। তবে একটি পরীক্ষার জন্য আমি পরীক্ষার বান্ডিল থেকে কোনও ফাইল মুখ্য বান্ডলে অনুলিপি না করেই ব্যবহার করতে চাই।
ক্রিস

2
@ ক্রিস আমি আমার আগের সম্পাদনাটি দিয়ে একটি ভুল করেছি, এবং উত্তরটি আবার সম্পাদনা করেছি। পরীক্ষার সময়, অ্যাপ্লিকেশন বান্ডিলটি এখনও মূল বান্ডিল। আপনি যদি ইউনিট পরীক্ষার বান্ডেলে থাকা কোনও রিসোর্স ফাইল লোড করতে চান তবে আপনাকে ইউনিট পরীক্ষার বান্ডেলের bundleForClass:একটি শ্রেণীর সাথে ব্যবহার করতে হবে । আপনার ইউনিট পরীক্ষার কোডে আপনার ফাইলের পাথ পাওয়া উচিত, তারপরে আপনার অন্য কোডের সাথে পাথ স্ট্রিংটি পাস করুন।
বেনজাদো

এটি কাজ করে তবে আমি কীভাবে রান-ডিপ্লয় এবং পরীক্ষা-স্থাপনার মধ্যে পার্থক্য করতে পারি? সত্য যদি এটি পরীক্ষা হয় তবে তার ভিত্তিতে আমার মূল বান্ডেলের একটি ক্লাসে পরীক্ষার বান্ডেল থেকে একটি সংস্থান দরকার। এটি যদি নিয়মিত 'রান' হয় তবে আমার পরীক্ষার বান্ডিল নয়, মূল বান্ডেল থেকে একটি সংস্থান দরকার। কোন ধারণা?
ক্রিস

78

একটি দ্রুত পরিবর্তন:

সুইফট 2

let testBundle = NSBundle(forClass: self.dynamicType)
let fileURL = testBundle.URLForResource("imageName", withExtension: "png")
XCTAssertNotNil(fileURL)

সুইফট 3, সুইফট 4

let testBundle = Bundle(for: type(of: self))
let filePath = testBundle.path(forResource: "imageName", ofType: "png")
XCTAssertNotNil(filePath)

বান্ডেলটি আপনার কনফিগারেশনের জন্য প্রধান এবং পরীক্ষার পথগুলি আবিষ্কার করার উপায় সরবরাহ করে:

@testable import Example

class ExampleTests: XCTestCase {

    func testExample() {
        let bundleMain = Bundle.main
        let bundleDoingTest = Bundle(for: type(of: self ))
        let bundleBeingTested = Bundle(identifier: "com.example.Example")!

        print("bundleMain.bundlePath : \(bundleMain.bundlePath)")
        // …/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents
        print("bundleDoingTest.bundlePath : \(bundleDoingTest.bundlePath)")
        // …/PATH/TO/Debug/ExampleTests.xctest
        print("bundleBeingTested.bundlePath : \(bundleBeingTested.bundlePath)")
        // …/PATH/TO/Debug/Example.app

        print("bundleMain = " + bundleMain.description) // Xcode Test Agent
        print("bundleDoingTest = " + bundleDoingTest.description) // Test Case Bundle
        print("bundleUnderTest = " + bundleBeingTested.description) // App Bundle

এক্সকোড 6 | 7 | 8 | 9 এ, ইউনিট-পরীক্ষার বান্ডিল পথটিDeveloper/Xcode/DerivedData এমন কিছু হবে ...

/Users/
  UserName/
    Library/
      Developer/
        Xcode/
          DerivedData/
            App-qwertyuiop.../
              Build/
                Products/
                  Debug-iphonesimulator/
                    AppTests.xctest/
                      foo.txt

... যা Developer/CoreSimulator/Devices নিয়মিত (নন-ইউনিট-পরীক্ষা) বান্ডিল পথ থেকে পৃথক :

/Users/
  UserName/
    Library/
    Developer/
      CoreSimulator/
        Devices/
          _UUID_/
            data/
              Containers/
                Bundle/
                  Application/
                    _UUID_/
                      App.app/

এছাড়াও নোট করুন ইউনিট পরীক্ষাটি এক্সিকিউটেবল, ডিফল্টরূপে, অ্যাপ্লিকেশন কোডের সাথে যুক্ত। তবে, ইউনিট পরীক্ষা কোডের কেবলমাত্র পরীক্ষার বান্ডেলে লক্ষ্যমাত্রার সদস্যতা থাকা উচিত। অ্যাপ্লিকেশন কোডটিতে কেবলমাত্র অ্যাপ্লিকেশন বান্ডলে টার্গেট সদস্যতা থাকা উচিত। রানটাইমের সময়, ইউনিট পরীক্ষার টার্গেট বান্ডিলটি প্রয়োগের জন্য অ্যাপ্লিকেশন বান্ডেলে ইনজেক্ট করা হয়

সুইফট প্যাকেজ ম্যানেজার (এসপিএম) 4:

let testBundle = Bundle(for: type(of: self)) 
print("testBundle.bundlePath = \(testBundle.bundlePath) ")

দ্রষ্টব্য: ডিফল্টরূপে, কমান্ড লাইন swift testএকটি MyProjectPackageTests.xctestপরীক্ষার বান্ডিল তৈরি করবে । এবং, পরীক্ষার বান্ডেল swift package generate-xcodeprojতৈরি করবে MyProjectTests.xctest। এই বিভিন্ন পরীক্ষার বান্ডিলগুলির বিভিন্ন পথ রয়েছেএছাড়াও, বিভিন্ন পরীক্ষার বান্ডেলে কিছু অভ্যন্তরীণ ডিরেক্টরি কাঠামো এবং সামগ্রীর পার্থক্য থাকতে পারে

উভয় ক্ষেত্রেই, .bundlePathএবং .bundleURLবর্তমানে ম্যাকোএসে চালিত পরীক্ষার বান্ডিলের পথে ফিরে আসবে। তবে Bundleবর্তমানে উবুন্টু লিনাক্সের জন্য প্রয়োগ করা হয়নি।

এছাড়াও, কমান্ড লাইন swift buildএবং swift testবর্তমানে সংস্থানগুলি অনুলিপি করার জন্য কোনও ব্যবস্থা সরবরাহ করে না।

তবে কিছু চেষ্টা করে ম্যাকস এক্সকোড, ম্যাকোস কমান্ড লাইন এবং উবুন্টু কমান্ড লাইন পরিবেশে সংস্থান সহ সুইফট প্যাকেজ ম্যানেজার ব্যবহারের জন্য প্রক্রিয়াগুলি স্থাপন করা সম্ভব। একটি উদাহরণ এখানে পাওয়া যাবে: 004.4'2 রিসোর্স Qref সহ এসডাব্লু দেব সুইফট প্যাকেজ ম্যানেজার (এসপিএম)

আরও দেখুন: সুইফট প্যাকেজ ম্যানেজারের সাথে ইউনিট পরীক্ষায় সংস্থানগুলি ব্যবহার করুন

সুইফট প্যাকেজ ম্যানেজার (এসপিএম) 4.2

সুইফ্ট প্যাকেজ ম্যানেজার প্যাকেজডেস্ক্রিপশন ৪.২ স্থানীয় নির্ভরতাগুলির সমর্থন সরবরাহ করে ।

স্থানীয় নির্ভরতা হ'ল ডিস্কের প্যাকেজগুলি যা তাদের পাথ ব্যবহার করে সরাসরি উল্লেখ করা যেতে পারে। স্থানীয় নির্ভরতা কেবল রুট প্যাকেজে অনুমোদিত হয় এবং তারা প্যাকেজ গ্রাফের একই নামের সাথে সমস্ত নির্ভরতা ওভাররাইড করে।

দ্রষ্টব্য: আমি প্রত্যাশা করি, তবে এখনও পরীক্ষা করে দেখিনি, এসপিএম ৪.২ এর মাধ্যমে নিম্নলিখিতগুলির মতো কিছু হওয়া সম্ভব:

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "MyPackageTestResources",
    dependencies: [
        .package(path: "../test-resources"),
    ],
    targets: [
        // ...
        .testTarget(
            name: "MyPackageTests",
            dependencies: ["MyPackage", "MyPackageTestResources"]
        ),
    ]
)

1
সুইফট 4 এর পাশাপাশি, আপনি বান্ডিলটি ব্যবহার করতে পারেন (এর জন্য: টাইপ (এর: স্ব))
রকেট গার্ডেন

14

সুইফট সুইফট 3 এর সাথে সিনট্যাক্সটিকে self.dynamicTypeঅবজ্ঞা করা হয়েছে, পরিবর্তে এটি ব্যবহার করুন

let testBundle = Bundle(for: type(of: self))
let fooTxtPath = testBundle.path(forResource: "foo", ofType: "txt")

অথবা

let fooTxtURL = testBundle.url(forResource: "foo", withExtension: "txt")

4

নিশ্চিত করুন যে পরীক্ষার লক্ষ্যে সংস্থানটি যুক্ত হয়েছে।

এখানে চিত্র বর্ণনা লিখুন


2
পরীক্ষার বান্ডেলে রিসোর্স যুক্ত করা পরীক্ষার ফলাফলগুলি বেশিরভাগ অবৈধ করে তোলে। সর্বোপরি, কোনও সংস্থান সহজেই পরীক্ষার টার্গেটে থাকতে পারে তবে অ্যাপ্লিকেশন টার্গেটে নয়, এবং আপনার পরীক্ষাগুলি সমস্ত পাস হয়ে যায় তবে অ্যাপটি শিখায় ফেটে যায়।
dgatwood

1

আপনার প্রকল্পে যদি আপনার একাধিক লক্ষ্য থাকে তবে আপনার লক্ষ্যমাত্রার সদস্যপদে প্রাপ্ত বিভিন্ন লক্ষ্যমাত্রার মধ্যে সংস্থান স্থাপন করতে হবে এবং নীচের চিত্রটিতে প্রদর্শিত তিনটি ধাপ হিসাবে আপনাকে বিভিন্ন লক্ষ্যমাত্রার মধ্যে স্যুইচ করতে হবে

এখানে চিত্র বর্ণনা লিখুন


0

আমাকে নিশ্চিত করতে হয়েছিল যে এই সাধারণ পরীক্ষার চেকবক্সটি সেট করা হয়েছিল এই সাধারণ পরীক্ষার চেকবাক্স সেট করা হয়েছিল

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.