Skip to content

always-awake/Test-Driven-Development

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

파이썬을 이용한 클린 코드를 위한 테스트 주도 개발

이 책의 목적

  • 보다 나은 웹 애플리케이션과 행복한 개발자를 만들기 위한 웹 개발 방법론을 전달하는 것
  • '안정적으로 동작하는 깔끔한 코드 작성'을 위한 TDD 사용법에 대해 다룸
  • Django, 셀레늄, jQuery, 모크 등의 툴을 사용해서 실제 웹 애플리케이션을 개발해가면서 실용적인 예제 코드들을 다룸

이 책의 구성

  • 1부(1장~6장): 기초편
    • TDD를 이용해서 간단한 웹 애플리케이션 구축
    • 셀레눔 기반으로 기능 테스트 작성
    • 철저한 단위 테스트를 기반으로 하는 Django(모델, 뷰, 템플릿) 기초를 다룸
  • 2부(7장~14장): 웹 개발 핵심편
    • 웹 개발의 필수 기술에 대해 다룸
    • 테스트가 어떻게 웹 개발에 도움이 되는지 학습
    • 정적 파일, 배포, 폼 데이터 검증, 데이터베이스 마이그레이션, 자바스크립트 테스트를 중점적으로 다룸
  • 3부(15장~20장): 고급편
    • 모킹(Mocking), 외부 인증 시스템 통합, AJAX, 테스트 픽스처(fixtures), TDD 상호작용, 지속적 통합(CI) 등에 대해 다룸

개발환경

테스트 주도 개발이란?

TDD is an awareness of the gap between decision and feedback during programming, and techniques to control that gap. --Test Driven Development by Example, p xxi

TDD란 프로그래밍 의사결정과 피드백 사이의 간극에 대한 인식이자, 이 간극을 제어하기 위한 기술이다.

  • 프로그래밍을 하는 과정에서 일어나는 의사결정들(변수 이름, 함수 길이 등)
  • 그러한 의사결정을 내린 후에 돌아오는 피드백(컴파일 에러, 버그, 깔끔한 코드, 금전적 손실 등)
  • 그리고 이 둘 사이의 간극

즉, 이 세가지를 잘 의식하면서 적극적으로 제어하려는 노력, 이것이 테스트 주도 개발이라는 것이다.

기능테스트(Functional test)란?

  • 애플리케이션이 어떻게 **동작(functions)**하는지 사용자 관점에서 확인하는 것
  • 승인 테스트, 종단간 테스트라고 부르기도 함
  • 블랙박스 테스트라고 부르기도 함
    • 시스템 내부에 대해선 전혀 알지 못하기 때문
  • 중요한 것은 이 테스트들이 전체 애플리케이션이 어떻게 동작하는지를 외부 사용자 관점에서 확인하는 테스트라는 것
  • 제대로 된 기능성을 갖춘 애플리케이션을 구축하도록 돕고, 그 기능성이 망가지지 않도록 보장

단위 테스트(Unit Tests)란?

  • 프로그래머 관점에서 그 내부를 테스트하는 것
  • 자동화된 테스트 실행자에 의해 실행됨
  • 단위 테스트는 기능 테스트에 의해 파생되며 더 실제 코드에 가깝다.
  • 단위 테스트의 전형적인 구조
    • 설정(Setup): 테스트 설정을 위한 코드 그룹
    • 처리(Exercise): 실제 함수를 호출하는 코드 부분
    • 어설션(Assert)
  • 각각의 단위 테스트가 한 가지만 테스트 하는 것이 좋은 단위 테스트이다.
    • 테스트에 많은 어설션이 있는 경우, 앞에 있는 어설션이 실패하면 뒤에 있는 어설션 상태를 파악할 수 없음

유용한 TDD 개념

  • 사용자 스토리 (User Story)
    • 사용자 관점에서 어떻게 애플리케이션이 동작해야 하는지 기술한 것
    • 기능 테스트 구조화를 위해 사용
  • 예측된 실패(Expected failure)
    • 의도적으로 구현한 테스트 실패를 의미
  • TDD 주기
    • 실패 테스트를 작성한 후 테스트를 통과할 수 있는 코드를 작성하는 과정

