How do I use XCGLogger in a test target in swift 3?

483 Views Asked by At

I have been using XCGLogger for a while now, but after converting my app to swift 3.0, I am having issues with it in my test target.

I have the following as part of my AppDelegate class file. This creates a global variable log which I can use anywhere in my app by just calling log?.info("foo") for example.

Prior to moving to swift 3 this worked in test target as well, but now I get a link error if I try to use log?.info("foo") in my test target.

AppDelegate code

import XCGLogger

// USE_XCGLOGGER is set for debug but not for release

#if USE_XCGLOGGER
let log: XCGLogger? = {
  // Setup XCGLogger
  let log = XCGLogger.default      
  return log
}()
#else
let log: XCGLogger? = nil
#endif

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
 ...
}

Class in test target

import XCTest
@testable import OurLatitude

class ApiAccessTests: XCTestCase {

    override func tearDown() {
        super.tearDown()
        log?.info("foo")
    }

}

Link errors

undefined symbols for architecture x86_64:
  "XCGLogger.XCGLogger.(info (@autoclosure () -> Any?, functionName : Swift.StaticString, fileName : Swift.StaticString, lineNumber : Swift.Int, userInfo : [Swift.String : Any]) -> ()).(default argument 4)", referenced from:
      OurLatitudeTests.ApiAccessTests.tearDown () -> () in ApiAccessTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
1

There are 1 best solutions below

0
On

I use Carthage and my unit test settings are Host Application : None .

I figured, framework was not added to unit test target and I was right. So I've added XCGLogger.framework from carthage folder to Link Binary with Libraries in Build Phase. Then I have also added framework to the run script

enter image description here

This solved the error I was getting and I started to get a new error

Ambiguous reference to member 'log'

Then creating a one time class to init XCGLogger solved it

I have created a pull request here , hopefully he will merge it....

https://github.com/DaveWoodCom/XCGLogger/pull/188/files

Using with Unit Tests. [after Carthage or Manual framework install]

Make sure your XCGLogger.framework is added to your Unit Test Target's Build Phases -> Link Binary With Libraries.

I've also added a run script to make sure framework is copied from Carthage folder.

If your unit test's host application is set to None and your app's classes are using XCGLogger you will see an error like

Ambiguous reference to member 'log' This is happening because XCTest is runnning your unit tests one by one and it doesnt access to your XCGLogger constructor in your AppDelegate file. So your one time init doesn't exist and it is failinf to find the correct references.

To solve this you will need a one time init method that will construct your XCGLogger

Create a new class in your test target, make sure it is named TestSetup

import XCGLogger

let log: XCGLogger = {
    // Setup XCGLogger
    let log = XCGLogger.default

    return log
}()


class TestSetup: NSObject {
    override init() {

    }
}

then go to your test targets info settings and add a new row Principal class and Value will be YourTestTargetName.TestSetup , for detail read go to How to run one-time setup code before executing any XCTest

This should do the trick....