inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

백엔드 클린코드, 테스트코드 회고 3주차

ronnie
0

해당 회고는 'Practical Testing: 실용적인 테스트 가이드' 강의에 대한 회고입니다.

시작

이번주부터는 본격적으로 테스트 코드에 대한 강의를 듣게 되었습니다. 테스트 코드에 대해서 적용은 하고 싶지만 접근 방법에 대해서 몰랐던 저에게 한줄기 희망이 된 강의입니다.

 

배운 것들

3주차에서는 테스트가 왜 필요한지, 사용한다면 어떤 이점이 있는지에 대한 학습을 위주로 했습니다.

 

테스트 필요성


테스트 코드가 없는 경우

따라서 테스트코드를 작성하는 것이 좋다

테스트 코드를 작성할 경우

개발 코드에 대한 빠른 피드백을 얻을 수 있으며 자동화를 통해 시스템이 코드를 검증할 수 있도록 할 수 있다

이를 통해 서비스의 안정성을 보장할 수 있다

 

이런 이유에서 테스트 코드를 잘 작성하는 것은 매우 중요하다

무엇을 검증하는지 모호하고 혹은 너무 복잡한 테스트 코드라면 무용지물이 될 수 있다. 혹은 잘못된 검증이 이루어질 수 있다

 

좋은 테스트 코드는 다음과 같다

테스트 코드가 자동화되어 빠른 시간에 버그를 발견할 수 있어 사람이 수동 테스트하는 비용을 줄여준다

내가 남긴 코드와 테스트에 대해 다른 팀원에게도 공유되어 팀 전체의 공유 자산으로 활용된다

짤 때는 귀찮은데 사실 이것이 가장 빠르고 확실하고 좋은 길이다

 

문서로써 테스트

 

@Test
void add() {

    CafeKiosk cafeKiosk = new CafeKiosk();
    cafeKiosk.add(new Americano());

    System.out.println("담긴 음료 수 : " + cafeKiosk.getBeverages().size());
    System.out.println("음료 상세 : " + cafeKiosk.getBeverages().get(0).getName() + ": " + cafeKiosk.getBeverages().get(0).getPrice());
}

이런 테스트 코드의 경우 문제가 있다

심지어 이 코드는 틀릴 일이 없다… 단순한 콘솔 찍기이므로..

이런 수동 테스트는 효율적이지도 못하고 테스트의 역할조차 제대로 하지 못한다

자동화된 테스트로 코드 검증을 자동으로 해주어 개발자의 코드검증 개입을 최소화 해보자

 

 

단위테스트


단위테스트란

경계값에서 테스트하는 것이 중요하다

경계값에서 설정한 예외와 설정한 메시지가 잘 던져지는지 확인하자

 

테스트하기 어려운 영역을 구분하고 분리하자

테스트 가능한 코드에 테스트가 불가능한 부분이 들어온다면 전체 코드가 테스트 불가능하게 된다. 따라서 테스트하고자 하는 영역을 잘 생각해야 한다.

 

테스트 영역을 어디까지 분리하는 것이 좋을까?

기본적으로는 모호하고 어려운 부분을 외부로 분리할 수록 테스트를 할 수 있는 범위는 늘어난다. 하지만 당연히 적당한 멈추는 선이 있을 것이다.

정확하게 어려운 영역이 무엇인지 체크해보고 분리범위에 대해서 알아보자.

 

테스트 어려운 영역

 

테스트 쉬운 영역 (순수 함수)

 

 

TDD


Test Driven Development

테스트 코드를 먼저 작성하고 이후에 프로덕션 코드를 작성해서 테스트 코드를 중심으로 서비스가 구현되는 방법론

cf. 애자일 소프트웨어 개발 선언에서 켄트 백이 소프트웨어 개발 방법으로 XP(extream programming)을 제안했고 이것을 실천할 수 있는 방법 중 하나가 TDD

 

TDD과정

  1. 실패할 수밖에 없는 테스트 작성 (RED)

  2. 테스트를 통과하기 위한 최소한의 코드 작성 (돌아가기만 하면된다. GREEN)

  3. 테스트 통과를 유지하면서 작성한 코드를 개선해 나감 (REFACTOR)

 

TDD의 핵심

내가 작성하는 프로덕션 코드에 대해서 빠르고 자주 피드백을 받을 수 있다

결국 테스트를 잘하기 위한 구조를 고민하게 된다. 시간을 분리했던 코드와 같이 시간이 테스트하기 어려운 부분이라는 것을 먼저 캐치하고 미리 외부로 분리하는 구조를 선택!

 

선 테스트 작성 후 기능 구현

TDD는 구현부가 테스트와 상호작용하며 발전한다

TDD는 클라이언트 관점에서 피드백을 준다

 

DisplayName과 BDD


@DisplayName

 

명사의 나열보다 문장으로 쓰자

 

BDD

 

작성 방법

Given 어떤 환경에서

When 어떤 행동을 진행했을 때

Then 어떤 상태가 일어난다

 

Persistence Layer 테스트


Persistence Layer?

Data Access 역할을 한다

비즈니스 관련 작업을 하는 로직이 포함되어서는 안된다

data에 대한 CRUD에만 집중한 레이어

 

Repository Layer에 대한 테스트

JpaRepository를 상속하는 경우 쿼리 메서드명을 잘 지을 경우 틀릴 일이 없는데 왜 테스트를 진행할까?

→ 간단한 쿼리라면 가시적으로 충분히 확인할 수 있지만 where절의 조건 때문에 메서드명이 길어지거나 파라미터를 잘못 작성할 수도 있다. 날 것 그대로 쿼리를 작성하는 JPQL이나 QueryDSL을 사용하는 경우도 있다

따라서 현재 내가 작성한 쿼리가 잘 동작하는지 테스트하는 것도 있지만 이후 다른 방법으로 사용될 쿼리를 미리 검증하기 위해서도 필요하다.

Repository 테스트의 경우 서버를 띄워서 하지만 DB에 엑세스하는 부분만 보기 때문에 기능 별로 테스트하는 단위 테스트의 느낌이 있다

 

cf. 테스트가 통과할거라고 예상하고 테스트했지만 에러 발생

java.lang.AssertionError: 
Expected size: 2 but was: 4 in:
[sample.cafekiosk.spring.domain.product.Product@7bb996e0,
    sample.cafekiosk.spring.domain.product.Product@589cc8eb,
    sample.cafekiosk.spring.domain.product.Product@44233014,
    sample.cafekiosk.spring.domain.product.Product@6888a33]

아마 설정파일이 디폴트가 local로 되어 있는데 local 설정은 디비 초기화 후 data.sql이 자동실행되어 이미 저장된 데이터들 때문에 에러가 발생하는 것 같다

해당 테스트를 실행할 설정 프로파일을 data.sql이 적용되지 않는 다른 프로파일로 지정해주자!

테스트 클래스에 @ActiveProfiles(”적용할 설정 프로파일이름”)만 해주면 된다

 

마무리 회고


이것저것 할 것이 많은 한 주였습니다. 잘 마무리하고 마지막주인 다음주까지 열심히 달리고 싶습니다.

워밍업 클럽뿐만 아니라 배운 것들을 정리하면서 기록하는 것이 중요하다는 것을 크게 느낍니다. 앞으로도 차곡차곡 쌓아갈 수 있었으면 좋겠습니다. 앞으로도 화이팅!

웹 개발 백엔드 클린코드 테스트코드 워밍업클럽

답변 0