Unit Test vs Integration Test
La base de la stratégie de test iOS : les tests unitaires qui isolent chaque composant, ou les tests d'intégration qui valident les interactions entre eux ? Comment construire correctement sa pyramide de tests ?
La nouvelle bibliothèque de test open source d'Apple — basée sur les macros, intégrée nativement à Swift Concurrency
Framework éprouvé au combat depuis ~13 ans — la seule référence pour les tests UI et de performance
La tendance est claire, mais une « migration en bloc » reste un risque inutile. Écrivez vos nouveaux tests unitaires et d'intégration avec Swift Testing — moins de code, capture automatique des valeurs, tests paramétrés intégrés et parallélisme par défaut. Laissez les tests UI et de performance dans XCTest ; c'est ce que recommande la documentation Apple. Les deux frameworks pouvant cohabiter dans la même cible et Swift 6.4 apportant un rapport croisé des échecs, une migration en bloc n'est pas nécessaire — avancez fichier par fichier.
| Catégorie | Swift Testing | XCTest |
|---|---|---|
| Performance | 8/10 | 8/10 |
| Facilité d'apprentissage | 7/10 | 6/10 |
| Écosystème | 6/10 | 8/10 |
| Communauté | 6/10 | 8/10 |
| Marché de l'emploi | 5/10 | 7/10 |
| Pérennité | 9/10 | 6/10 |
// Swift Testing — test unitaire asynchrone paramétré
import Testing
@testable import PaymentKit
@Suite("Calcul du prix")
struct PriceCalculatorTests {
@Test("La remise est correctement calculée avec des codes promo valides",
arguments: [
("SAVE10", 100.0, 90.0),
("SAVE20", 100.0, 80.0),
("NONE", 100.0, 100.0)
])
func discountIsApplied(code: String, base: Double, expected: Double) async throws {
let calculator = PriceCalculator()
let result = try await calculator.applyDiscount(code: code, to: base)
#expect(result == expected, "pour \(code), attendu \(expected), obtenu \(result)")
}
@Test("Un code promo invalide lève une erreur")
func invalidCouponThrows() async throws {
let calculator = PriceCalculator()
await #expect(throws: CouponError.invalid) {
try await calculator.applyDiscount(code: "XXX", to: 100.0)
}
}
@Test("Le total du panier est requis", .disabled("Le service de panier n'est pas encore migré"))
func cartTotalRequired() async throws {
let calculator = PriceCalculator()
try #require(calculator.cartTotal > 0)
}
}// XCTest — même scénario (calcul de prix) + test UI
import XCTest
@testable import PaymentKit
final class PriceCalculatorTests: XCTestCase {
var calculator: PriceCalculator!
override func setUpWithError() throws {
calculator = PriceCalculator()
}
func testDiscountIsAppliedForKnownCoupons() async throws {
let cases: [(String, Double, Double)] = [
("SAVE10", 100.0, 90.0),
("SAVE20", 100.0, 80.0),
("NONE", 100.0, 100.0)
]
for (code, base, expected) in cases {
let result = try await calculator.applyDiscount(code: code, to: base)
XCTAssertEqual(result, expected, "code promo : \(code)")
}
}
// XCTAssertThrowsError est synchrone ; utiliser do/catch + XCTFail dans un appel async
func testInvalidCouponThrows() async throws {
do {
_ = try await calculator.applyDiscount(code: "XXX", to: 100.0)
XCTFail("une erreur était attendue")
} catch {
XCTAssertEqual(error as? CouponError, .invalid)
}
}
}
// Test UI — possible uniquement avec XCTest/XCUITest
final class CheckoutUITests: XCTestCase {
func testApplyCouponButtonUpdatesTotal() throws {
let app = XCUIApplication()
app.launch()
app.textFields["couponField"].tap()
app.textFields["couponField"].typeText("SAVE10")
app.buttons["applyCouponButton"].tap()
XCTAssertEqual(app.staticTexts["totalLabel"].label, "$90.00")
}
}La tendance est claire, mais une « migration en bloc » reste un risque inutile. Écrivez vos nouveaux tests unitaires et d'intégration avec Swift Testing — moins de code, capture automatique des valeurs, tests paramétrés intégrés et parallélisme par défaut. Laissez les tests UI et de performance dans XCTest ; c'est ce que recommande la documentation Apple. Les deux frameworks pouvant cohabiter dans la même cible et Swift 6.4 apportant un rapport croisé des échecs, une migration en bloc n'est pas nécessaire — avancez fichier par fichier.
Obtenir une consultation gratuiteNon. Swift Testing est désormais le choix par défaut recommandé par Apple pour les nouveaux tests unitaires et d'intégration, mais XCTest n'a pas été retiré ; XCUITest (automatisation UI) et XCTMetric (tests de performance) restent exclusifs à XCTest. Les deux peuvent cohabiter dans la même cible, avec un rapport croisé des échecs depuis Swift 6.4.