Software Engineering 79

[단위 테스트] 4-2. 좋은 단위 테스트의 4대 요소: 이상적인 테스트

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.3. 이상적인 테스트를 찾아서테스트의 가치좋은 단위 테스트의 4대 특성을 곱하여 얻은 결과 (추정치)소수의 가치있는 테스트가 평범한 테스트보다 프로젝트 성장에 훨씬 더 효과적테스트 스위트에 테스트를 계속 둘지 여부를 결정할 수 있음임계치를 충족하는 테스트만 두어, 책임을 적절하게 맡도록 해야 함 이상적인 테스트를 만들 수 있는가?이상적인 테스트는 네 가지 특성 모두에서 최대 점수를 받는 테스트실제로는 세 가지 특성(회귀 방지, 리팩터링 내성, 빠른 피드백)이 서로 충돌함 모두를 동시에 만족하는 것은 불가능함 핵심 전략항목설명하나의 특성을 완전히 버릴 수 없다하나를 버리면 곱셈 규칙(가치의 곱)에 의해 전체 테스트의 유용성이 0에 가까워짐리..

[단위 테스트] 4-1. 좋은 단위 테스트의 4대 요소: 4대 요소

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.1. 좋은 단위 테스트의 4대 요소요소설명문제 상황 / 원인해결 방안회귀 방지코드 수정 후 기능이 깨지는 것을 방지하는 테스트 역할코드 수정 후 테스트는 통과하지만 실제로는 동작하지 않음기존 동작을 명확히 검증리팩터링 내성코드 내부 구현이 변경되어도 테스트가 정상적으로 동작해야 함리팩토링 시 내부 동작 테스트 깨짐결과 기반 테스트구현 디테일 분리빠른 피드백테스트가 빠르게 실행되어야 실시간 피드백이 가능외부 의존성으로 느려지거나 무거워짐의존성 분리 (Fake/Stub)유지 보수성가독성, 유지 비용, 실행 비용 등을 평가 └ 이해 난이도테스트가 얼마나 직관적이고 쉽게 읽히는가복잡한 준비 코드AAA 패턴 사용설명적인 테스트 이름└ 실행 난이도..

[단위 테스트] 3. 단위 테스트 구조

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.1. AAA 패턴테스트 코드를 세 단계로 구분하여 작성하는 패턴스위트 내 모든 테스트가 단순하고 균일한 구조를 갖게함단계설명Arrange테스트 대상(SUT) 및 의존성 설정Act테스트 대상 메서드 실행Assert결과 확인 (반환 값, 상태 변화, 호출 여부 등) 2. 권장 사항항목권장 사항이유 및 설명구절 수 제한한 테스트에는 한 act만단일 동작 검증조건문 회피분기문 피하기 (if, switch 등)복잡도 증가 (한 테스트에 여러 경우를 넣지 말고 분리해야 함)메서드 캡슐화복잡한 검증 로직 분리 (private 메서드로)반복 제거가독성 향상목적 명확화불변 위반 방지여러 호출로 결과 만들지 말 것불변성 깨질 수 있음 (한 동작 = 한 결과..

[단위 테스트] 2-2. 단위 테스트란 무엇인가: 런던파와 고전파

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다. 2. 런던파와 고전파격리 방식에 따라 크게 두 가지 스타일로 나뉨항목런던파 (London School)고전파 (Classical School)중심 철학상호작용 기반 (행위 검증)상태 기반 (결과 검증)테스트 단위코드 조각단일 동작TDD 방식하향식 (전체 설계/인프라 → 상위 → 하위)상향식 (하위 → 상위 → 전체 설계/인프라)의존성 처리모든 의존성을 Mock으로 대체공유 의존성만 Fake/Stub으로 격리 (나머지는 실제 객체 사용)장점빠르고 정밀함현실적인 테스트단점과잉 명세구현 의존성 높음문제 원인 추적이 어려움 예제) EmailSender더보기런던파// 인터페이스public interface EmailSender { void ..

[단위 테스트] 2-1. 단위 테스트란 무엇인가: 단위 테스트란

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.1. '단위 테스트'의 정의작은 코드 조각을 대상으로, 독립적으로 빠르게 검증하는 테스트 격리성독립적으로 실행 가능한 상태✅ 실행 환경이나 다른 테스트에 영향받지 않음✅ 순서에 의존하지 않아야 함 2. 의존성내 코드가 직접 사용하지만, 내가 직접 구현하지 않은 것 (외부에 기대는 요소)✅ 단위 테스트의 격리성을 보장하기 위해 실제 의존성과 함께 동작하지 않음➡️ 테스트 대역으로 대체하여 핵심 로직만 집중적으로 검증의존성 종류설명문제점예시해결 방법공유 의존성테스트 간에 공유되는 상태테스트 간 간섭 발생- 정적 가변 필드- 싱글턴- 전역 변수- 공유 제거- 테스트마다 초기화비공개 의존성코드에 드러나지 않는 숨은 의존성실패 원인 파악 어려움- ..

