본문 바로가기

(76)
11장 마치며 테스트 우선과 스트레스테스트가 증가할 수록 코드에 대한 신뢰도 함께 증가한다. 이는 개발자의 스트레스를 줄여주고 심리적 안정을 준다.테스트 코드는 회귀 테스트로 사용할 수 있다. 코드를 수정하거나 새로 추가할 때 앞서 작성한 테스트 코드를 사용하면 다른 기능에 문제가 없는지 바로 확인할 수 있다.맺음말TDD는 마치 운동과도 같다. 운동을 꾸준히 하면 건강해지고 체력이 좋아지는 것처럼 TDD도 꾸준히 연습하고 적용해야 실력이 늘고 효과를 볼 수 있다.
10장 테스트 코드와 유지보수 테스트 코드와 유지보수테스트 코드는 그 자체로 코드이기 때문에 제품 코드와 동일하게 유지보수 대상이 된다.이런 악순환이 발생하지 않으려면 테스트 코드 자체의 유지 보수성이 좋아야 한다.좋은 테스트 코드를 만들려면 몇가지 주의해야 할 사항이 있다.변수나 필드를 사욜해서 기댓값 표현하지 않기객체를 생성할 때 사용한 값이 무엇인지 알아보기 위해 필드와 변수를 참조하지 않아도 된다. 단언할 때 사용한 값이 무엇인지 알기 위해 필드와 변수를 오갈 필요도 없다.두 개 이상을 검증하지 않기한 테스트 메서드에서 서로 다른 내용을 검증한다면 각 검증 대상을 별도로 분리해서 테스트의 집중도를 높일 수 있다.물론 테스트 메서드가 반드시 한 가지만 검증해야 하는 것은 아니지만, 검증 대상이 명확하게 구분된다면 테스트 메서드도..
9장 테스트 범위와 종류 테스트 범위테스트의 범위는 테스트의 목적과 수행하는 사람에 따라 달라진다.기능 테스트와 E2E 테스트기능 테스트는 끝(브라우저)에서끝(데이터베이스)가지 모든 구성 요소를 논리적으로 ㅎ완전한 하나의 기능으로 다룬다.기능 테스트는 사용자와 동일한 방식으로 기능을 검증해야 한다.통합 테스트통합 테스트는 시스템의 각 구성 요소가 올바르게 연동되는지 확인한다.서비스 클래스에 대한 테스트가 통합 테스트 예가 될 수 있다.단위 테스트단위 테스트는 개별 코드나 컴포넌트가 기대한대로 동작하는지 확인한다.테스트 범위간 차이단위 테스트는 서버를 구동하거나 DB를 준비할 필요가 없다. 테스트 대상이 의존하는 기능을 대역으로 처리하면 되므로 테스트 실행 속도가 빠르다.통합 테스트나 기능 테스트로는 상황을 준비하거나 결과 확인이..
8장 테스트 가능한 설계 테스트가 어려운 코드하드 코딩된 경로하드 코딩된 경로뿐만 아니라 하드 코딩된 IP주소, 포트번호도 테스트를 어렵게 만든다.의존 객체를 직접 생성테스트를 어렵게 만드는 도 다른 요인은 의존 대상을 직접 생성하고 있다정적 메서드 사용정적 메서드를 사용해도 테스트가 어려워질 수 있다.실행 시점에 따라 달라지는 결과테스트를 실행하는 시점에 다라 테스트 결과가 달라진다면 그 테스트는 믿을 수 없게 된다.역할이 섞여 있는 코드대역을 알맞게 설정해야만 포인트 계산도 가능해진다.그 외 테스트가 어려운 코드이 외에 테스트 대상이 다음과 같다면 테스트가 여려울 수 있다.메서드 중간에 소켓 통신 코드가 포함되어 있다.콘솔에서 입력을 받거나 결과를 콘솔에 출력한다.테스트 대상이 사용하는 의존 대상 클래스나 메서드가 final..
7장 대역 대역의 필요성테스트 대상이 이런 외부 요인에 의존하면 테스트를 작성하고 실행하기 어려워진다.외부 요인은 테스트 작성을 어렵게 만들 뿐만 아니라 테스트 결과도 예측할 수 없게 만든다.테스트 대상에서 의존하는 요인 때문에 테스트가 어려울 때는 대역을 써서 테스트를 진행할 수 있다.영어로 된 테스트 관련 글을 읽으면 test double이란 표현이 자주 나오는데 여기서 double은 본 장에서 설명하는 대역에 해당한다.대역에는 종류는 스텁, 가짜, 스파이, 모의 객체가 존재하는데 각 대역 종류마다 쓰임새가 다르다.대역을 사용한 외부상황 흉내와 결과 검증스텁 : 구현을 단순한 것으로 대체한다. 테스트에 맞게 단순히 원하는 동작을 수행한다.가짜 : 제품에는 적합하지 않지만 실제 동작하는 구현을 제공한다.스파이 :..
6장 테스트 코드의 구성 기능에서의 상황기능은 주어진 상황에 따라 다르게 동작한다.결과에 영향을 줄 수 있는 모든 상황을 완벽하게 찾기 힘들 수도 이지만 가능한 많은 예외 상황을 찾기 위해 노력해야 한다.테스트 코드의 구성요소 : 상황, 실행, 결과 확인기능은 상황에 따라 결과가 달라진다. 테스트 코드는 기능을 실행하고 그 결과를 확인하므로 상황, 실행, 결과 확인의 세 가지 요소로 테스트를 구성할 수 있다.상황, 실행, 결과 확인은 영어 표현 given, when, then에 대응한다.JUnit에서 상황을 설정하는 방법은 테스트할 대상에 따라 달라진다.객체를 생성해서 상황을 설정@BeforeEach를 적용한 메서드에서 상황을 설정상황이 없는 경우도 존재한다.실행 결과를 확인하는 쉬운 방법은 리턴 값을 사용하는 것이다.실행 결과..
4장 TDD, 기능 명세, 설계 기능 명세결과는 여러 형식으로 정의할 수 있다. 가장 쉽게 생각할 수 있는 결과 형식은 리턴 값이다.익셉션을 결과로 사용할 수도 있다.기능 실행 결과에는 변경도 포함한다.이런 변경은 리턴 값으로는 결과를 알 수 없기 때문에 테스트 대상을 실행한 뒤에는 변경 대상에 접근해서 결과를 확인해야 한다.설계는 기능 명세로부터 시작한다.기능 명세의 입력과 결과를 코드에 반영하는 과정에서 기능의 이름, 파라미터, 리턴 타입 등이 결정된다.설계 과정을 지원하는 TDD테스트 코드를 가장 먼저 작성해야 한다는 점이다.테스트를 작성하기 위해 가장 먼저 고민한 것은 테스트 대상이 될 클래스의 이름이었다.테스트 대상이 되는 타입의 이름을 결정한 뒤에는 테스트 코드에서 호출할 메서드를 고민했다.이를 위해 실행 결과를 어떻게 검증..
3장 테스트 코드 작성 순서 테스트 코드 작성 순서2장에서 테스트 코드를 작성한 순서는 다음과 같다.쉬운 경우에서 어려운 경우로 진행예외적인 경우에서 정상인 경우로 진행반대로 어려운 경우를 먼저 시작하거나 정상 상황을 먼저 시작하면 구현 과정이 원활하게 진행되지 않기도 한다.초반에 복잡한 테스트부터 시작하면 안 되는 이유초반부터 다양한 조합을 검사하는 복잡한 상황을 테스트로 추가하면 해당 테스트를 통과시키기 위해 한 번에 구현해야 할 코드가 많아진다.이 테스트를 통과시키려면 어떻게 해야 할까? 가장 빨리 통과시킬 수 있는 방법은 입력 값이 "abcDef12"이면 STRONG을 리턴하는 코드를 추가하는 것이다.한번에 많은 코드를 만들다 보면 나도 모르게 버그를 만들고 나중에 버그를 잡기 위해 많은 시간을 허비하게 된다.구현하기 쉬운 ..
2장 TDD 시작 TDD란?TDD는 기능을 검증하는 테스트 코드를 먼저 만든다고 했다.테스트 대상이 될 클래스 이름, 메서드 이름, 파라미터 개수, 리턴 타입을 고민했다. 또한 새로운 객체를 생성할지 아니면 정적 메서드로 구현할지 등을 함께 고민했다.테스트 코드를 작성한 뒤에는 컴파일 오류를 없애는 데 필요한 클래스와 메서드를 작성했다. 그런 뒤 바로 테스트를 실행했고 테스트에 실패했다.테스트를 통과할 만큼만 코드를 구현했다.실패한 테스트를 통과시킨 뒤에 새로운 테스트를 추가했고 다시 그 테스트를 통과시키기 위한 코드를 작성했다.존재하지 않는 클래스의 이름을 고민하며 바로 테스트 코드를 작성했다. TDD 예: 암호검사기(기능 요구사항이 주어진 상황입니다.)테스트할 기능의 이름을 정해보자검사를 한다는 의미를 표한할 단어를 ..
18장 함수형 관점으로 생각하기 18.1 시스템 구현과 유지보수함수형 프로그래밍이 제공하는 주가용 없음과 불변성이라는 개념이 이 문제를 해결하는 데 도움을 준다.이처럼 공유 가변 데이터 구조를 사용하면 프로그램 전체에서 데이터 갱신 사실을 추적하기가 어려워진다.자신을 포함하는 클래스의 상태 그리고 다른 객체의 상태를 바꾸지 않으며 return 문을 통해서만 자신의 겨로가를 반환하는 메서드를 순수 메서드 또는 부작용 없는 메서드라고 부른다.함수형 프로그래밍은 선언형 프로그래밍을 따른느 대표적인 방식이며, 이전에 설명한 것처럼 부작용이 없는 계산을 지향한다.18.2 함수형 프로그래밍이란 무엇인가?실제 부작용이 있지만 아무도 이를 보지 못하게 함으로써 함수형을 달성할 수 있다.함수나 메서드는 지역 변수만을 변경해야 함수형이라 할 수 있다.