Server-side Swift: Testing Code That Uses Bundle

219 views Asked by At

I'm using server-side Swift, and doing my development in Xcode after doing:

swift package generate-xcodeproj

I have a class that uses Bundle (formerly NSBundle) to load in a .plist file for some settings in the server. It works fine when running in the server itself, but when I create some unit tests for this class, I cannot get access to the directory where the .plist file is located. The relevant snippet of code is:

let bundlePath = Bundle.main.bundlePath as NSString
let plistPath = bundlePath.appendingPathComponent("Test.plist")
plistDict = NSDictionary(contentsOfFile: plistPath)

When I run this in unit XCTests, plistPath is:

/Applications/Xcode-8.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/Test.plist

which is not very useful.

One thing that I've noticed is that there are no options for "Host Application:" under the General tab.

Thoughts?

1

There are 1 answers

0
Chris Prince On

I've not been able to fully answer this, but came up with a work-around for my situation. I'm using the Perfect File class (see https://github.com/PerfectlySoft/Perfect.git), and just dynamically creating the file I need for my XCTest cases in the setUp() method. Fortunately, I have fairly simple needs for file contents. Here's the initial part of my XCTest file:

import XCTest
import SMServerLib
import PerfectLib

class TestPlistDictLoader: XCTestCase {
    var plistFileName:String! = "TestPlistDictLoader.plist"
    var pathName:String! = "/tmp"

    override func setUp() {
        super.setUp()
        // A bit of a hack, but I can't figure out a way otherwise to access the install directory where the code is running.
        // See also http://stackoverflow.com/questions/41340114/server-side-swift-testing-code-that-uses-bundle
        // The only downside is that these tests don't test the `init(plistFileNameInBundle filename:String)` constructor that uses the Bundle.
        // Write the .plist file to a known location. Use only pure Swift methods.

        let plistPath = (pathName as NSString).appendingPathComponent(plistFileName)
        let plist = File(plistPath)
        try! plist.open(.write)
        try! plist.write(string: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
            "<plist version=\"1.0\">\n" +
            "<dict>\n" +
                "<key>MyString</key>\n" +
                "<string>Hello World!</string>\n" +
                "<key>MyInteger</key>\n" +
                "<integer>100</integer>\n" +
            "</dict>\n" +
            "</plist>\n"
        )

        plist.close()
    }

See https://github.com/crspybits/SMServerLib for the full context.