مقدمة: لماذا يجب اختبار تطبيقات Swift؟
تطوير تطبيق iOS أو macOS عالي الجودة لا يمكن أن يتم دون اختبار دقيق. في نظام Swift البيئي، يوجد إطار عمل قوي XCTest يسمح بكتابة جميع مستويات الاختبارات الثلاثة: الاختبارات الوحدوية (unit)، اختبارات التكامل (integration)، والاختبارات الشاملة (E2E). كل مستوى من هذه المستويات مسؤول عن مجاله الخاص ويساعد في اكتشاف الأخطاء في مراحل مختلفة من التطوير.
في هذه المقالة، سنشرح كيفية إعداد وكتابة الاختبارات لتطبيقات Swift باستخدام الممارسات والأدوات الحديثة. ستتعرف على الفروق بين أنواع الاختبارات المختلفة، وستحصل على أمثلة جاهزة للكود يمكن تطبيقها فوراً في مشروعك.
الاختبارات الوحدوية (Unit Testing) في Swift
الاختبارات الوحدوية هي أساس هرم الاختبارات. تتحقق من عمل المكونات الفردية (الطرق، الكلاسات، الهياكل) بشكل معزول عن التبعيات الخارجية.
إعداد الاختبارات الوحدوية في Xcode
لإنشاء هدف اختبار في Xcode، عند إنشاء المشروع يكفي تحديد علامة "Include Tests". إذا كان المشروع موجوداً بالفعل، أضف هدفاً جديداً: File → New → Target → iOS Unit Testing Bundle.
مثال أساسي لاختبار وحدوي
لننظر إلى مثال بسيط لاختبار آلة حاسبة:
import XCTest
final class CalculatorTests: XCTestCase { var calculator: Calculator! override func setUpWithError() throws { calculator = Calculator() } override func tearDownWithError() throws { calculator = nil } func testAddition() { // Given let a = 5 let b = 3 // When let result = calculator.add(a, b) // Then XCTAssertEqual(result, 8, "5 + 3 يجب أن يساوي 8") } func testDivisionByZero() { XCTAssertThrowsError(try calculator.divide(10, 0)) { error in XCTAssertEqual(error as? CalculatorError, CalculatorError.divisionByZero) } }}أفضل الممارسات للاختبارات الوحدوية
- العزل: يجب أن يكون كل اختبار مستقلاً. استخدم
setUpWithErrorوtearDownWithErrorللتحضير والتنظيف. - نمط AAA: Arrange (التحضير)، Act (الإجراء)، Assert (التحقق).
- فحص واحد لكل اختبار: الاختبار المثالي يتحقق من سلوك واحد فقط.
- التسمية: استخدم أسماء وصفية:
testMethodName_WhenCondition_ExpectedResult.
اختبارات التكامل (Integration Testing) في Swift
تتحقق اختبارات التكامل من التفاعل بين المكونات: العمل مع قاعدة البيانات، طلبات الشبكة، نظام الملفات. على عكس الاختبارات الوحدوية، هنا لا نقوم بعمل Mock لكل شيء، بل نختبر التفاعلات الحقيقية.
اختبار Core Data
مثال لاختبار العمل مع Core Data:
import XCTest@testable import MyApp
final class CoreDataIntegrationTests: XCTestCase { var coreDataStack: CoreDataStack! override func setUpWithError() throws { coreDataStack = CoreDataStack(inMemory: true) // نستخدم تخزينًا في الذاكرة } func testSaveAndFetchUser() { // Arrange let user = User(context: coreDataStack.viewContext) user.name = "إيفان" user.age = 30 // Act try? coreDataStack.viewContext.save() let fetchRequest: NSFetchRequest<User> = User.fetchRequest() let users = try? coreDataStack.viewContext.fetch(fetchRequest) // Assert XCTAssertEqual(users?.count, 1) XCTAssertEqual(users?.first?.name, "إيفان") }}اختبار طبقة الشبكة
لاختبارات تكامل الشبكة، استخدم