[단위 테스트] 1-2. 단위 테스트의 목표: 커버리지 지표

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다.1. 테스트 스위트 품질 측정커버리지 지표테스트에 의해 실행된 코드의 비율✅ 테스트 스위트의 품질을 평가하는데 자주 사용됨종류항목설명공식코드 커버리지전체 코드 중, 테스트 실행 시 실행된 라인의 비율실행된 코드 라인 수 / 전체 코드 라인 수분기 커버리지모든 분기가 테스트되었는지 측정➡️ 코드 커버리지보다 더 정밀하고 정확한 테스트 평가 가능통과한 분기 수 / 전체 분기 수 예시) 분기 커버리지더보기public boolean isEligibleForDiscount(int age, boolean hasCoupon) { if (age >= 18) { // 분기 1 if (hasCoupon) { // 분기 2 ..

[단위 테스트] 1-1. 단위 테스트의 목표: 단위 테스트 목표

블라디미르 코리코프 님의 "단위 테스트" 책을 정리한 포스팅입니다. 1. 소프트웨어 엔트로피코드베이스는 시간이 흐를수록 복잡성과 불확실성이 증가하는 경향이 있음 흐름⚠️ 엔트로피 증가: 코드 변경 시, 복잡도가 증가함➡️ 예기치 못한 문제 발생: 복잡한 코드에 새 기능을 추가하면 부작용 발생 가능성이 커짐➡️ 신뢰성 하락: 테스트가 없는 프로젝트는 처음엔 빠르게 개발되지만, 시간이 갈수록 코드 작성이 급격히 느려짐 2. 테스트 코드 작성의 중요성새로운 기능을 개발할 때마다 새로운 버그 가능성이 존재함✅ 코드 설계가 적절하지 못하면 테스트 코드 작성이 어려워지고, 테스트 코드 자체도 오류를 포함할 수 있음⚠️ 잘못된 테스트 코드는 신뢰성을 떨어뜨려, 상황을 더 악화시킬 수 있음➡️ 테스트 코드의 품질도 본..

[헤드퍼스트 디자인 패턴] 12-6. 비지터 패턴

에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다 1. 비지터 패턴다양한 객체에 새로운 기능을 추가할 경우 구성요소Visitor새로운 기능을 추가하는 객체각 객체의 accept 메소드를 호출하여 자신을 전달 ConcreteVisitor각 Element에 대해 수행할 작업 정의 Elementaccept() 메서드를 정의한 객체자신이 받아들일 수 있는 비지터를 정의 장점객체의 구조를 변경하지 않음새로운 기능 추가 용이비지터만 추가하면 됨 2. MenuMenuComponent// 메뉴 항목을 나타내는 요소 클래스public abstract class MenuComponent { public abstract void accept(MenuVisitor visitor);} Menupubl..

[헤드퍼스트 디자인 패턴] 12-5. 프로토타입 패턴

에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다1. 프로토타입 패턴어떤 객체의 인스턴스를 만들 때 자원이 많이 들거나 복잡할 경우 장점성능기존 인스턴스를 복사 (생성 X)클라이언트 코드에서 어떤 클래스의 인스턴스를 만드는지 모름 2. GameMonster// Prototype 인터페이스public interface Monster extends Cloneable { Monster clone(); void display(); // 몬스터의 모양을 화면에 표시}// 기본 몬스터 클래스public class DefaultMonster implements Monster { private String shape; // 몬스터의 모양 private String color;..

[헤드퍼스트 디자인 패턴] 12-4. 플라이웨이트 패턴

에릭 프리먼 님의 "헤드퍼스트 디자인 패턴" 책을 정리한 포스팅 입니다1. 플라이웨이트 패턴객체를 최대한 재사용하여 메모리를 절약하는 디자인 패턴인스턴스 하나로 여러 개의 가상 인스턴스를 제공하고 싶을 경우 구성 요소Intrinsic State여러 객체 간에 공유되는 상태불변 Extrinsic State공유되지 않고 개별 객체에 따라 달라지는 상태호출 시 클라이언트가 전달 2. TreeManagerimport java.util.ArrayList;import java.util.List;public class TreeManager { private final List trees = new ArrayList(); // 나무 추가 (외재적 상태를 포함한 TreeLocation 객체 생성) pub..