단위 테스트-코드 주기

  • 터미널에서 단위 테스트를 실행해서 어떻게 실패하는지 확인
  • 편집기상에서 현재 실패 테스트를 수정하기 위한 최소한의 코드 변경
  • 코드 품질을 높이고 싶다면 코드 변경을 최소화 -> 변경된 코드를 하나하나 테스트에 의해 검증
  • 레드(Red), 그린(Green), 리팩터(Refactor)
    • 레드: 실패할 단위 테스트를 작성함으로써 작업 시작
    • 그린: 이 테스트를 통과할 최소 코드 작성, 편법이라도 상관없음
    • 리팩터: 코드를 리팩터링해서 이해할 수 있는 코드로 만든다.
      • 중복 제거: 테스트 코드와 애플리케이션 코드 간 중복 제거
      • 삼각법: 테스트가 상수 같은 편법 코드를 허용하지 않음 -> 다른 테스트를 작성해서 더 나은 코드를 작성하도록 함

리팩터링(Refactoring)이란?

  • 기능(결과물)은 바꾸지 않고 코드 자체를 개선하는 작업을 일컫는다.
  • 리팩터링은 테스트와 함께!
  • 앱 코드와 테스트 코드를 한 번에 동시 수정하는 것이 아니라 하나씩 수정해야 함
  • 리팩터링 전에는 반드시 커밋하는 습관 갖기

Django의 Template

  • 템플릿은 Django의 매우 강력한 기능 중 하나
  • 파이썬 변수를 HTML 텍스트로 변경해주는 기능이 있음
  • render 함수
    • 첫 번째 인수: 요청(request)
    • 두 번째 인수: 렌더링할 템플릿 명
    • Django는 앱 폴더 내에 있는 templates 폴더를 자동으로 검색
    • 템플릿 콘텐츠 기반으로 HttpResponse를 만들어줌

객체 관계형 맵핑(Object-Relational Mapper, ORM)이란?

  • 데이터베이스의 테이블, 레코드, 칼럼 형태로 저장되어 있는 데이터를 추상화
  • ORM을 이용하면 익숙한 객체 지향 코딩 방식을 이용해서 데이터베이스 조작, 처리 가능
  • 데이터베이스는 클래스로 표현하고, 칼럼은 속성, 레코드는 각 클래스의 인스턴스로 표현
  • 클래스 속성인 .objects을 통해 데이터베이스 쿼리 가능

마이그레이션(Migration)이란?

  • model.py 파일에 적용된 내용을 기반으로, 사용자가 테이블칼럼을 삭제 및 추가할 수 있도록 함
  • 데이터베이스를 위한 버전 관리 시스템
  • 상용 서버에 배포한 데이터베이스를 업그레이드할 때 특히 유용

유용한 TDD 개념

  • 퇴행(Regression)
    • 동작하고 있던 애플리케이션 처리가 새롭게 추가된 코드에 의해 망가지는 것을 의미
  • 예상하지 못한 실패(Unexpected failure)
    • 생각하지 못한 방법으로 테스트가 실패하는 것을 의미
    • 이는 테스트를 잘못 작성했거나, 테스트 자체가 코드 퇴행을 발견했다는 것, 애플리케이션 코드 수정이 필요하다는 의미
  • 삼각법(Triangulation)
    • 기존 코드에 구체적인 테스트 케이스를 추가해서 일반화(편법이 될 수도 있는)한 처리를 정당화하는 것
  • 스트라이크 세 개면 리팩터(Three strikes and refactor)
    • 중복 코드를 제거해야할 시기를 말해주는 일반적인 규칙
    • 세 번째 동일 코드가 사용된다면 -> 리팩터링 확신

LiveServerTestCase

  • 자동으로 테스트용 데이터베이스를 생성하고(단위 테스트와 마찬가지로), 기능 테스트를 위한 개발 서버 가동
  • LiveServerTestCase는 Django의 manage.py를 이용해 실행
  • Django 1.6 부터는 테스트 실행자가 'test'로 시작하는 파일을 자동 탐색

애자일(Agile)이란?

  • 개발 초기 단계에 요구사항 분석과 설계에 많은 시간을 할애하는 전통적 소프트웨어 공학과 상반된 방법론
  • 애자일은 이론보다는 실제 상황을 통해 문제를 해결하려는 것을 근간으로 하고 있음
  • 가능한 빨리 사용자가 애플리케이션을 접할 수 있도록 하는 것이 특징
  • 긴 설계 과정 대신에, "동작하는 최소한의 애플리케이션"을 빠르게 만들고, 이를 이용해서 얻은 실제 사용자 의견을 설계에 점진적으로 반영해가는 방식
  • YAGNI: "You ain't gonna need it"

REST(Representational State Transfer)란?

  • (REST 정리 글)
  • 웹 설계 방법 중 하나
  • 일반적으로 웹 기반 API를 이용해서 설계하도록 유도
  • 데이터 구조를 URL 구조에 일치시키는 방식

