Develop/React & React Native

TDD 개발 방법론

안다희 2019. 9. 14. 23:10
728x90

github : https://github.com/daheeahn/TDDRN

 

Test Driven Development

불확실성이 높을 때 진행

 

https://gmlwjd9405.github.io/2018/06/03/agile-tdd.html

 

[Agile] TDD(테스트 주도 개발)란 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

테스트를 많이 하는 개발방법? 그정도의 개념이 아니다.

말그대로 테스트가 주도하는 개발.

테스트를 먼저 작성하고 테스트가 요구하는 만큼의 개발을 진행. 테스트를 작성하지 않은 부분은 구현하지 않는다!

 

Describe it. = RDD Readme Driven Dev

Make it fail *** (테스트 코드가 꼭 실패하도록 해야함)

Make it green

(option) Refactoring

 

Expo 대신 RN Cli (라는 커맨드 툴)로 개발하는 이유

=> Detox와 

Detox에서

Expo는 Expo Launcher라는 앱에서 앱이 실행됨.

TDD의 핵심 요소인 E2E (End To End) 테스트를 하는 Detox(E2E Library)와 매치되지 않음

Detox라는 앱에서 앱의 구동을 확인하고 테스트를 진행하는데 Expo라는 중간 단계의 레이어 때문에

Detox가 앱의 구동을 인지하지 못함.

 

앱 구동시키고 서버만 끄면 터미널에서 react-native start하면 됨~!

 

<TDD에 사용되는 라이브러리 설치>

1. JEST - react native cli 로 하면 기본적으로 jest 포함되어 있음~

https://jestjs.io/

 

Jest · 🃏 Delightful JavaScript Testing

🃏 Delightful JavaScript Testing

jestjs.io

 

2. Enzyme

에어비앤비에서 제공

리액트 컴포넌트 테스트 라이브러리

컴포넌트 렌더링 or 탐색

https://airbnb.io/enzyme/

 

Introduction · Enzyme

Enzyme Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output. Enzyme's API is meant to be intuitive and flexible by

airbnb.io

3. Detox

https://github.com/wix/Detox

 

wix/Detox

Gray box end-to-end testing and automation framework for mobile apps - wix/Detox

github.com

E2E 사용자 관점의 테스트

ios만 지원.

 

<Jest 설정 및 동작확인>

init 한 폴더에 App.js는 src 폴더 만들어서 넣고 // 이것도 일단 보류

__test__ 폴더는 test폴더로 이름 바꿈, 근데 뭔가 설정 많이 바꿔야하고 yarn test도 안돼서 그냥 __있는채로 냅둠

test폴더 안에 있는 App-test.js 근데 강의에선 App.spec.js임. 코드는 같음

 

테스트 코드 작성!

App-test.js

describe('Jest', () => {
  it('is it working?', () => {
    const a = 1;
    expect(a + 1).toBe(2);
  });
});

 

<Enzyme 설치 및 동작확인>

컴포넌트를 렌더링하는 툴!

installation에서 3개 설치

 

tests 폴더에 추가 (안돼서 루트로 ㄱ)

setup.js

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });
// Enzyme docs에 있음!

 

package.json 에 추가

  "jest": {
    "preset": "react-native",
    "setupFiles": [ // here
      "./setup.js" // jest가 이 파일 확인 후 enzyme을 불러온다. // here
    ] // here
  }
  
  // __test__ 안에 setup.js 파일을 인식못해 루트 디렉토리에 넣어놨다.

 

App-test.js

/**
 * @format
 */

import 'react-native';
import {Text} from 'react-native';
import React from 'react';
import App from '../src/App';
import { italic } from 'ansi-colors';

import {shallow} from 'enzyme';

describe('Jest', () => {
  it('is it working?', () => {
    const a = 1;
    expect(a + 1).toBe(2);
  });
});

describe('Enzyme', () => {
  it('is it working?', () => {
    const text = 'some text';
    const wrapper = shallow(<Text>{text}</Text>);
    expect(wrapper.text()).toBe(text);
  });
});

 

