전 포스팅에서 Karma+Mocha+Chai를 이용하여 유닛테스트의 환경을 구축하여 간단한 컴포넌트 마운트에 대해서 유닛테스트를 진행했다. 이번에는 Todo APP이라는 주요 기능에 대해서 실제 유닛테스트를 적용시켜보겠다. Todo App의 주요 기능은 다음과 같다.
Todo list가 제대로 노출되어야 한다.
Todo item이 Todo list에 추가 되어야 한다.
Todo item이 삭제가 되어야 한다.
Todo item이 수정이 되어야 한다.
Todo item이 각각 완료처리를 할 수 있어야 한다.
Todo list를 한번에 완료 처리 할 수 있어야 한다.
Todo item이 ‘All’, ‘Active’, ‘Completed’ 필터에 맞게 제대로 노출되어야 한다.
위의 체크 사항 순차적으로 돌아가며 유닛테스트에 적용해보도록 하겠다. 적용된 소스는 Github 레파지토리 에서 볼 수 있다.
Todo list 가 제대로 노출되어야 한다.
Todo list의 경우 app의 entry 에서 받은 props의 값을 TodoList 컴포넌트에게 전달해주고, TodoList는 받은 그 데이터를 v-for를 이용하여 Todo 컴포넌트에 바인딩해준다. 그렇다면 list가 제대로 노출되는지를 확인하려면 Todo 컴포넌트를 확인하면 된다.
// Todo.spec.js import { mount } from'avoriaz'; import App from'@/components/Todo.vue';
describe('Todo.vue', () => { it('Should render correct todo item', () => { // Mock data const todo = { id: "223362f9637d2895", isDone: true, todo: "Todo01" }; // propsData에 Mock data를 등록 const TodoComponent = mount(App, { propsData: { todo }}); const textElement = TodoComponent.find('label')[0]; // propsData의 todo를 제대로 보여주는가? expect(textElement.text()).to.equal(todo.todo); }); });
Todo 컴포넌트의 역할은 단순하다. TodoList에서 받은 todo의 데이터를 제대로 랜더링 해주는가가 Todo의 관심사이다. 위의 코드를 보면 todo 라는 변수에 mock data를 넣어주었다. TodoList 컴포넌트로부터 todo에 해당하는 데이터가 내려올 경우 그 데이터를 제대로 보여주는가에 대한 테스트이다. 위의 코드와 동일하게 작성되었다면 아래와 같은 초록색 글씨를 볼 수 있다.
describe('Header.vue', () => { it('Should add a new todo item and after that deleted text field', () => { // Mock date const newItem = 'Todo Item01'; const HeaderComponent = mount(Header); const inputField = HeaderComponent.find('input')[0];
// Set mock data HeaderComponent.setData({ newItem });
// Set spy for addTodo function const event = sinon.spy(); HeaderComponent.vm.$on( 'addTodo', event );
inputField.trigger('keydown.enter');
// newItem의 데이터를 추가한 후, 값이 지워지는가 expect(HeaderComponent.data().newItem).to.equal(''); // 부모로부터 내려받은 이벤트를 실행시키는가? expect(event.calledOnce).to.equal(true); }) })
위의 코드는 값을 입력한 후, enter 키는 누르면 부모에게 event bus 를 전달하는가와 field가 초기화 되는가에 대한 관심사를 유닛테스트로 검증하고 있다.
Todo item이 삭제가 되어야 한다.
삭제에 대한 기능의 관심사는 2개이다. button을 클릭했을 때, 클릭한 타켓의 primary key를 전달하느냐와 event bus 를 발생시키느냐.
현재 이커머스회사에서 frontend 개발자로 업무를 진행하고 있는 Martin 입니다. 글을 읽으시고 궁금한 점은 댓글 혹은 메일(hoons0131@gmail.com)로 연락해주시면 빠른 회신 드리도록 하겠습니다. 이 외에도 네트워킹에 대해서는 언제나 환영입니다.:Martin(https://github.com/martinYounghoonKim)