2016-01-22 32 views
0

根據是否運行Xcode UI測試,我如何定義全局變量?我試圖做到這一點:根據是否運行Xcode UI測試來定義全局變量

#if UITESTS 
    let api = StubbedAPI() 
#else 
    let api = RealAPI() 
#endif 

這些都是全局變量,所以我不能在文件範圍內來電或NSProcessInfo.processInfo().environmentNSProcessInfo.processInfo().arguments

回答

5

UI測試目標作爲與您的應用程序分開的過程運行。這意味着您不能在測試目標中設置預處理器宏,並期望應用程序知道它們。測試可以與應用程序通信的唯一方法是通過您提到的兩個processInfo設置。

使用這些是動態的,而您提出的解決方案是靜態的。但是,仍然有可能通過蘋果給我們提供的工具來做你正在嘗試做的事情。

首先,創建StubbedAPI和RealAPI都符合的協議。

protocol API { 
    // ... // 
} 

class RealAPI: API { 
    // ... // 
} 

class StubbedAPI: API { 
    // ... // 
} 

接下來,創建一個配置類。這將用於告訴你的代碼在運行時使用哪個API。

struct Config { 
    var api: APIProtocol { 
     get { 
      return UITesting() ? RealAPI() : StubbedAPI() 
     } 
    } 
} 

private func UITesting() -> Bool { 
    return NSProcessInfo.processInfo().arguments.contains("UI-TESTING") 
} 

然後,通過配置檢索對API實現的引用。

class FooService { 
    private let api = Config().api; 
} 

最後,在UI Testing下啓動應用程序之前設置processInfo參數。

class UITests: TestCase { 
    let app = XCUIApplication() 

    override func setUp() { 
     super.setUp() 
     app.launchArguments = ["UI-TESTING"] 
     app.launch() 
    } 
} 

api屬性將生產運行的代碼和存根之一的,UI測試時設置爲真正的API。

這種方法有一些缺點。首先,您要向生產代碼引入實際的「殘留」API。這有一個實際在生產中使用它的開發者的潛在缺點。其次,你需要創建API協議,只有一個「真實」的對象實現它。不幸的是,鑑於UI測試和Swift的當前狀態,這是我提出的最佳解決方案。