我正在尝试使用Quick和Nimble学习测试,我编写了简单的单例和一些测试
的Singleton:
public class LocationManager : NSObject {
// Singleton
public class var sharedInstance : LocationManager {
struct Static {
static var instance : LocationManager?
static var token : dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = LocationManager()
}
return Static.instance!
}
}
我的测试:
class LocationManagerSpec: QuickSpec {
override func spec() {
describe("Location manager") {
let locationManager = LocationManager.sharedInstance
context("initialized") {
it("is not nil") {
expect(locationManager).notTo(beNil())
}
it("is unique") {
let tempLocationManager = LocationManager()
expect(locationManager).notTo(equal(tempLocationManager))
}
it("and shared instances are same") {
let tempLocationManager = LocationManager.sharedInstance
expect(locationManager).to(equal(tempLocationManager))
}
}
}
}
}
如何测试我的单例是否是线程安全的?
答案 0 :(得分:0)
为了测试你的Singleton是线程安全的我做了一点样本。您可以在Github repo基本上找到所有代码:
我发现了几个问题(使用Xcode 6.2 ergo Swift 1.1),甚至编译器崩溃。因此,在this accepted SO answer之后,我改变了您的Singleton实现,避免了GCD的经典使用。你需要管理这些指针和不安全的可变指针,我因此而崩溃了
所以你的Singleton课程现在是:
import Foundation
public class LocationManager: NSObject {
public class var sharedInstance: LocationManager {
struct Static {
static let instance: LocationManager = LocationManager()
}
return Static.instance
}
}
要测试它,你需要等到所有线程都完成。当测试运行器在MainThread上运行时,您需要使用期望
describe("Accesing Location manager from multiple concurrent threads") {
context("When created") {
it("should return always the same object for every of these 500 threads") {
var allSingletons = Array<LocationManager>()
for i in 1...10 {
println("Launching thread \(i)")
dispatch_async(self.globalBackgroundQueue) {
allSingletons.append(LocationManager.sharedInstance)
}
}
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
}
}
}
重要的是这一部分:
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
这里我只是调用一个函数来确定每个存储的对象是否与传递的Singleton相同,并给出10秒超时
整个测试类:
import Quick
import Nimble
import QuickNimbleExample
class LocationManagerSpec: QuickSpec {
var globalBackgroundQueue: dispatch_queue_t {
return dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0)
}
func allSingletonsEqual(#inArray: Array<LocationManager>, singleton: LocationManager) -> Bool {
for loc in inArray {
if loc != singleton {
return false
}
}
return true
}
override func spec() {
describe("Accesing Location manager from multiple concurrent threads") {
context("When created") {
it("should return always the same object for every of these 500 threads") {
var allSingletons = Array<LocationManager>()
for i in 1...10 {
println("Launching thread \(i)")
dispatch_async(self.globalBackgroundQueue) {
allSingletons.append(LocationManager.sharedInstance)
}
}
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
}
}
}
}
}