테스트 격리(Test Isolation)와 전역 상태(Global State)

  • 각각의 테스트가 다른 테스트에 영향을 끼쳐서는 안된다는 것을 의미
  • 각 테스트 마지막에는 영구적인 상태를 초기화해야 하다는 것
  • Django의 테스트 실행자는 각 테스트 결과물을 제거해주는 테스트 데이터베이스를 생성함으로써 이 문제를 해결

스모크(Smoke) 테스트란?

Django 템플릿 상속 기능을 이용해야할 상황

  • 다수의 템플릿 각각에 전체 상용구 코드(Boilerplate)를 추가하는 것은 바람직하지 않음
  • 템플릿 간 공통 부분을 추출해서 base.html을 생성하고, 'blocks'이라는 연속 영역 정의 -> 이는 자식 템플릿의 콘텐츠를 추가하거나 연동할 수 있는 영역
  • 다른 템플릿에서 base.html 상속
  • 자식 템플릿은 커스터마이징을 위해 'block'설정

Django의 정적 파일

  • Django의 개발 서버를 이용하고 있는 동안은(manage.py runserver), Django가 제공하는 솔루션을 이용해서 정적 파일을 찾을 수 있다.
  • 즉, Django가 앱의 서브 폴더를 모두 검색해서 static이라는 폴더를 찾는다.
  • Django/runserver는 요청 url이 settings.py의 'STATIC_URL' 접두사로 시작되면, 이 요청이 정적 파일을 위한 것이라 생각하고, 해당 파일을 검색하여 서빙
  • 기능 테스트 실행시
    • runserver와 달리 LiveServerTestCase는 자동으로 정적 파일을 찾을 수 없음
    • StaticLiveServerCase를 이용해 테스트 함

collectstatic과 다른 정적 디렉터리

  • 실제 운영 중인 서버에서 Django가 정적 콘텐츠를 제공하도록 하는 것은 매우 느리며 비효율적이다.
    • 아파치(Apache)나 Nginx 같은 웹 서버도 같은 역할을 할 수 있다.
    • 직접 정적 파일을 호스팅하는 대신에 CDN(Content Delivery Network)에 업로드해서 호스팅하는 방법도 있다.
  • 따라서, 여러 앱에 존재하는 모든 정적 파일을 한 곳에 모아서 배포용으로 만들어 둘 필요가 있고, 이 작업을 collectstatic 명령으로 수행함
  • collectstatic명령으로 수집된 정적 파일들은 settings.py의 STATIC_ROOT에서 설정된 위치에 모임

디자인 및 레이아웃 테스트에 대한 정리

  • 디자인과 레이아웃용 테스트는 작성할 필요 없음
  • 최소한의 '스모크 테스트'를 이용해서 CSS와 정적 파일이 동작하는지만 확인하는 것이 좋다.
  • 작은 스타일링 코드를 적용하기 위해 다량의 클라이언트 측 자바스크립트가 요구되는 경우, 이를 위한 테스트도 반드시 필요
  • 디자인과 레이아웃이 동작한다는 것을 확신할 수 있게 하는 최소한의 테스트만 작성
  • 디자인과 레이아웃을 자유롭게 변경할 수 있도록 하고, 변경 시마다 테스트 하거나 이전 상태로 돌리는 등의 작업은 배제

배포 시 주의사항

정적 파일(CSS, 자바스크립트, 이미지 등등)

  • 이 파일들을 제공하기 위해 웹 서버에 특수한 설정 필요

데이터 베이스

  • 권한이나 경로 문제가 있을 수 있으며, 배포 시 테스트 데이터 관리에 유의해야 함

의존 관계

  • 개발한 소프트웨어와 연계돼 있는 패키지를 서버에 설치해야 하며, 패키지 버전도 확인해야

주의사항에 대한 해결방법

  • 신제 운영 사이트에서 사용하는 환경과 동일한 환경의 스테이징(staging) 사이트이용
    • 이를 통해 '실제' 사이트에 배포하기 전에 모든 것이 제대로 동작하는지 테스트할 수 있음
  • 스테이징 사이트에 대해 기능 테스트 실행
    • 이를 통해 서버상에 있는 코드와 패키지가 제대로 된 것임을 다시 확인할 수 있음
    • 레이아웃용 '스모크 테스트'를 통해 CSS가 정상적으로 로딩되는지 알 수 있음
  • Virtualenv를 이용해 하나 이상의 파이썬 애플리케이션이 동작하고 있는 장비에서 패키지 및 패키지 의존 관계를 관리할 수 있음
  • 자동화
    • 자동화된 스크립트를 이용해서 신규 버전을 배포하고, 이를 스테이징 서버와 운영 서버에 동시에 배포
    • 운영 서버와 스테이징 서버를 가능한 동일 상태로 유지

