본문 바로가기

개발/JavaScript

[Vanilla Javascript] Jasmine을 이용해 테스트 코드 작성해보기 -1

레거시 코드

<button onclick="counter++; countDisplay()">증가</button>
<span id="counter-display">0</span>

<script>
    var counter = 0;

    function countDisplay() {
        var el = document.getElementById('counter-display');
        el.innerHTML = counter;
    }
</script>

버튼을 누르면 하나씩 증가하는 형태의 코드이며 이 코드에는 세가지 문제점이 있다.

 

레거시 코드의 문제점

1. 관심사의 미분리

<button onclick="counter++; countDisplay()">증가</button>

한줄의 코드가 여러개의 역할을 하고있는데 하나의 코드는 한가지 역할만 하는 것이 좋다. (단일 책임의 원칙)

그래야 읽기 쉽고 명확한 코드가 된다.

 

2. 전역변수의 충돌

var counter = 0;

전역변수는 어떤 경우에서라도 쓰지 않는 것이 좋다. 충돌나기 쉽기 때문이다.

 

3. 재사용이 어려움

var el = document.getElementById('counter-display');

span id를 하드코딩하여 재사용성이 떨어진다.

확장에는 열려있고 변경에는 닫혀있는 코드가 좋은 코드이다.

 

어떻게 하면 테스트 할 수 있을까?

1. 코드를  UI에서 완전히 분리

HTML에서 JS 코드를 떼어내면 비즈니스 로직만 테스트 할 수 있다.

 

2. 자바스크립트를 별도 파일로 분리

다른곳에서도 재사용할 수 있고 테스트성도 좋아진다.

 


작성해보기

ClickCounter는 카운터 데이터를 다루는 모듈이다.

전역 공간에 있는 counter 변수를 ClickCounter 안에서 관리하자

 

첫번째 스펙

"ClickCounter 모듈의 getValue()는 카운터 값을 반환한다"

 

Red

ClickCounter.spec.js

describe('App.ClickCounter', ()=> {
  describe('getValue()', ()=> {
    it('초기값이 0인 카운터 값을 반환한다', ()=> {
      const counter = App.ClickCounter();
      expect(counter.getValue()).toBe(0);
    })
  })
})

초기값이 0인 카운터 값을 반환하는 getvalue 테스트

 

Green

ClickCounter.js

var App = App || {}

App.ClickCounter = () => {
    
    return {
        getValue: function() {return 0;}
    }
}

 

Refactor

ClickCounter.js

var App = App || {}

App.ClickCounter = () => {
    let value = 0;

    return {
        getValue: function() {return value;}
    }
}

두번째 스펙

"ClickCounter 모듈의 increase()는 카운터 값을 1만큼 증가한다"

 

Red 

ClickCounter.spec.js

  describe('increase()', () => {
    it('카운터 값을 1만큼 증가한다', () => {
      const counter = App.ClickCounter();
      counter.increase();
      expect(counter.getValue()).toBe(1);
    })
  })

 

Green

ClickCounter.js

var App = App || {}

App.ClickCounter = () => {
    let value = 0;

    return {
        getValue() {
            return value;
        },
        increase() {
            value++;
        },
    }
}

 

Refector

ClickCounter.spec.js

describe('App.ClickCounter', ()=> {
  let counter;
  beforeEach(() => {
    counter = App.ClickCounter();
  });

  describe('getValue()', () => {
    it('초기값이 0인 카운터 값을 반환한다', ()=> {
      expect(counter.getValue()).toBe(0);
    })
  })

  describe('increase()', () => {
    it('카운터 값을 1만큼 증가한다', () => {
      const initialValue = counter.getValue();
      counter.increase();
      expect(counter.getValue()).toBe(initialValue + 1);
    })
  })
})

 

beforeEach()로 코드 중복 방지 및 initial 변수 할당


Reference 

https://www.inflearn.com/course/tdd-%EA%B2%AC%EA%B3%A0%ED%95%9C-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

견고한 JS 소프트웨어 만들기 - 인프런 | 강의

같은 기능을 만들더라도 자바스크립트 문법을 이제 막 뗀 주니어 개발자와 경험 많은 시니어 개발자의 코드는 상당히 다릅니다. 물론 결과물은 같더라도 말이죠. 후자의 코드가 인정받는 이유

www.inflearn.com