J'ai quelques tests unitaires dans lesquels j'aimerais tester si un rappel est appelé dans la file d'attente de répartition correcte.
Dans Swift 2, j'ai comparé le libellé de la file d'attente actuelle à ma file d'attente de test. Cependant dans Swift 3 le DISPATCH_CURRENT_QUEUE_LABEL
la constante n'existe plus.
J'ai trouvé le dispatch_assert_queue
fonction. Ce qui semble être ce dont j'ai besoin, mais je ne sais pas comment l'appeler.
Mon Swift 2:
let testQueueLabel = "com.example.my-test-queue"
let testQueue = dispatch_queue_create(testQueueLabel, nil)
let currentQueueLabel = String(UTF8String: dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))!
XCTAssertEqual(currentQueueLabel, testQueueLabel, "callback should be called on specified queue")
Mise à jour:
Je suis confus par le manque de saisie semi-automatique, mais il est possible d'utiliser __dispatch_assert_queue
:
if #available(iOS 10.0, *) {
__dispatch_assert_queue(test1Queue)
}
Bien que cela fonctionne pour les tests unitaires, il arrête de manière agaçante l'ensemble du processus avec un EXC_BAD_INSTRUCTION
au lieu d'échouer uniquement à un test.
Répondre à ma propre question:
Basé sur commentaires de KFDoom , j'utilise maintenant setSpecific
et getSpecific
.
Cela crée une clé, la place dans la file d'attente de test, puis la récupère à nouveau:
let testQueueLabel = "com.example.my-test-queue"
let testQueue = DispatchQueue(label: testQueueLabel, attributes: [])
let testQueueKey = DispatchSpecificKey<Void>()
testQueue.setSpecific(key: testQueueKey, value: ())
// ... later on, to test:
XCTAssertNotNil(DispatchQueue.getSpecific(key: testQueueKey), "callback should be called on specified queue")
Notez qu'il n'y a pas de valeur associée à la clé (son type est Void
), je ne suis intéressé que par l'existence du spécifique, pas par sa valeur.
Important!
Assurez-vous de conserver une référence à la clé ou de nettoyer après avoir fini de l'utiliser. Sinon, une clé nouvellement créée pourrait utiliser la même adresse mémoire, conduisant à un comportement étrange. Voir: http://tom.lokhorst.eu/2018/02/leaky-abstractions-in-Swift-with-dispatchqueue
Utilisez dispatchPrecondition(.onQueue(expectedQueue))
, le Swift 3 remplacement de l'API pour le dispatch_assert_queue()
C API.
Cela a été couvert lors de la session GCD de la WWDC de cette année: https://developer.Apple.com/videos/play/wwdc2016/720/
Tests basés sur réponse de KFDoom :
import XCTest
import Dispatch
class TestQueue: XCTestCase {
func testWithSpecificKey() {
let queue = DispatchQueue(label: "label")
let key = DispatchSpecificKey<Void>()
queue.setSpecific(key:key, value:())
let expectation1 = expectation(withDescription: "main")
let expectation2 = expectation(withDescription: "queue")
DispatchQueue.main.async {
if (DispatchQueue.getSpecific(key: key) == nil) {
expectation1.fulfill()
}
}
queue.async {
if (DispatchQueue.getSpecific(key: key) != nil) {
expectation2.fulfill()
}
}
waitForExpectations(withTimeout: 1, handler: nil)
}
func testWithPrecondition() {
let queue = DispatchQueue(label: "label")
let expectation1 = expectation(withDescription: "main")
let expectation2 = expectation(withDescription: "queue")
DispatchQueue.main.async {
dispatchPrecondition(condition: .notOnQueue(queue))
expectation1.fulfill()
}
queue.async {
dispatchPrecondition(condition: .onQueue(queue))
expectation2.fulfill()
}
waitForExpectations(withTimeout: 1, handler: nil)
}
}
Une option consiste à définir une condition préalable pour tester directement la file d'attente ou définir "spécifique" dessus et la récupérer plus tard. De plus, on pourrait utiliser setSpecific et getSpecific. Alternativement, vous pouvez utiliser une vérification des conditions préalables si vous êtes dans une file d'attente, ce qui devrait répondre au besoin de "se mettre à jour". src: https://github.com/duemunk/Async/blob/feature/Swift_3.0/AsyncTest/AsyncTests.Swift
et
https://github.com/Apple/Swift/blob/master/stdlib/public/SDK/Dispatch/Dispatch.Swift