[Kotlin] TestFixture

๐Ÿ’ก TDD๋ฅผ ํ†ตํ•ด ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ TestFixture์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ , ์ด์— ๋Œ€ํ•˜์—ฌ ์ž์„ธํ•˜๊ฒŒ ํ•™์Šตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

TestFixture

  • ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๊ณ ์ •๋œ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์ „์— ๊ณตํ†ต์œผ๋กœ ํ•„์š”ํ•œ ๊ฐ์ฒด๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•˜์—ฌ, ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ค„์ด๊ณ  ๊ฐ€๋…์„ฑ๊ณผ ์ผ๊ด€์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ํด๋ž˜์Šค ์ƒ์„ฑ

class Calculator {
    fun add(a: Int, b: Int): Int {
        return a + b
    }

    fun subtract(a: Int, b: Int): Int {
        return a - b
    }
}
  • ์œ„์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.assertEquals

class CalculatorTest {

    private lateinit var calculator: Calculator

    @BeforeEach
    fun setUp() {
        // TestFixture ์„ค์ •
        calculator = Calculator()
    }

    @Test
    fun testAdd() {
        val result = calculator.add(2, 3)
        assertEquals(5, result)
    }

    @Test
    fun testSubtract() {
        val result = calculator.subtract(5, 3)
        assertEquals(2, result)
    }
}
  • @BeforEach ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•ด์„œ ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— setUp() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ calculator ๊ฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋งค๋ฒˆ calculator ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ ธ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ™•์žฅํ•จ์ˆ˜ ํ™œ์šฉํ•˜๊ธฐ

  • ํ…Œ์ŠคํŠธ์ฝ”๋“œ ๋งŒ์„ ์œ„ํ•œ ํ™•์žฅํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋„ TestFixture๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
object TestFixture {
    fun CartItemDatabase.deleteAll() {
        this.openHelper.writableDatabase.execSQL("DELETE FROM ${CartItemDatabase.CART_ITEMS_DB_NAME}")
    }
}
  • CartItemDatabase๋ผ๋Š” ๋กœ์ปฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ™•์žฅํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์ด๋Š” ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๊ณ , ์ผ๊ด€์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์—ˆ์œผ๋ฏ€๋กœ ์ผ์ข…์˜ TestFixture๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Mock ๋ฐ์ดํ„ฐ ์ƒ์„ฑ

  • ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ํ•˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ๊ณ ์ •๋œ ์ƒํƒœ๋‚˜ ๊ฐ์ฒด๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ TestFixture๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์•„๋ž˜์™€ ๊ฐ™์€ ํ…Œ์ŠคํŠธ์— ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด ์ƒ์„ฑ์˜ ์—ญํ• ์„ ์ค„์—ฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
object TestFixture {
    fun makeCartItemEntity(): CartItemEntity {
        return CartItemEntity(
            product =
                Product(
                    imageUrl = "",
                    price = 10000,
                    name = "์•„๋ฉ”๋ฆฌ์นด๋…ธ",
                    id = 0L,
                    category = "",
                ),
        )
    }

    fun makeRecentlyProductEntity(): RecentlyProductEntity {
        return RecentlyProductEntity(
            id = 2L,
            productId = 9999999L,
            imageUrl = "",
            name = "",
            category = "fashion",
        )
    }
}

์ •๋ฆฌ

  • TestFixture๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ•„์š”ํ•œ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ผ๊ด€์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๋„์›€์ด ๋˜๋ฉฐ, @BeforEach ํ˜น์€ @BeforAll ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ 

https://oliveyoung.tech/blog/2024-04-01/testcode-use-fixture-monkey/

https://velog.io/@pood/Test-Fixture-์—-๋Œ€ํ•ด์„œ