<Detox 설치 및 동작확인>

getting started 따라하면 됨. step2 - 1번까지! 그리고

Jest test

detox init -r jest

step2 - 2번 하기 : example -> appname으로!

  "detox": {
    "test-runner": "jest",
    "configurations": {
      "ios.sim.debug": {
        "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/TDDRN.app",
        "build": "xcodebuild -project ios/TDDRN.xcodeproj -scheme TDDRN -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
        "type": "ios.simulator",
        "name": "iPhone 7"
      }
    }
  }
  
  spec.js에서 device랑 element등을 쓸 수 있다. 이것땜에 한참 헤맴!

그러면 package.json 이래야해! TDDRN.app 어떻게 알았냐면 그냥 저 루트 따라가다보면!

 

detox는 async를 지원. 사용자관점에서 테스트하기 때문.

e2e/firstTest.spec.js를 보자!

근데 우리 앱과 맞지 않기 때문에 당연히 실패할 것!

detox test // 앱 구동하고 하기!
    <View style={styles.sectionContainer} testID="welcome">
      <Text style={styles.sectionTitle}>Step One</Text>
      <Text style={styles.sectionDescription}>
        Hi
      </Text>
    </View>
    
    <Fragment>가 최상위인데 얘는 props 많이 못가지고 그 아래에 하면 인식을 못해..
    그래서 위와같이 App.js 일단 하고 testID 저렇게 함!
    

firstTest.spec.js앱 Design 및 Component 정의

// const {device, element, by} = require('detox'); // 이거 안해도 됨 근데 그냥 구글링하다보니.. 근데 device.reload는 없는 함수라네 ㅋㅋ 그러니까 주석!

describe('Example', () => {
  beforeEach(async () => {
    await device.reloadReactNative();
  });

  it('should have welcome screen', async () => {
    await expect(element(by.id("welcome"))).toBeVisible();
  });
});

 

<앱 디자인 및 컴포넌트 정의>

TDD는 functional 한 테스트를 진행!

 

<첫 번째 테스트 코드 작성>

App-test.js

/**
 * @format
 */

import 'react-native';
import {Text} from 'react-native';
import React from 'react';
import App from '../App';
import {shallow} from 'enzyme';

describe('App', () => {
  const wrapper = shallow(<App></App>);
  it('is Text visible?', () => { // RDD describe it!
    expect(wrapper.find('Text').contains('ToDo TDD')).toBeNotVisible(true);
  })

  // it('is AddToDo visible?')
  // it('is ToDoList visible?')
})

yarn test 하면 - e2e테스트도 같이돌아가 (그전에 해둔거)

=> package.json

"test": "jest __tests__/.*.js",

이렇게 바꾸기! __test__ 안에 저런것만 테스트를 돌리겠다!

그러면 이제 저 안에것만 테스트 코드 돌아가겠지

 

그리고 다시 yarn test -> 당연히 실패하는 것을 보고 간다!

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Fragment} from 'react';
import {
  View,
  Text,
  StatusBar,
} from 'react-native';

import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';

const App = () => {
  return (
    <View testID="welcome">
      <Text>ToDo TDD</Text>
    </View>
  );
};

export default App;

ㅇㅁ이러고 다시 yarn test! 그러면 통과! 

ToDo TDD에 대한 테스트 코드만 짰으니까 저렇게 해야해! 그다음 addToDo 먼저 하지 말구

이런식으로 테스트코드작성 - yarn test - 실패 - 테스트코드 성공 위한 코드 짜기 - yarn test - 확인 이렇게 진행하기!

 

github 확인

 

<AddToDo Component>

테스트코드작성 - yarn test - 실패 - 테스트코드 성공 위한 코드 짜기 - yarn test - 확인

역시나 같은 루틴!

 

<ToDoList Component>

 

 

<ToDoItem Component>

 

<<E2E 테스트>>

 

<ToDo 추가 시나리오>

 

<ToDo 완료 시나리오>

 

<ToDo 삭제 시나리오>