Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
React로
TDD 쵸큼 맛보기
김훈민@네이버
나는자바스크립트개발자다
김코딩
스마트에디터 3.0, 프론트엔드 개발 - @네이버
기술 블로그(huns.me)에 아주 가끔 글 쓰기
페이스북 커뮤니티 프론트엔드개발그룹 운영하는 척
네이버 사내 리액트 미트업 운영하는 척
Facebook은 Rea...
오늘의 주제는 …
단위 테스트 어떻게 작성하나요?
TDD, 왜 해요?
TDD 하면 뭐가 좋아요?
TDD 하면 설계를 잘 할 수 있나요?
TDD 하면 클린 코드를 작성할 수 있나요?
TDD 하는 모습이 궁금해요
오늘의 주제는 …
단위 테스트 어떻게 작성하나요?
TDD, 왜 해요?
TDD 하면 뭐가 좋아요?
TDD 하면 설계를 잘 할 수 있나요?
TDD 하면 클린 코드를 작성할 수 있나요?
TDD 하는 모습이 궁금해요
오늘 만들 녀석은,
“막막” 간단한 Spinbox
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
환경은…?
Webpack
ES2015 with babel
Jest
Enzyme
들어가기 전에
테스트 설정은 잘 되어있나?
구현 코드 테스트 코드
it('스핀박스 생성할 수 있다.', () => {
// given - 어떤 조건 또는 상황일 때
// when - 어떤 행위를 하면
// then - 결과가 무엇이어야 한다
});
it('스핀박스를 생성할 수 있다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
expect(spinbox).toBeDefined();
...
it('스핀박스 생성할 수 있다.', () => {
// setup
// exercise
// verify
});
“어디에서 시작하지?”
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
“어디에서 시작하지?”
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
it('스핀박스를 생성할 수 있다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
expect(spinbox).toBeDefined();
...
it('스핀박스를 생성할 수 있다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
expect(spinbox).toBeDefined();
...
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
expect(spinbox).toBe...
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
const input = spinbo...
import React from 'react';
const Spinbox = () => (
<div>
<input type=“text" />
<button>▲</button>
<button>▼</button>
</div...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200" />
<button>▲</button>
<butt...
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
const input = spinbo...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200" />
<button>▲</button>
<butt...
TDD는
테스트와 구현을 반복하면서
계단을 하나씩 쌓아가는 여정
“테스트 코드”는
어떻게 검증해야 하지?
두 번째 요구사항
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
const input = spinbo...
it('입력 폼에 999를 입력할 수 있다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
const input = spinbox
.fin...
it('입력 폼에 999를 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('input'...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200" />
<button>▲</button>
<butt...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200"
onChange={ () => {
this.set...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200" />
<button>▲</button>
<butt...
it('입력 폼에 숫자 값을 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('input...
it.skip('입력 폼에 숫자 값을 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('...
import React from 'react';
const Spinbox = () => (
<div>
<input type="text"
defaultValue="200" />
<button>▲</button>
<butt...
import React from ‘react';
class Spinbox extends React.Component {
render() {
return (
<div>
<input type="text"
defaultVal...
it.skip('입력 폼에 숫자 값을 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('...
it('입력 폼에 999를 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('input'...
class Spinbox extends React.Component {
componentWillMount() {
this.state = {
value: 200
};
}
render() {
return (
<div>
<i...
class Spinbox extends React.Component {
componentWillMount() {
this.state = {
value: 200
};
}
render() {
return (
<div>
<i...
class Spinbox extends React.Component {
componentWillMount() {
this.state = {
value: 200
};
this.handleChangeInput = this....
it('스핀박스를 생성할 수 있다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// then
expect(spinbox).toBeDefined();
...
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … });
it('입력 폼에 999를 입력할 수 있다.', () => { … });
it('입력 폼에 0을 입력할 수 있다.', () => {
// given
const spinbox = mount(<Spinbox />);
// when
const input = spinbox.find('input');...
handleChangeInput() {
this.setState({
value: 999
});
}
handleChangeInput(e) {
this.setState({
value: e.target.value
});
}
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => {
// given
// when
const spinbox = mount(<Spinbox />);
// 생략…
});
it('입력 폼에 999를 입력...
let spinbox;
beforeEach(() => {
spinbox = mount(<Spinbox />);
});
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … });
it('입력 폼에...
it('입력 폼에 999을 입력할 수 있다.', () => {
// then
const inputNode = input.getDOMNode();
const actualValue = Number(inputNode.valu...
let spinbox;
beforeEach(() => {
spinbox = mount(<Spinbox />);
});
function getValueFromInputNode(input) {
const inputNode ...
세 번째 요구사항
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => {
// given
// when
const input = spinbox.find('input');
input.simulate('change', {...
it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => {
// given
const defaultValue = 200;
// when
const incrementBtn = spinbox.find('[d...
render() {
return (
<div>
<input type="text"
value={ this.state.value }
onChange={ this.handleChangeInput } />
<button dat...
render() {
return (
<div>
<input type="text"
value={ this.state.value }
onChange={ this.handleChangeInput } />
<button dat...
render() {
return (
<div>
<input type="text"
value={ this.state.value }
onChange={ this.handleChangeInput } />
<button dat...
componentWillMount() {
this.state = {
value: 200
};
this.handleChangeInput = this.handleChangeInput.bind(this);
this.handl...
it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => {
// given
const defaultValue = 200;
// when
const incrementBtn = spinbox.find...
handleClickIncrement() {
this.setState({
value: 201
});
}
handleClickIncrement() {
this.setState({
value: this.state.value + 1
});
}
it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … });
it('입력 폼에 999를 입력할 수 있다.', () => { … });
it('입력 폼에 0을 입력할 수 있다.', () => { …...
describe('기본값 >', () => {
it('스핀박스를 생성하면 기본값이 200이어야 한다.', () => { … });
});
describe('값 입력 >', () => {
it('입력 폼에 999를 입력할...
describe(‘값 입력 >', () => {
it('입력 폼에 999를 입력할 수 있다.', () => {
// given
// when
const input = spinbox.find('input');
// … 생...
describe(‘값 입력 >', () => {
let input;
beforeEach(() => {
input = spinbox.find('input');
});
it('입력 폼에 999를 입력할 수 있다.', () ...
describe(‘기본값 >', () => {
it('스핀박스를 생성하면 기본값이 200이어야 한다.', () => { … });
});
describe('값 입력 >', () => {
let input;
beforeE...
얻는 것과 잃는 것
변경의 포인트는 집중
코드는 덜 직관적
it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => {
// given
// when
incrementBtn.simulate('cli...
네 번째 요구사항
기본값은 200
값 입력
증가 버튼을 클릭하여 값이 1 증가
감소 버튼을 클릭하면 값이 1 감소
describe('값 증가 >', () => {
const defaultValue = 200;
let incrementBtn;
beforeEach(() => {
incrementBtn = spinbox.find('[da...
describe('값 감소 >', () => {
const defaultValue = 200;
let decrementBtn;
beforeEach(() => {
decrementBtn = spinbox.find('[da...
class Spinbox extends React.Component {
componentWillMount() {
this.state = {
value: 200
};
this.handleChangeInput = this....
render() {
return (
<div>
<input type="text"
value={ this.state.value }
onChange={ this.handleChangeInput } />
<button dat...
render() {
return (
<div>
<input type="text"
value={ this.state.value }
onChange={ this.handleChangeInput } />
<button dat...
이걸로 충분할까?
불안하다면 망설이지 말고
테스트 작성!
it('감소 버튼을 세 번 클릭하여 값을 3 감소시킬 수 있다.', () => {
// given
// when
decrementBtn.simulate('click');
decrementBtn.simulate('clic...
끝!
감사합니다!
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
Upcoming SlideShare
Loading in …5
×

React로 TDD 쵸큼 맛보기

1,721 views

Published on

TDD로 간단한 스핀박스 React 컴포넌트를 구현하는 과정을 보여드립니다.

Published in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

React로 TDD 쵸큼 맛보기

  1. 1. React로 TDD 쵸큼 맛보기 김훈민@네이버 나는자바스크립트개발자다
  2. 2. 김코딩 스마트에디터 3.0, 프론트엔드 개발 - @네이버 기술 블로그(huns.me)에 아주 가끔 글 쓰기 페이스북 커뮤니티 프론트엔드개발그룹 운영하는 척 네이버 사내 리액트 미트업 운영하는 척 Facebook은 React를 왜 만들었을까 - @FBDG 2015 Angular2 vs React, React vs Angular2 - @Deview 2016
  3. 3. 오늘의 주제는 … 단위 테스트 어떻게 작성하나요? TDD, 왜 해요? TDD 하면 뭐가 좋아요? TDD 하면 설계를 잘 할 수 있나요? TDD 하면 클린 코드를 작성할 수 있나요? TDD 하는 모습이 궁금해요
  4. 4. 오늘의 주제는 … 단위 테스트 어떻게 작성하나요? TDD, 왜 해요? TDD 하면 뭐가 좋아요? TDD 하면 설계를 잘 할 수 있나요? TDD 하면 클린 코드를 작성할 수 있나요? TDD 하는 모습이 궁금해요
  5. 5. 오늘 만들 녀석은, “막막” 간단한 Spinbox 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  6. 6. 환경은…? Webpack ES2015 with babel Jest Enzyme
  7. 7. 들어가기 전에 테스트 설정은 잘 되어있나?
  8. 8. 구현 코드 테스트 코드
  9. 9. it('스핀박스 생성할 수 있다.', () => { // given - 어떤 조건 또는 상황일 때 // when - 어떤 행위를 하면 // then - 결과가 무엇이어야 한다 });
  10. 10. it('스핀박스를 생성할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); });
  11. 11. it('스핀박스 생성할 수 있다.', () => { // setup // exercise // verify });
  12. 12. “어디에서 시작하지?” 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  13. 13. “어디에서 시작하지?” 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  14. 14. it('스핀박스를 생성할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); }); it('스핀박스를 생성할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); }); 복사해서 붙여넣기
  15. 15. it('스핀박스를 생성할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); });
  16. 16. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); });
  17. 17. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { // given // when const spinbox = mount(<Spinbox />); // then const input = spinbox .find('input') .getDOMNode(); expect(input.value).toEqual(200); });
  18. 18. import React from 'react'; const Spinbox = () => ( <div> <input type=“text" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox;
  19. 19. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox;
  20. 20. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { // given // when const spinbox = mount(<Spinbox />); // then const input = spinbox .find('input') .getDOMNode(); const actualValue = Number(input.value); expect(actualValue).toEqual(200); });
  21. 21. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox; 넘나 신경 쓰이는 것!
  22. 22. TDD는 테스트와 구현을 반복하면서 계단을 하나씩 쌓아가는 여정 “테스트 코드”는 어떻게 검증해야 하지?
  23. 23. 두 번째 요구사항 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  24. 24. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { // given // when const spinbox = mount(<Spinbox />); // then const input = spinbox .find('input') .getDOMNode(); const actualValue = Number(input.value); const defaultValue = 200; expect(actualValue).toEqual(defaultValue); });
  25. 25. it('입력 폼에 999를 입력할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then const input = spinbox .find('input') .getDOMNode(); const actualValue = Number(input.value); const defaultValue = 200; expect(actualValue).toEqual(defaultValue); });
  26. 26. it('입력 폼에 999를 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); });
  27. 27. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox;
  28. 28. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox; 아놬! 무상태 컴포넌트!
  29. 29. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox; 안전할 때 까지 되돌리기!
  30. 30. it('입력 폼에 숫자 값을 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); });
  31. 31. it.skip('입력 폼에 숫자 값을 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); });
  32. 32. import React from 'react'; const Spinbox = () => ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox;
  33. 33. import React from ‘react'; class Spinbox extends React.Component { render() { return ( <div> <input type="text" defaultValue="200" /> <button>▲</button> <button>▼</button> </div> ); } } Spinbox.defaultProps = {}; Spinbox.propTypes = {}; export default Spinbox;
  34. 34. it.skip('입력 폼에 숫자 값을 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); });
  35. 35. it('입력 폼에 999를 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '999' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); });
  36. 36. class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div> ); } } // 생략 …
  37. 37. class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ () => { this.setState({ value: 999 }) } } /> <button>▲</button> <button>▼</button> </div> ); } }
  38. 38. class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button>▲</button> <button>▼</button> </div> ); } handleChangeInput() { this.setState({ value: 999 }); } }
  39. 39. it('스핀박스를 생성할 수 있다.', () => { // given // when const spinbox = mount(<Spinbox />); // then expect(spinbox).toBeDefined(); }); it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … }); it('입력 폼에 999를 입력할 수 있다.', () => { … });
  40. 40. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … }); it('입력 폼에 999를 입력할 수 있다.', () => { … });
  41. 41. it('입력 폼에 0을 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '0' } }); // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(0); });
  42. 42. handleChangeInput() { this.setState({ value: 999 }); }
  43. 43. handleChangeInput(e) { this.setState({ value: e.target.value }); }
  44. 44. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { // given // when const spinbox = mount(<Spinbox />); // 생략… }); it('입력 폼에 999를 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // 생략… }); it('입력 폼에 0을 입력할 수 있다.', () => { // given const spinbox = mount(<Spinbox />); // 생략… });
  45. 45. let spinbox; beforeEach(() => { spinbox = mount(<Spinbox />); }); it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … }); it('입력 폼에 999를 입력할 수 있다.', () => { … }); it('입력 폼에 0을 입력할 수 있다.', () => { … });
  46. 46. it('입력 폼에 999을 입력할 수 있다.', () => { // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(999); }); it('입력 폼에 0을 입력할 수 있다.', () => { // then const inputNode = input.getDOMNode(); const actualValue = Number(inputNode.value); expect(actualValue).toEqual(0); });
  47. 47. let spinbox; beforeEach(() => { spinbox = mount(<Spinbox />); }); function getValueFromInputNode(input) { const inputNode = input.getDOMNode(); return Number(inputNode.value); } it('입력 폼에 999를 입력할 수 있다.', () => { // …생략 // then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(999); }); it('입력 폼에 0을 입력할 수 있다.', () => { // …생략 // then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(0); });
  48. 48. 세 번째 요구사항 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  49. 49. it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { // given // when const input = spinbox.find('input'); input.simulate('change', { target: { value: '0' } }); // then const actualValue = getValueFromInputNode(input); expect(actualValue).toEqual(0); });
  50. 50. it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { // given const defaultValue = 200; // when const incrementBtn = spinbox.find('[data-name="increment"]'); incrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 1); });
  51. 51. render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment">▲</button> <button>▼</button> </div> ); }
  52. 52. render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ () => { this.setState({ value: 201 }) } }>▲</button> <button>▼</button> </div> ); }
  53. 53. render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ () => { this.setState({ value: 201 }) } }>▲</button> <button>▼</button> </div> ); }
  54. 54. componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); this.handleClickIncrement = this.handleClickIncrement.bind(this); } render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button>▼</button> </div> ); } handleClickIncrement() { this.setState({ value: 201 }); }
  55. 55. it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { // given const defaultValue = 200; // when const incrementBtn = spinbox.find('[data-name="increment"]'); incrementBtn.simulate('click'); incrementBtn.simulate('click'); incrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 3); });
  56. 56. handleClickIncrement() { this.setState({ value: 201 }); }
  57. 57. handleClickIncrement() { this.setState({ value: this.state.value + 1 }); }
  58. 58. it('스핀박스를 생성하면 기본값은 200이어야 한다.', () => { … }); it('입력 폼에 999를 입력할 수 있다.', () => { … }); it('입력 폼에 0을 입력할 수 있다.', () => { … }); it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { … }); it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { … });
  59. 59. describe('기본값 >', () => { it('스핀박스를 생성하면 기본값이 200이어야 한다.', () => { … }); }); describe('값 입력 >', () => { it('입력 폼에 999를 입력할 수 있다.', () => { … }); it('입력 폼에 0을 입력할 수 있다.', () => { … }); }); describe('값 증가 >', () => { it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { … }); it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { … }); });
  60. 60. describe(‘값 입력 >', () => { it('입력 폼에 999를 입력할 수 있다.', () => { // given // when const input = spinbox.find('input'); // … 생략 }); it('입력 폼에 0을 입력할 수 있다.', () => { // given // when const input = spinbox.find('input'); // … 생략 }); });
  61. 61. describe(‘값 입력 >', () => { let input; beforeEach(() => { input = spinbox.find('input'); }); it('입력 폼에 999를 입력할 수 있다.', () => { … }); it('입력 폼에 0을 입력할 수 있다.', () => { … }); });
  62. 62. describe(‘기본값 >', () => { it('스핀박스를 생성하면 기본값이 200이어야 한다.', () => { … }); }); describe('값 입력 >', () => { let input; beforeEach(() => { input = spinbox.find('input'); }); it('입력 폼에 999를 입력할 수 있다.', () => { … }); it('입력 폼에 0을 입력할 수 있다.', () => { … }); }); describe('값 증가 >', () => { const defaultValue = 200; let incrementBtn; beforeEach(() => { incrementBtn = spinbox.find('[data-name="increment"]'); }); it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { … }); it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { … }); });
  63. 63. 얻는 것과 잃는 것 변경의 포인트는 집중 코드는 덜 직관적 it('증가 버튼을 세 번 클릭하여 값을 3 증가시킬 수 있다.', () => { // given // when incrementBtn.simulate('click'); incrementBtn.simulate('click'); incrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 3); }); 뭘까?
  64. 64. 네 번째 요구사항 기본값은 200 값 입력 증가 버튼을 클릭하여 값이 1 증가 감소 버튼을 클릭하면 값이 1 감소
  65. 65. describe('값 증가 >', () => { const defaultValue = 200; let incrementBtn; beforeEach(() => { incrementBtn = spinbox.find('[data-name="increment"]'); }); it('증가 버튼을 클릭하여 값을 1 증가시킬 수 있다.', () => { // given // when incrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue + 1); }); });
  66. 66. describe('값 감소 >', () => { const defaultValue = 200; let decrementBtn; beforeEach(() => { decrementBtn = spinbox.find('[data-name="decrement"]'); }); it('감소 버튼을 클릭하여 값을 1 감소시킬 수 있다.', () => { // given // when decrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue - 1); }); });
  67. 67. class Spinbox extends React.Component { componentWillMount() { this.state = { value: 200 }; this.handleChangeInput = this.handleChangeInput.bind(this); this.handleClickIncrement = this.handleClickIncrement.bind(this); this.handleClickDecrement = this.handleClickDecrement.bind(this); } render() { … } handleClickDecrement() { this.setState({ value: this.state.value - 1 }); } handleClickIncrement() { … } handleChangeInput(e) { … } }
  68. 68. render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button>▼</button> </div> ); }
  69. 69. render() { return ( <div> <input type="text" value={ this.state.value } onChange={ this.handleChangeInput } /> <button data-name="increment" onClick={ this.handleClickIncrement }>▲</button> <button data-name="decrement" onClick={ this.handleClickDecrement }>▼</button> </div> ); }
  70. 70. 이걸로 충분할까? 불안하다면 망설이지 말고 테스트 작성!
  71. 71. it('감소 버튼을 세 번 클릭하여 값을 3 감소시킬 수 있다.', () => { // given // when decrementBtn.simulate('click'); decrementBtn.simulate('click'); decrementBtn.simulate('click'); // then const actualValue = getValueFromInputNode(spinbox.find('input')); expect(actualValue).toEqual(defaultValue - 3); });
  72. 72. 끝! 감사합니다!

×