๐Ÿฅ’ Cucumber: BDD ํ…Œ์ŠคํŒ…์˜ ์‹ ์„ธ๊ณ„๋กœ ํ’๋ฉ! ๐ŸŠโ€โ™‚๏ธ

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿฅ’ Cucumber: BDD ํ…Œ์ŠคํŒ…์˜ ์‹ ์„ธ๊ณ„๋กœ ํ’๋ฉ! ๐ŸŠโ€โ™‚๏ธ

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ์‹ ์„ ํ•˜๊ณ  ๋ง›์žˆ๋Š”(?) ์ฃผ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์™”์–ด์š”. ๋ฐ”๋กœ 'Cucumber'๋ผ๋Š” BDD ํ…Œ์ŠคํŒ… ํ”„๋ ˆ์ž„์›Œํฌ์— ๋Œ€ํ•ด ๊นŠ์ด ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด๋ฆ„๋ถ€ํ„ฐ ์ฐธ ๊ท€์—ฝ์ฃ ? ๐Ÿฅ’ ๊ทผ๋ฐ ์ด ์˜ค์ด(?)๊ฐ€ ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋ฅผ ๋” ๋ง›์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š”์ง€, ํ•จ๊ป˜ ์•Œ์•„๋ณด์•„์š”!

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท(https://www.jaenung.net)์ด๋ผ๋Š” ์‚ฌ์ดํŠธ ์•„์„ธ์š”? ๊ฐœ๋ฐœ์ž๋“ค์˜ ์žฌ๋Šฅ์„ ๊ณต์œ ํ•˜๊ณ  ๊ฑฐ๋ž˜ํ•˜๋Š” ํ”Œ๋žซํผ์ธ๋ฐ, ์ด๋Ÿฐ ๊ณณ์—์„œ Cucumber ํ…Œ์ŠคํŒ… ์Šคํ‚ฌ์„ ๊ณต์œ ํ•˜๋ฉด ์–ผ๋งˆ๋‚˜ ๋ฉ‹์งˆ๊นŒ์š”? ใ…Žใ…Ž ์•„๋ฌดํŠผ, ์šฐ๋ฆฌ Cucumber ์„ธ๊ณ„๋กœ ๊ณ ๊ณ ์”ฝ~! ๐Ÿš€

์ž ๊น! Cucumber๊ฐ€ ๋ญ๋ƒ๊ณ ์š”? ๐Ÿค”

Cucumber๋Š” ํ–‰๋™ ์ฃผ๋„ ๊ฐœ๋ฐœ(Behavior-Driven Development, BDD)์„ ์ง€์›ํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด ๋„๊ตฌ์˜ˆ์š”. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์„ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฑธ ๋„์™€์ฃผ์ฃ . ์‰ฝ๊ฒŒ ๋งํ•ด, ์šฐ๋ฆฌ๊ฐ€ ์ผ์ƒ์—์„œ ์“ฐ๋Š” ์–ธ์–ด๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฉ‹์ง„ ๋…€์„์ด์—์š”!

๐Ÿฅ’ Cucumber์˜ 3๋Œ€ ์ฒœ์™• ๐Ÿ†

Cucumber๋Š” ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ด๋ค„์ ธ ์žˆ์–ด์š”. ๋งˆ์น˜ ์‚ผ๊ฒน์‚ด์˜ 3๋Œ€ ์ฒœ์™•์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! (์•„, ๋ฐฐ๊ณ ํŒŒ ๐Ÿ–)

  • Feature ํŒŒ์ผ: ์šฐ๋ฆฌ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์„ ๋‹ด๊ณ  ์žˆ๋Š” ํ…์ŠคํŠธ ํŒŒ์ผ์ด์—์š”. ๋งˆ์น˜ ์š”๋ฆฌ ๋ ˆ์‹œํ”ผ๊ฐ™์ฃ ?
  • Step Definitions: Feature ํŒŒ์ผ์˜ ๊ฐ ๋‹จ๊ณ„๋ฅผ ์‹ค์ œ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ถ€๋ถ„์ด์—์š”. ์š”๋ฆฌ์‚ฌ๊ฐ€ ๋ ˆ์‹œํ”ผ๋ฅผ ๋ณด๊ณ  ์‹ค์ œ๋กœ ์š”๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”!
  • Runner: ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•˜๋Š” ์—ญํ• ์„ ํ•ด์š”. ๋งˆ์น˜ ์š”๋ฆฌ ํ‰๋ก ๊ฐ€๊ฐ€ ์Œ์‹์„ ๋ง›๋ณด๊ณ  ํ‰๊ฐ€ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”.

์ด ์„ธ ๊ฐ€์ง€๊ฐ€ ์–ด์šฐ๋Ÿฌ์ ธ Cucumber์˜ ๋ง›์žˆ๋Š”(?) ํ…Œ์ŠคํŒ… ์„ธ๊ณ„๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ฑฐ์˜ˆ์š”. ์ž, ์ด์ œ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿง

๐Ÿฅ’ Feature ํŒŒ์ผ: ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์˜ ๊ฝƒ ๐ŸŒธ

Feature ํŒŒ์ผ์€ Cucumber์˜ ์‹ฌ์žฅ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด ํŒŒ์ผ์—์„œ ์šฐ๋ฆฌ๋Š” Gherkin์ด๋ผ๋Š” ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์„ ์ •์˜ํ•ด์š”. Gherkin? ๊ฑฐํ‚จ? ์˜ค์ด์ ˆ์ž„...? ๐Ÿฅ’ ์•„๋‹ˆ์—์š”, ๊ทธ๋ƒฅ ์ด๋ฆ„์ด ๋น„์Šทํ•  ๋ฟ์ด์ฃ . ใ…‹ใ…‹ใ…‹

Gherkin์€ ์ž์—ฐ์–ด์™€ ๋น„์Šทํ•ด์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹Œ ์‚ฌ๋žŒ๋“ค๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ๋™ํ™”์ฑ…์„ ์ฝ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! ์ž, ์˜ˆ์‹œ๋ฅผ ํ•œ๋ฒˆ ๋ณผ๊นŒ์š”?

Feature: ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ
  ์‚ฌ์šฉ์ž๊ฐ€ ์›น์‚ฌ์ดํŠธ์— ๋กœ๊ทธ์ธํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ด์š”

  Scenario: ์œ ํšจํ•œ ์ž๊ฒฉ ์ฆ๋ช…์œผ๋กœ ๋กœ๊ทธ์ธ
    Given ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์žˆ๋‹ค
    When ์œ ํšจํ•œ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค
    And ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค
    Then ์‚ฌ์šฉ์ž๋Š” ๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋œ๋‹ค
    And ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค

  Scenario: ์ž˜๋ชป๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ๋กœ๊ทธ์ธ ์‹œ๋„
    Given ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์žˆ๋‹ค
    When ์œ ํšจํ•œ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ์ž˜๋ชป๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค
    And ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค
    Then ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค
    And ์‚ฌ์šฉ์ž๋Š” ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ๋จธ๋ฌธ๋‹ค

์–ด๋•Œ์š”? ๋งˆ์น˜ ์†Œ์„ค์„ ์ฝ๋Š” ๊ฒƒ ๊ฐ™์ง€ ์•Š๋‚˜์š”? ๐Ÿค“ ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด ๊ฐœ๋ฐœ์ž๋ฟ๋งŒ ์•„๋‹ˆ๋ผ PM์ด๋‚˜ ๊ธฐํš์ž, ์‹ฌ์ง€์–ด CEO๊นŒ์ง€๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์–ด์š”! (๋ฌผ๋ก  CEO๊ฐ€ ์ด๊ฑธ ์ฝ์„ ์‹œ๊ฐ„์ด ์žˆ์„์ง„ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ์š”... ๐Ÿ˜…)

๐ŸŒŸ Gherkin์˜ ์ฃผ์š” ํ‚ค์›Œ๋“œ

  • Feature: ํ…Œ์ŠคํŠธํ•  ๊ธฐ๋Šฅ์„ ์„ค๋ช…ํ•ด์š”.
  • Scenario: ํŠน์ • ์ƒํ™ฉ์„ ์„ค๋ช…ํ•ด์š”.
  • Given: ํ…Œ์ŠคํŠธ์˜ ์ „์ œ ์กฐ๊ฑด์„ ์„ค์ •ํ•ด์š”.
  • When: ์‚ฌ์šฉ์ž์˜ ํ–‰๋™์„ ์„ค๋ช…ํ•ด์š”.
  • Then: ์˜ˆ์ƒ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์„ค๋ช…ํ•ด์š”.
  • And: ์ถ”๊ฐ€์ ์ธ Given, When, Then์„ ์—ฐ๊ฒฐํ•ด์š”.
  • But: ๋ถ€์ •์ ์ธ ์ƒํ™ฉ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.

์ด๋ ‡๊ฒŒ ์ž‘์„ฑ๋œ Feature ํŒŒ์ผ์€ ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์•ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฝํž™๋‹ˆ๋‹ค. ์žฌ๋Šฅ๋„ท์—์„œ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ด๋Ÿฐ ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ณต์œ ํ•œ๋‹ค๋ฉด, ์„œ๋กœ์˜ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋˜๊ฒ ์ฃ ? ๐Ÿ˜Š

๐ŸŽญ ์‹œ๋‚˜๋ฆฌ์˜ค ์•„์›ƒ๋ผ์ธ๊ณผ ์˜ˆ์ œ

๋•Œ๋กœ๋Š” ๋น„์Šทํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์–ด์š”. ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ ์‹œ๋‚˜๋ฆฌ์˜ค ์•„์›ƒ๋ผ์ธ(Scenario Outline)์ด์—์š”. ๋งˆ์น˜ ํ‹€์„ ๋งŒ๋“ค์–ด ๋†“๊ณ  ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฌ๋ฃŒ๋ฅผ ๋„ฃ์–ด๋ณด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”!

Scenario Outline: ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์œผ๋กœ ๋กœ๊ทธ์ธ ์‹œ๋„
  Given ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์žˆ๋‹ค
  When <username>๊ณผ <password>๋ฅผ ์ž…๋ ฅํ•œ๋‹ค
  And ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค
  Then ์‹œ์Šคํ…œ์€ <result>๋ฅผ ๋ณด์—ฌ์ค€๋‹ค

  Examples:
    | username | password | result |
    | user1    | pass123  | ์„ฑ๊ณต   |
    | user2    | wrong    | ์‹คํŒจ   |
    | admin    | admin123 | ์„ฑ๊ณต   |

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•˜๋‚˜์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด์š”. ํšจ์œจ์ ์ด์ฃ ? ๐Ÿ‘

๐Ÿท๏ธ ํƒœ๊ทธ ์‚ฌ์šฉํ•˜๊ธฐ

Feature ํŒŒ์ผ์—์„œ๋Š” ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด ํŠน์ • ์‹œ๋‚˜๋ฆฌ์˜ค๋‚˜ ๊ธฐ๋Šฅ์„ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŠน์ • ์ข…๋ฅ˜์˜ ํ…Œ์ŠคํŠธ๋งŒ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ํ…Œ์ŠคํŠธ๋ฅผ ์ œ์™ธํ•  ์ˆ˜ ์žˆ์ฃ .

@login
Feature: ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ

@smoke
Scenario: ๊ธฐ๋ณธ ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ
  ...

@regression
Scenario: ์ƒ์„ธ ๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ
  ...

์ด๋ ‡๊ฒŒ ํƒœ๊ทธ๋ฅผ ๋ถ™์ด๋ฉด ๋‚˜์ค‘์— "@smoke" ํƒœ๊ทธ๊ฐ€ ๋ถ™์€ ํ…Œ์ŠคํŠธ๋งŒ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, "@regression"์„ ์ œ์™ธํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋งˆ์น˜ ์˜ท์— ํƒœ๊ทธ๋ฅผ ๋‹ฌ์•„ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! ๐Ÿ‘•๐Ÿ‘–๐Ÿ‘—

Cucumber Feature ํŒŒ์ผ ๊ตฌ์กฐ Feature ํŒŒ์ผ Scenario 1 Given... When... Then... Scenario 2 Given... When... Then...

์ž, ์ด์ œ Feature ํŒŒ์ผ์— ๋Œ€ํ•ด ๊ฝค ๋งŽ์ด ์•Œ๊ฒŒ ๋˜์—ˆ์ฃ ? ์ด ํŒŒ์ผ๋“ค์ด ์šฐ๋ฆฌ์˜ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์–ผ๋งˆ๋‚˜ ๋ช…ํ™•ํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š”์ง€ ๋Š๊ปด์ง€๋‚˜์š”? ๐Ÿ˜Š

๋‹ค์Œ์œผ๋กœ๋Š” ์ด Feature ํŒŒ์ผ์„ ์‹ค์ œ ์ฝ”๋“œ์™€ ์—ฐ๊ฒฐํ•˜๋Š” Step Definitions์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's go! ๐Ÿš€

๐Ÿฅ’ Step Definitions: ๋ง์„ ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๋Š” ๋งˆ๋ฒ• โœจ

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ ์ž์—ฐ์–ด๋กœ ๋œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‹ค์ œ ์ฝ”๋“œ๋กœ ๋ฐ”๊ฟ”๋ณผ ์‹œ๊ฐ„์ด์—์š”! ์ด๊ฒŒ ๋ฐ”๋กœ Step Definitions์˜ ์—ญํ• ์ด์ฃ . ๋งˆ์น˜ ํ†ต์—ญ์‚ฌ์ฒ˜๋Ÿผ Gherkin ์–ธ์–ด๋ฅผ Java(๋˜๋Š” ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด)๋กœ ๋ฒˆ์—ญํ•ด์ฃผ๋Š” ๊ฑฐ์˜ˆ์š”. ๋ฉ‹์ง€์ง€ ์•Š๋‚˜์š”? ๐Ÿง™โ€โ™‚๏ธ

๐Ÿ“ Step Definitions ์ž‘์„ฑํ•˜๊ธฐ

Step Definitions๋Š” ๋ณดํ†ต Java ํด๋ž˜์Šค ์•ˆ์— ๋ฉ”์†Œ๋“œ๋กœ ์ •์˜๋ผ์š”. ๊ฐ ๋ฉ”์†Œ๋“œ๋Š” Feature ํŒŒ์ผ์˜ ํ•œ ๋‹จ๊ณ„(Given, When, Then ๋“ฑ)์— ๋Œ€์‘๋ฉ๋‹ˆ๋‹ค. ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด ์–ด๋–ค Gherkin ๋ฌธ์žฅ๊ณผ ๋งค์นญ๋˜๋Š”์ง€ ์ง€์ •ํ•ด์ฃผ์ฃ .

import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;

public class LoginStepDefinitions {

    @Given("์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์žˆ๋‹ค")
    public void userIsOnLoginPage() {
        // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ์ฝ”๋“œ
        System.out.println("๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ–ˆ์–ด์š”!");
    }

    @When("์œ ํšจํ•œ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค")
    public void enterValidCredentials() {
        // ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ฝ”๋“œ
        System.out.println("์•„์ด๋””: user1, ๋น„๋ฐ€๋ฒˆํ˜ธ: pass123 ์ž…๋ ฅํ–ˆ์–ด์š”!");
    }

    @When("๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค")
    public void clickLoginButton() {
        // ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ํด๋ฆญ ์ฝ”๋“œ
        System.out.println("๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ '๊พน' ๋ˆŒ๋ €์–ด์š”!");
    }

    @Then("์‚ฌ์šฉ์ž๋Š” ๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋œ๋‹ค")
    public void userIsRedirectedToDashboard() {
        // ๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€ ํ™•์ธ ์ฝ”๋“œ
        System.out.println("์–ด๋ผ? ๋Œ€์‹œ๋ณด๋“œ๊ฐ€ ๋ณด์ด๋„ค์š”!");
    }

    @Then("ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค")
    public void welcomeMessageIsDisplayed() {
        // ํ™˜์˜ ๋ฉ”์‹œ์ง€ ํ™•์ธ ์ฝ”๋“œ
        System.out.println("ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ๋ผ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ๋ณด์—ฌ์š”. ๊ธฐ๋ถ„ ์ข‹๋‹ค ใ…Žใ…Ž");
    }
}

์–ด๋•Œ์š”? Feature ํŒŒ์ผ์˜ ๊ฐ ๋ฌธ์žฅ์ด ์–ด๋–ป๊ฒŒ ์‹ค์ œ ์ฝ”๋“œ์™€ ์—ฐ๊ฒฐ๋˜๋Š”์ง€ ๋ณด์ด์‹œ๋‚˜์š”? ๐Ÿ˜ƒ

๐Ÿšจ ์ฃผ์˜ํ•  ์ 

Step Definitions๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์ •๊ทœ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ํ†ตํ•ด ๋” ์œ ์—ฐํ•œ ๋งค์นญ์ด ๊ฐ€๋Šฅํ•ด์ง€์ฃ . ์˜ˆ๋ฅผ ๋“ค๋ฉด:

@Given("^์‚ฌ์šฉ์ž๊ฐ€ (\\d+)๋ฒˆ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•œ๋‹ค$")
public void userTriesLoginTimes(int times) {
    System.out.println(times + "๋ฒˆ ๋กœ๊ทธ์ธ ์‹œ๋„ํ–ˆ์–ด์š”!");
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด "์‚ฌ์šฉ์ž๊ฐ€ 3๋ฒˆ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•œ๋‹ค", "์‚ฌ์šฉ์ž๊ฐ€ 10๋ฒˆ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•œ๋‹ค" ๋“ฑ ๋‹ค์–‘ํ•œ ๊ฒฝ์šฐ์— ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿงฉ ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌํ•˜๊ธฐ

Step Definitions์—์„œ๋Š” Feature ํŒŒ์ผ์˜ ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ฅผ ํ†ตํ•ด ๋” ๋™์ ์ธ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง€์ฃ !

@When("{string}๊ณผ {string}๋ฅผ ์ž…๋ ฅํ•œ๋‹ค")
public void enterCredentials(String username, String password) {
    System.out.println("์•„์ด๋””: " + username + ", ๋น„๋ฐ€๋ฒˆํ˜ธ: " + password + " ์ž…๋ ฅํ–ˆ์–ด์š”!");
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Feature ํŒŒ์ผ์—์„œ ๋‹ค์–‘ํ•œ ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”:

When "user1"๊ณผ "pass123"๋ฅผ ์ž…๋ ฅํ•œ๋‹ค
When "admin"๊ณผ "adminpass"๋ฅผ ์ž…๋ ฅํ•œ๋‹ค

์žฌ๋Šฅ๋„ท์—์„œ ์ด๋Ÿฐ ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๊ณต์œ ํ•˜๋ฉด, ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค์ด ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์‘์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ๐Ÿ˜Ž

๐ŸŽญ Hooks ์‚ฌ์šฉํ•˜๊ธฐ

Cucumber์—์„œ๋Š” Hooks๋ผ๋Š” ํŠน๋ณ„ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์š”. ์ด ๋ฉ”์†Œ๋“œ๋“ค์€ ๊ฐ ์‹œ๋‚˜๋ฆฌ์˜ค ์ „ํ›„์— ์‹คํ–‰๋˜์–ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ์ •๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ผ์š”.

import io.cucumber.java.Before;
import io.cucumber.java.After;

public class Hooks {

    @Before
    public void setUp() {
        System.out.println("ํ…Œ์ŠคํŠธ ์ค€๋น„ ์ค‘... ๐Ÿ—๏ธ");
        // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ๋ธŒ๋ผ์šฐ์ € ์—ด๊ธฐ ๋“ฑ
    }

    @After
    public void tearDown() {
        System.out.println("ํ…Œ์ŠคํŠธ ์ •๋ฆฌ ์ค‘... ๐Ÿงน");
        // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ํ•ด์ œ, ๋ธŒ๋ผ์šฐ์ € ๋‹ซ๊ธฐ ๋“ฑ
    }
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋งค ์‹œ๋‚˜๋ฆฌ์˜ค๋งˆ๋‹ค ์ผ๊ด€๋œ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊น”๋”ํ•˜์ฃ ? โœจ

Step Definitions ๋™์ž‘ ๊ณผ์ • Step Definitions ๋™์ž‘ ๊ณผ์ • Feature ํŒŒ์ผ Step Definitions ํ…Œ์ŠคํŠธ ์‹คํ–‰

์ž, ์ด์ œ Step Definitions์— ๋Œ€ํ•ด ๊ฝค ๋งŽ์ด ์•Œ๊ฒŒ ๋˜์—ˆ์ฃ ? ์ด๊ฒƒ๋“ค์ด ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ์˜ ์ž์—ฐ์–ด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‹ค์ œ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๋Š”์ง€ ์ดํ•ด๊ฐ€ ๋˜์…จ๋‚˜์š”? ๐Ÿ‘€

๋‹ค์Œ์œผ๋กœ๋Š” ์ด ๋ชจ๋“  ๊ฒƒ์„ ์‹คํ–‰์‹œํ‚ค๋Š” Runner์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ๋‹ฌ๋ ค๋ด…์‹œ๋‹ค! ๐Ÿƒโ€โ™‚๏ธ๐Ÿ’จ

๐Ÿฅ’ Runner: ํ…Œ์ŠคํŠธ์˜ ์ง€ํœ˜์ž ๐ŸŽญ

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ Feature ํŒŒ์ผ๋„ ์žˆ๊ณ , Step Definitions๋„ ์ค€๋น„๋์–ด์š”. ๊ทธ๋Ÿฐ๋ฐ ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ์‹คํ–‰์‹œํ‚ค์ฃ ? ์—ฌ๊ธฐ์„œ ๋“ฑ์žฅํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ Runner์˜ˆ์š”! Runner๋Š” ๋งˆ์น˜ ์˜ค์ผ€์ŠคํŠธ๋ผ์˜ ์ง€ํœ˜์ž์ฒ˜๋Ÿผ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์กฐํ™”๋กญ๊ฒŒ ์‹คํ–‰์‹œํ‚ค๋Š” ์—ญํ• ์„ ํ•ด์š”. ๐ŸŽป๐ŸŽบ๐Ÿฅ

๐Ÿƒโ€โ™‚๏ธ Runner ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ

Runner ํด๋ž˜์Šค๋Š” JUnit๊ณผ Cucumber๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์š”. ๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ๊ฒผ๋‹ต๋‹ˆ๋‹ค:

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = "com.example.stepdefinitions",
    plugin = {"pretty", "html:target/cucumber-reports"}
)
public class TestRunner {
}

์šฐ์™€, ๋ญ”๊ฐ€ ๋ณต์žกํ•ด ๋ณด์ด์ฃ ? ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณผ๊ฒŒ์š”! ๐Ÿ˜Ž

  • @RunWith(Cucumber.class): JUnit์—๊ฒŒ ์ด ํ…Œ์ŠคํŠธ๋ฅผ Cucumber๋กœ ์‹คํ–‰ํ•˜๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ๊ฑฐ์˜ˆ์š”.
  • @CucumberOptions: Cucumber ์‹คํ–‰์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์˜ต์…˜์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • features: Feature ํŒŒ์ผ๋“ค์ด ์žˆ๋Š” ์œ„์น˜๋ฅผ ์ง€์ •ํ•ด์š”.
  • glue: Step Definitions ํด๋ž˜์Šค๋“ค์ด ์žˆ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์ง€์ •ํ•ด์š”.
  • plugin: ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ์–ด๋–ค ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ• ์ง€ ์ •ํ•ด์š”. ์—ฌ๊ธฐ์„œ๋Š” ์ฝ˜์†”์— ์˜ˆ์˜๊ฒŒ ์ถœ๋ ฅํ•˜๊ณ , HTML ๋ฆฌํฌํŠธ๋„ ์ƒ์„ฑํ•˜๋„๋ก ํ–ˆ์–ด์š”.

๐Ÿ’ก ๊ฟ€ํŒ!

Runner ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ ๊ผญ "TestRunner"์ผ ํ•„์š”๋Š” ์—†์–ด์š”. "CucumberRunner", "BDDTestSuite" ๋“ฑ ํ”„๋กœ์ ํŠธ์— ๋งž๋Š” ์ด๋ฆ„์„ ์ž์œ ๋กญ๊ฒŒ ์ง€์–ด์ฃผ์„ธ์š”. ์ค‘์š”ํ•œ ๊ฑด @RunWith์™€ @CucumberOptions ์–ด๋…ธํ…Œ์ด์…˜์ด์—์š”!

๐ŸŽ›๏ธ ์ถ”๊ฐ€ ์˜ต์…˜๋“ค

@CucumberOptions์—๋Š” ๋” ๋งŽ์€ ์„ค์ •๋“ค์ด ์žˆ์–ด์š”. ๋ช‡ ๊ฐ€์ง€ ์œ ์šฉํ•œ ์˜ต์…˜๋“ค์„ ์‚ดํŽด๋ณผ๊นŒ์š”?

@CucumberOptions(
    features = "src/test/resources/features",
    glue = "com.example.stepdefinitions",
    plugin = {"pretty", "html:target/cucumber-reports", "json:target/cucumber.json"},
    tags = "@smoke or @regression",
    dryRun = false,
    monochrome = true
)
  • tags: ํŠน์ • ํƒœ๊ทธ๊ฐ€ ๋ถ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋งŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์—ฌ๊ธฐ์„œ๋Š” @smoke ๋˜๋Š” @regression ํƒœ๊ทธ๊ฐ€ ๋ถ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋งŒ ์‹คํ–‰ํ•ด์š”.
  • dryRun: true๋กœ ์„ค์ •ํ•˜๋ฉด ์‹ค์ œ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ , ๋ชจ๋“  step์ด ์ •์˜๋˜์–ด ์žˆ๋Š”์ง€๋งŒ ํ™•์ธํ•ด์š”. ๋น ๋ฅด๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ์ฐพ์„ ๋•Œ ์œ ์šฉํ•˜์ฃ !
  • monochrome: ์ฝ˜์†” ์ถœ๋ ฅ์„ ๋” ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ค˜์š”. ์ปฌ๋Ÿฌํ’€ํ•œ ๊ฒŒ ์ข‹๋‹ค๋ฉด false๋กœ ์„ค์ •ํ•˜์„ธ์š”!

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด ์šฐ๋ฆฌ์˜ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์™„์ „ํžˆ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋ฉด, ์ด๋Ÿฐ ์˜ต์…˜๋“ค์„ ์ž˜ ํ™œ์šฉํ•ด์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”๊ตฌ์— ๋งž๋Š” ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘ฉโ€๐Ÿ’ผ

๐Ÿƒโ€โ™€๏ธ Runner ์‹คํ–‰ํ•˜๊ธฐ

Runner ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด, ์ด์ œ ์‹คํ–‰๋งŒ ํ•˜๋ฉด ๋ผ์š”! IDE์—์„œ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ๊ณ , Maven์ด๋‚˜ Gradle ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

Maven์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”:

mvn test

Gradle์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ผ์š”:

gradle test

๊ทธ๋Ÿฌ๋ฉด ์šฐ๋ฆฌ์˜ Cucumber ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๊ฒฐ๊ณผ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋˜๋ฉฐ, HTML ๋ฆฌํฌํŠธ๋„ ์ƒ์„ฑ๋  ๊ฑฐ์˜ˆ์š”. ์งœ์ž”! ๐ŸŽ‰

Cucumber ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๊ณผ์ • Cucumber ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๊ณผ์ • Feature ํŒŒ์ผ Step Definitions Runner Cucumber ์—”์ง„ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ & ๋ฆฌํฌํŠธ

์ด ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๋ณด๋ฉด Cucumber์˜ ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. Feature ํŒŒ์ผ, Step Definitions, ๊ทธ๋ฆฌ๊ณ  Runner๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š”์ง€ ๋ณด์ด์‹œ๋‚˜์š”? ๐Ÿ˜Š

๐Ÿ“Š ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋ถ„์„ํ•˜๊ธฐ

ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ถ„์„ํ•ด์•ผ๊ฒ ์ฃ ? Cucumber๋Š” ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ ๋ฆฌํฌํŠธ๋ฅผ ์ œ๊ณตํ•ด์š”.

  1. ์ฝ˜์†” ์ถœ๋ ฅ: ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ๋กœ, ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๊ณผ์ •๊ณผ ๊ฒฐ๊ณผ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.
  2. HTML ๋ฆฌํฌํŠธ: ์‹œ๊ฐ์ ์œผ๋กœ ๋ณด๊ธฐ ์ข‹์€ ๋ฆฌํฌํŠธ์˜ˆ์š”. ๊ฐ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€, ์‹คํ–‰ ์‹œ๊ฐ„ ๋“ฑ์„ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์ฃ .
  3. JSON ๋ฆฌํฌํŠธ: ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ์—ฐ๋™ํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ ๋ถ„์„์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ์˜ˆ์š”.

HTML ๋ฆฌํฌํŠธ๋ฅผ ์—ด์–ด๋ณด๋ฉด ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ณด์ผ ๊ฑฐ์˜ˆ์š”:

Cucumber ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

์‹คํ–‰๋œ ์‹œ๋‚˜๋ฆฌ์˜ค: 10

์„ฑ๊ณต: 8 ๐ŸŸข

์‹คํŒจ: 2 ๐Ÿ”ด

์ด ์‹คํ–‰ ์‹œ๊ฐ„: 1๋ถ„ 30์ดˆ

์ด๋Ÿฐ ์‹์œผ๋กœ ํ•œ๋ˆˆ์— ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์–ด๋–ค ๋ถ€๋ถ„์—์„œ ์‹คํŒจํ–ˆ๋Š”์ง€ ์ž์„ธํžˆ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ์Šคํฌ๋ฆฐ์ƒท์ด๋‚˜ ๋กœ๊ทธ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ฃ .

๐ŸŒŸ Pro Tip!

CI/CD ํŒŒ์ดํ”„๋ผ์ธ์— Cucumber ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ฉํ•˜๋ฉด ๋”์šฑ ํšจ๊ณผ์ ์ด์—์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, Jenkins๋‚˜ GitLab CI์—์„œ ๋งค ์ปค๋ฐ‹๋งˆ๋‹ค Cucumber ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํŒ€์›๋“ค์—๊ฒŒ ์ž๋™์œผ๋กœ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์ฃ !

๐Ÿ”„ ์ง€์†์ ์ธ ๊ฐœ์„ 

Cucumber ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ถ„์„ํ–ˆ๋‹ค๋ฉด, ์ด์ œ ๋ฌด์—‡์„ ํ•ด์•ผ ํ• ๊นŒ์š”? ๋ฐ”๋กœ ๊ฐœ์„ ์ด์ฃ ! ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”:

  • ์‹คํŒจํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๋ถ„์„ ๋ฐ ์ˆ˜์ •
  • ์ƒˆ๋กœ์šด ์‹œ๋‚˜๋ฆฌ์˜ค ์ถ”๊ฐ€
  • ๊ธฐ์กด ์‹œ๋‚˜๋ฆฌ์˜ค ์ตœ์ ํ™”
  • Step Definitions ๋ฆฌํŒฉํ† ๋ง

์ด๋ ‡๊ฒŒ ์ง€์†์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐœ์„ ํ•˜๋ฉด, ํ”„๋กœ์ ํŠธ์˜ ํ’ˆ์งˆ๋„ ํ•จ๊ป˜ ํ–ฅ์ƒ๋  ๊ฑฐ์˜ˆ์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์ด๋Ÿฐ ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋ฉด, ํด๋ผ์ด์–ธํŠธ๋“ค์˜ ๋งŒ์กฑ๋„๊ฐ€ ํ›จ์”ฌ ๋†’์•„์งˆ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜‰

๐ŸŽ“ ๋งˆ๋ฌด๋ฆฌ

์ž, ์ด์ œ Cucumber์˜ ์„ธ ๊ฐ€์ง€ ํ•ต์‹ฌ ์š”์†Œ์ธ Feature ํŒŒ์ผ, Step Definitions, ๊ทธ๋ฆฌ๊ณ  Runner์— ๋Œ€ํ•ด ๋ชจ๋‘ ์•Œ์•„๋ดค์–ด์š”. ์ด ์„ธ ๊ฐ€์ง€๊ฐ€ ์–ด์šฐ๋Ÿฌ์ ธ ์šฐ๋ฆฌ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์™„์„ฑํ•˜๋Š” ๊ฑฐ์ฃ . ๋งˆ์น˜ ๋ง›์žˆ๋Š” ์š”๋ฆฌ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์—์š”! ๐Ÿฅ’๐Ÿฝ๏ธ

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

์žฌ๋Šฅ๋„ท์—์„œ ์ด๋Ÿฐ Cucumber ํ…Œ์ŠคํŒ… ์Šคํ‚ฌ์„ ๊ณต์œ ํ•˜๋ฉด ์–ด๋–จ๊นŒ์š”? ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ BDD์˜ ๋งค๋ ฅ์„ ์ „ํŒŒํ•˜๊ณ , ํ•จ๊ป˜ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ํ…Œ์ŠคํŠธ ์ž๋™ํ™”์˜ ์„ธ๊ณ„๋Š” ์ •๋ง ๋„“๊ณ  ๊นŠ๋‹ต๋‹ˆ๋‹ค. ๊ณ„์†ํ•ด์„œ ํƒํ—˜ํ•ด๋ณด์„ธ์š”! ๐Ÿš€๐ŸŒŸ

์ž, ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ Cucumber์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์—ˆ์–ด์š”. ์–ด๋–ค๊ฐ€์š”? BDD ํ…Œ์ŠคํŒ…์˜ ์„ธ๊ณ„๊ฐ€ ๊ถ๊ธˆํ•ด์ง€์ง€ ์•Š๋‚˜์š”? ์ง์ ‘ ํ•ด๋ณด๋ฉด ๋” ์žฌ๋ฏธ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋Œ€ํ™”ํ•˜๋Š” ์ƒˆ๋กœ์šด ๊ฒฝํ—˜์„ ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”! ๐Ÿฅ’๐Ÿ’ป๐ŸŽ‰