본문 바로가기
테스트코드

[단위테스트 2장] 단위 테스트란 무엇인가

by pius712 2023. 7. 2.

2.1 단위테스트란?

  • 작은 코드 조각(단위) 검증
  • 빠르게 수행
  • 격리된 방식으로 처리하는 자동화 테스트

격리라는 주체를 어떻게 보느냐에 따라 고전파와 런던파로 나뉘게 됨.

 

저자는 고전파의 입장으로 책을 설명하고 있다. 

 

 

2.2 런던파 vs 고전파

  격리주체 단위의 크기 테스트 대역 사용 대상
런던파 단위 단일 클래스 불변 의존성 외의 모든 의존성
고전파 단위 테스트 단일 클래스 또는 클래스의 세트 공유 의존성

 

런던파

한번에 하나의 클래스를 테스트함

  • 입자성이 좋음, 한번에 한 클래스만 확인
  • 서로 연결된 클래스의 그래프를 테스트하기 좋음
  • 테스트가 어떤 기능이 실패했는지 확인하기 좋음

TDD 설계 방식

하향식

  • 상위 레벨 부터 하위레벨에 대한 것은 목을 만들어서 협력자를 만들어 진행
  • 모든 클래스 구현할 때까지 클래스 그래프를 구성해나감

고전파

다른 테스트와의 격리

  • 테스트 간에 간섭이 없어야한다.
  • 공유 의존성은 대체.

TDD 설계 방식

상향식

  • 테스트에서 실제 객체를 다뤄야함
  • 도메인 모델을 시작으로 최종 사용자가 사용할 때까지 계층을 쌓아나감

2.2 의존성

공유 의존성

  • 테스트간 공유되고 서로 결과의 영향을 미치는 수단
  • 데이터베이스, 정적 필드 등등

static field 의 경우, 테스트 간 공유될 수 있기 때문에, 공유 의존성이라고 할 수 있다. 
그 외에도 데이터베이스도 하나의 커넥션으로 동작하는 경우 공유 의존성이 될 수 있다. 

class Foo {
    static count = 0;
    run(str: string) {
        Foo.count++;
        return str;
    }
}

 

describe('Foo test', function () {

    it('run 수행시 무엇을 해야한다.', async () =>{
		const sut = new Foo();
        const result = sut.run('hello');
        console.log(Foo.count); // 1
    });

    it('run 수행시 무엇을 해야한다.', async () =>{
		 const sut = new Foo();
        const result = sut.run('bye');
       	console.log(Foo.count); // 2
    });

});

 

 

비공개 의존성 (공유 의존성의 반대)

  • 공유하지 않는 의존성
  • 값 or 값 객체 or 변경가능한 의존성

만약 인스턴스 변수, 혹은 readonly와 같은 변수들은 테스트 간에 공유되지 않는다. 

 

프로세스 외부 의존성

  • 실행되는 애플리케이션 외부의 의존성
  • 프로세스 외부 의존성과 공유 의존성은 정확히는 다른 개념으로, 
    실제 프로세스가 별도로 뜨는 외부의 의존성에 대해서 설명한다. 
  • 예시) 데이터베이스, 레디스 등등.. 

협력자

  • 공유 가능하거나 변경 가능한 의존성
  • 시간에 따라서 상태가 변하는 것

 

2.3 통합테스트

런던파

협력자를 사용하는 모든 테스트를 통합테스트로 여김

→ 대부분의 고전파식 단위테스트는 통합테스트

 

고전파

단위테스트

  • 단일 동작 단위를 검증
  • 빠르게 수행
  • 다른 테스트와 별도로 처리

→ 통합테스트라는 것은 위 기준 중 하나 이상을 충족하지 않는 테스트

 

아래의 코드가 있다고 가정해볼때,  

class Foo {
  constructor(private readonly reader: Reader,
  	private readonly notifier: Notifier ) {}
  
  run(callbackUrl:string, pattern :RegExp) {
    const item = this.reader.read(pattern)
    
    this.notifier.notify(callbackUrl, item);
  }
}

// 데이터베이스 커넥션
class Reader { 
  read() {
   // 구현 생략
  }
}

// 네트워크 의존성
class Notifier { 
  notify() {
     // 구현 생략
  }
}

 

테스트 방식이 런던파와 고전파는 서로 다르다. 

  describe('테스트 비교', async ()=> {
    it('고전파 스타일', async () => {
    	// 실제 객체를 사용함. (협력 객체)
        const sut = new Foo(new Reader(), new Notifier());
        const result = sut.run('callbackUrl', new RegExp(''));
        expect(result).toEqual({});
    });

    it('런던파 스타일.', async () => {
        // 목을 사용하여, 의존성을 대체함. 
        const sut = new Foo(new MockReader(), new MockNotifier());
        const result = sut.run('callbackUrl', new RegExp(''));
        expect(result).toEqual({});
    });
  })

 

2.4 엔드 투 엔드 테스트

  • 통합 테스트의 일부
  • 모든 의존성에 전부 or 대부분 접근

'테스트코드' 카테고리의 다른 글

[단위테스트 1장] 단위테스트의 목표  (0) 2023.07.02