๐ฅ 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"์ ์ ์ธํ ํ ์คํธ๋ฅผ ์คํํ ์ ์์ด์. ๋ง์น ์ท์ ํ๊ทธ๋ฅผ ๋ฌ์ ์ ๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ฃ ! ๐๐๐
์, ์ด์ 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์ ๋ํด ๊ฝค ๋ง์ด ์๊ฒ ๋์์ฃ ? ์ด๊ฒ๋ค์ด ์ด๋ป๊ฒ ์ฐ๋ฆฌ์ ์์ฐ์ด ์๋๋ฆฌ์ค๋ฅผ ์ค์ ๋์ํ๋ ์ฝ๋๋ก ๋ฐ๊พธ๋์ง ์ดํด๊ฐ ๋์ จ๋์? ๐
๋ค์์ผ๋ก๋ ์ด ๋ชจ๋ ๊ฒ์ ์คํ์ํค๋ 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์ ์ ์ฒด์ ์ธ ํ๋ฆ์ ํ๋์ ๋ณผ ์ ์์ด์. Feature ํ์ผ, Step Definitions, ๊ทธ๋ฆฌ๊ณ Runner๊ฐ ์ด๋ป๊ฒ ์ํธ์์ฉํ๋์ง ๋ณด์ด์๋์? ๐
๐ ํ ์คํธ ๊ฒฐ๊ณผ ๋ถ์ํ๊ธฐ
ํ ์คํธ๊ฐ ๋๋๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ถ์ํด์ผ๊ฒ ์ฃ ? Cucumber๋ ๋ค์ํ ํํ์ ๋ฆฌํฌํธ๋ฅผ ์ ๊ณตํด์.
- ์ฝ์ ์ถ๋ ฅ: ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก, ํ ์คํธ ์คํ ๊ณผ์ ๊ณผ ๊ฒฐ๊ณผ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ณผ ์ ์์ด์.
- HTML ๋ฆฌํฌํธ: ์๊ฐ์ ์ผ๋ก ๋ณด๊ธฐ ์ข์ ๋ฆฌํฌํธ์์. ๊ฐ ์๋๋ฆฌ์ค์ ์ฑ๊ณต/์คํจ ์ฌ๋ถ, ์คํ ์๊ฐ ๋ฑ์ ํ๋์ ๋ณผ ์ ์์ฃ .
- 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 ํ ์คํ ์ ์ธ๊ณ๊ฐ ๊ถ๊ธํด์ง์ง ์๋์? ์ง์ ํด๋ณด๋ฉด ๋ ์ฌ๋ฏธ์์ ๊ฑฐ์์. ์ฝ๋๋ฅผ ํตํด ๋ํํ๋ ์๋ก์ด ๊ฒฝํ์ ์์ํด๋ณด์ธ์! ๐ฅ๐ป๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