서버 구축하기 (AWS)

  • AWS(Amazon Web Services)
    • 아마존 웹 서비스는 아마존닷컴이 제공하는 각종 원격 컴퓨팅 서비스(웹 서비스)이다.
    • 아마존 웹 서비스는 다른 웹 사이트나 클라이언트 측 응용 프로그램에 대해 온라인 서비스를 제공하고 있다.
    • 아마존 웹 서비스의 상당수는 최종 사용자에 직접 공개되는 것이 아니고, 다른 개발자가 사용 가능한 기능을 제공하는 플랫폼을 제공하는 Paas다.
    • 아마존 웹 서비스의 각종 서비스는 REST 프로토콜 및 SOAP 프로토콜을 통해 접근, 이용 및 관리가 가능하다.
    • 비용은 실제 사용량에 따라 결정되며, 일부 서비스의 경우 미리 고정된 금액을 지불하는 형태도 있음
  • 아키텍처(서버 구성)
    • Nginx와 uWSGI는 유직스 유닉스 도메인 소켓으로 통신
    • Supervisor을 이용해 Nginx와 uWSGI 프로세스가 다운되면, 자동으로 재시작해줄 수 있도록 함
클라이언트 - Nginx - uWSGI - Django

배포 자동화

  • Fabric
    • 페브릭은 파이썬 스크립트를 이용ㅎ해서 서버상에서 명령어를 실행하게 해준다.
    • 서버 관리 자동화를 위한 훌륭한 툴이다.
    • fabfile에 있는 함수들은 상단부터 차례대로 커맨드라인에서 호출되기 때문에, 밑줄(_)을 이용해서 공용 API와 섞이지 않도록 한다.
    • mkdir -p 를 이용
      • 여러 단계로 이루어진 디렉터리의 경우 상위 디렉터리까지 작성(예: mkdir -p /tmp/foo/bar는 bar뿐만 아니라 부모 디렉터리인 foo도 생성)
      • mkdir 명령어로 만드려는 디렉터리 이름이 이미 존재하더라도 오류를 발생시키지 않음(예: 이미 bar 폴더가 있어도 에러가 발생하지 않는다.)
  • 멱등성(Idempotency)
    • 멱등성이란 몇 번을 실행해도 결과가 같은 것을 의미한다.
    • 자동화 스크립트는 신규 사이트뿐만이 아니라 기존 사이트에서도 동작하는 것을 의미
    • 기존 서버에 배포 스크립트를 실행한다면, 스크립트 설계 시 두 가지 측면을 고려해야 한다.
    • 서버에 신규로 설치하는 경우와 이미 설치 버전이 있는 경우
  • 설정 파일 버전 관리
    • 설정 파일이 서버에만 존재하는 일은 없어야 한다.
    • 애플리케이션 핵심 파일이기 때문에 다른 코드와 같이 버전 관리를 해야 한다.
  • 프로비저닝 자동ㅎ화
    • 신규 서버 가동과 필요 소프트웨어 설치까지 모두 자동화되어야 한다.
    • 또한 호스팅 제공자의 API연계성도 확인해야 한다.
  • 관리 툴 설정
    • 페브릭은 매우 유연한 툴이긴 하지만 그 로직이 스크립트에 기반하고 있다.
    • 선언적인 작성이 가능해서 작업을 더 쉽게 해주는 툴들도 있다.
    • Ansible, Vagrant, Chef, Puppet 등등

기능 테스트를 여러 파일로 분할

  • 기존에 하나의 파일에 모든 기능 테스트 함수를 정의했지만, 각 테스트 기능 단위로 새로은 class를 만들고 테스트를 나눈다.
  • 초기 세팅을 위한 클래스를 다른 테스트 클래스들이 상속받도록한다.
  • 나누어진 클래스들은 각각 다른 파일에 존재한다.
  • 기능 테스트를 기능 단위로 여러 파일로 분할하게 되면, 특정 테스트에만 관심이 있다면 모든 테스트를 실행해서 해당 테스트가 실행될 때까지 기다릴 필요가 없다.

About

파이썬을 이용한 클린 코드를 위한 테스트 주도 개발 - Pyhton/Django

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published