Vue BDD

Vue BDD - Cypress ์ ์šฉํ•˜๊ธฐ

eddie0329 2020. 10. 13. 12:21
๋ฐ˜์‘ํ˜•

๐Ÿ“Œ ๋ชฉ์ฐจ

  • Introduction
  • Gherkin ์‚ฌ์šฉ
  • Gherkin + Cypress
  • Vuex store mocking ํ•˜๊ธฐ
  • Conclusion
  • Reference

๐Ÿ“Œ Introduction

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ ๋‹ค๋ค˜๋˜ Gherkin์„ ์‹ค์ œ๋กœ Cypress์— ์ ์šฉํ•˜๋Š” ํฌ์ŠคํŒ…์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์—์„œ ํ™•์ธ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿšง ํ•ด๋‹น ํฌ์ŠคํŒ…์˜ ์˜ˆ์ œ๋Š” ๊ฐ„๋‹จํ•œ counter ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.

๐Ÿ“Œ Gherkin ์‚ฌ์šฉ

Counter๋Š” ์„ธ๊ฐ€์ง€ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•ด์„œ ์ž‘๋™์ด ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. count์˜ ์‹œ์ž‘ ๊ฐ’์€ 0์ž…๋‹ˆ๋‹ค.
  2. ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด count๊ฐ€ 1 ์ฆ๊ฐ€ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
  3. ๋งˆ์ด๋„ˆ์Šค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด count๊ฐ€ 1 ๊ฐ์†Œ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ํ•ด๋‹น ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ Gherkin์œผ๋กœ ์˜ฎ๊ฒจ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# Counter.feature
Feature: Counter
    Background:
        Given I am on the main page # ํ•ญ์ƒ main page('/')์—์„œ ๋™์ž‘์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

    # count์˜ ์‹œ์ž‘ ๊ฐ’์€ 0์ž…๋‹ˆ๋‹ค.
    Scenario: Counter display
        Then: I can see count display with 0

    # ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด count๊ฐ€ 1 ์ฆ๊ฐ€ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    Scenario: Click plus button
        When I click plus button
        Then count display should 1

    # ๋งˆ์ด๋„ˆ์Šค ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด count๊ฐ€ 1 ๊ฐ์†Œ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    Scenario: Click minus button
        When I click minus button
        Then count display should -1

์ด๋ ‡๊ฒŒ Gherkin๋ฌธ๋ฒ•์œผ๋กœ ์˜ฎ๊ฒจ๋ดค์Šต๋‹ˆ๋‹ค.
(๐Ÿšจ ํ•ด๋‹น Gherkin ๋ฌธ๋ฒ•์€ ์ด์ „์— ์•Œ๋ ค๋“œ๋ ธ๋˜ ์ข‹์€ ์˜ˆ์ œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ์‚ผ์ธ์นญ์„ ์จ์ฃผ์„ธ์š”!)

๐Ÿ“Œ Gherkin + Cypress

์ด์ œ ์ด๋Ÿฌํ•œ ๋ฌธ๋ฒ•์„ ์ด์ œ Cypress๋กœ ์ด๋™์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// specs/Counter/index.js

const { visit, the } = cy;

// Background:
Given("I am on the main page", () => {
  visit("/");
});

// Scenario: Counter display
Then("I can see count display with {int}", (countDisplay) => {
  the("counter").contains(countDisplay);
});

// Click plus button
When("I click plus button", () => {
  the("plus-button").click();
});
Then("count display should {int}", (countDisplay) => {
  the("counter").contains(countDisplay);
});

// Click minus button
When("I click minus button", () => {
  the("minus-button").click();
});
Then("count display should {int}", (countDisplay) => {
  the("counter").contains(countDisplay);
});

๋˜๋‹ค๋ฅธ ์‹ ๊ธฐํ•œ ์ ์€ {int}์ž…๋‹ˆ๋‹ค. Gherkin์—์„œ ์ •์˜๋œ ์ˆซ์ž๋ฅผ ์ธ์ž๊ฐ’์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cy.the๋Š” ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.(๋”ฐ๋กœ commands๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”)
์•„๋ž˜ data-test-counter๊ฐ™์ด cypress๋ฅผ ์œ„ํ•œ tag๋ฅผ ์ง€์ •ํ•œ ๋’ค์— the commands๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<!-- App.vue -->
<div id="app">
    <div data-test-counter>{{ count }}</div>
    <div>
      <button @click="increase" data-test-plus-button>+</button>
      <button @click="decrease" data-test-minus-button>-</button>
    </div>
    <div data-test-todo>
      {{ todos.title }}
    </div>
  </div>

๐Ÿ“Œ Vuex store mocking ํ•˜๊ธฐ

Vuex store๋ฅผ mockํ•˜๊ธฐ์— ์•ž์„œ ์ƒˆ๋กœ์šด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ถ”๊ฐ€ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
โญ๏ธ๋งŒ์•ฝ count๊ฐ€ 100์ด๋ผ๋ฉด ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„๋•Œ 101์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋จผ์ € Gherkin์„ ์ž‘์„ฑ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Scenario: Click plus button when count is 100
    Given Count is 100
    When I click plus button
    Then count display should 101

์ด์ œ cypress๋กœ store๋ฅผ mock ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const { visit, the, getStore } = cy; // ๋จผ์ € getStore๋ฅผ ๊ฐ€์ ธ์™€ ์ฃผ์„ธ์š”!

// Scenario: Click plus button when count is 100
Given("Count is {int}", (newCount) => {
  getStore().setState("counter", "count", newCount); // counter module์˜ count ๊ฐ’์„ newCount๋กœ ์žฌ์ •์˜ ํ•ฉ๋‹ˆ๋‹ค.
});
When("I click plus button", () => {
  // set state
  the("plus-button").click();
});
Then("count display should {int}", (countDisplay) => {
  the("counter").contains(countDisplay);
});

๐Ÿ“Œ Conclusion

์ด๋ ‡๊ฒŒ BDD๋ฅผ ํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„ ๋ดค์Šต๋‹ˆ๋‹ค. ์ž์—ฐ์–ด๋ฅผ ์“ด๋‹ค๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ด์ ์„ ๊ฐ€์ ธ๋‹ค ์ฃผ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Test code๋ฅผ ์ ๋Š” ๋‹ค๋Š” ๊ฒƒ์ด ๋‹จ์ˆœ testing์˜ ๋ชฉ์ ์ด ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฌธ์„œ์˜ ์—ญํ• ์„ ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. BDD๋ฅผ ํ•˜๋Š”๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ํฐ ์ด์ ์„ ์ฃผ๋Š”์ง€๋Š” ํ˜‘์—…์„ ํ• ๋•Œ ๊ฐ€์žฅ ๋งŽ์€ ํž˜์ด ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋ด์•ผํ• ๋•Œ ๊ธฐํš์„œ๋ฅผ ๋‹ค์‹œ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ ‡๊ฒŒ ์งœ์—ฌ์ง„ Gherkin ์ฝ”๋“œ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋„ ๊ธฐํš์„œ์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ์ค๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ BDD๋ฅผ ํ•˜๋Š”๊ฐ€ ๋ด…๋‹ˆ๋‹ค...๐Ÿ˜Ž ๊ทธ๋Ÿผ ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” api๋ฅผ mock ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ํฌ์ŠคํŒ… ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค~~

๐Ÿ“Œ Reference

๋ฐ˜์‘ํ˜•