اختبار في Kotlin: مراجعة شاملة للأطر والأدوات
Kotlin — لغة تكتسب شعبية متسارعة في تطوير الواجهات الخلفية (Spring Boot، Ktor) و Android. ومع ذلك، فإن اللغة القوية تتطلب أدوات اختبار مناسبة. في هذه المقالة، سنستعرض الأطر والمكتبات الرئيسية لاختبار تطبيقات Kotlin: من JUnit5 الكلاسيكي إلى Kotest و MockK الحديثين. ستكون المادة مفيدة لكل من المبتدئين والمطورين ذوي الخبرة الذين ينتقلون من Java.
1. JUnit5 — أساس الاختبار الحديث
JUnit5 (Jupiter) — هو المعيار الفعلي للاختبارات الوحدوية في Java/Kotlin. في Kotlin، يُستخدم مع ميزات صغيرة ولكنها مهمة.
- دعم تعابير اللامدا والدوال عالية المستوى — يمكن كتابة الاختبارات بشكل أكثر إيجازًا.
- التعليقات التوضيحية —
@Test،@BeforeEach،@AfterAllتعمل كما في Java. - الافتراضات والتأكيدات — فحوصات مدمجة.
مثال على اختبار بسيط باستخدام JUnit5 مع Kotlin:
import org.junit.jupiter.api.Assertions.assertEqualsimport org.junit.jupiter.api.Test
class CalculatorTest {
private val calculator = Calculator()
@Test fun `addition of two numbers should return correct sum`() { val result = calculator.add(2, 3) assertEquals(5, result) }
@Test fun `should throw exception when dividing by zero`() { assertThrows<IllegalArgumentException> { calculator.divide(10, 0) } }}هام: يسمح Kotlin باستخدام المسافات في أسماء دوال الاختبار (باستخدام backticks)، مما يجعل أسماء الاختبارات قابلة للقراءة باللغة الطبيعية.
2. Kotest — إطار Kotlin الأصلي
Kotest (المعروف سابقًا باسم KotlinTest) — هو الإطار الأكثر شمولاً ومرونة، والمكتوب بالكامل بلغة Kotlin. يقدم عدة أنماط لكتابة الاختبارات (النمط النصي، النمط المواصفاتي، النمط السلوكي) ومطابقات مدمجة قوية.
الإمكانيات الرئيسية:
- الاختبار القائم على الخصائص — توليد تلقائي لبيانات الاختبار.
- الاختبارات الموجهة بالبيانات — مع جداول بيانات الإدخال.
- مطابقات تأكيد قوية —
shouldBe،shouldContain،shouldThrowوغيرها. - دعم Coroutines —
testCoroutineScopeمدمج.
مثال على اختبار بنمط "String Spec":
import io.kotest.core.spec.style.StringSpecimport io.kotest.matchers.shouldBeimport io.kotest.matchers.shouldThrow
class UserServiceTest : StringSpec({
val service = UserService()
"should return user by id" { val user = service.getUser(1) user.name shouldBe "Alice" }
"should throw exception for invalid id" { shouldThrow<NoSuchElementException> { service.getUser(-1) } }})الاختبار القائم على الخصائص في Kotest:
import io.kotest.property.forAllimport io.kotest.property.arbitrary.int
class MathPropertiesTest : StringSpec({ "addition is commutative" { forAll<Int, Int> { a, b -> (a + b) == (b + a) } }})3. MockK — وهميات (Mocks) لـ Kotlin
على عكس Mockito (الذي يمكن استخدامه أيضًا)، فإن MockK مُكيّف بالكامل مع خصائص Kotlin: يدعم sealed classes، object، extension functions و coroutines.
الإمكانيات الرئيسية:
- DSL موجز لإنشاء الوهميات والـ stubs.
- دعم الوهميات المرنة (الاستدعاءات غير المُتحقق منها).
- التحقق من ترتيب الاستدعاءات وعددها.
- وهميات للدوال من نوع
suspend.