[망했어요 2] Software Testing

LILO Ghim·2022년 3월 16일
1
post-thumbnail

오늘의 주제와 너무 잘어울리는 내 사랑 짤

두 번째 면접 당시, 나로 하여금 가장 큰 충격이었던, 
뭔가 밥상 걷어 차버린 느낌이 들게 했던, 
프로젝트 내에서 구현하였던 Kakao 소셜 로그인 API에 대하여 
작성했던 test code를 설명하라는 면접 질문.

"본인이 작성하셨나요?" 
"네 직접 작성하였습니다."
"설명해보시겠어요?"
"ㅏㅁ이러ㅏㅣㅇ;ㅓ 먼ㅇ;ㅣ럼ㄴ아ㅣ;어님;라ㅓㅇ마ㅓㄹ ㅏㅁ이너라ㅣㄴ어ㅣ라 죄송합니다."
"이렇게 이렇게 해서 이렇게 이렇게 값을 비교 하도록 짜신 거죠?"
"네 맞습니다"

그래서
망했어요 두 번째는
software testing 세션 다시 듣기였다.
(왜 다른 기수 세션이 더 재밌는것 같지. 기분탓인가)

이미 한차례 블로깅을 한 적이 있었는데,
이번엔 망했어요임

세션 내용 & unittest와 함께 했던 총 5개 썰 중 두 가지 썰로 구성
(아 이제 이거까지 육썰이구나 흫 ^^)

What is Software Testing?

코드를 작성하고 -> 기대하는 결과가 나옴 -> 호출을 해보거나 테스트 해봄 -> 성공 또는 실패 -> 수정

제대로 된 소프트웨어를 개발했는가? & 소프트웨어를 제대로 개발했는가?


목적

  • 결함확인
  • 사전방지
  • 시간절약
  • 구조개선
  • 품질개선
  • 확장성

Manual Testing

  • 불안정성이 높다
  • 인력소모가 많이 든다
  • 비용이 많이 든다
  • 테스트 속도가 낮다

Automation Testing

  • 안정성이 높아짐
  • 인력소모가 낮아짐
  • 비용이 적게 든다
  • 테스트 속도가 빠르다
  • 확장성이 높다

<시스템 테스트 전략 3가지>

End to End(E2E) Tests

  • (테스트 비중 10%) 복잡도가 가장 높다
  • 이쪽에서 이쪽을 끝까지 확인
  • front-end to back-end
  • 시작과 끝 전체적인 Flow
  • 브라우저상 클릭 후 생기는 변화에 대한 검증
  • 양쪽 서버가 다 켜져 있는 상태에서, 연동이 완료 되어 있는 상태에서
  • front-end에서 back-end로 요청을 하고 응답이 제대로 와서 화면에 제대로 뿌려지는 지

Integration Tests(통합테스트)

  • (테스트 비중 20%)
  • 모듈 간의 호환성 검증
    (예로, 웹페이지 혹은 포스트맨을 통한 API호출시 올바르게 동작하는지 확인)
  • 백엔드 서버가 켜져 있어야 함
  • 내가 만든 기능이 전체적으로 묶여 있을 때 맞는 결과를 return 하는지만 확인함

Unit Tests(단위테스트)

  • (테스트 비중 70%) 복잡도가 가장 낮다
  • 독립적으로 진행되는 가장 작은 단위의 테스트
  • 함수별로, 로직 구분해서 따로따로 테스트 (하나의 기능 또는 메소드)
  • 서버가 필요 없음
  • 빠른 문제 파악 가능
  • 시간과 비용 절감
  • 리팩토링 시 안정성 확보
  • 코드에 대한 문서로 활용
  • 항상 돌릴 수 있다 (호출이 필요 없기 때문에)

UnitTest 구조

  • TestCase
    unittest 프레임 워크(파이썬 내장 유닛테스트 라이브러리)의 테스트 조직의 기본 단위
  • Fixture
    테스트를 진행할 때 필요한 테스트용 데이터 혹은 설정 등 주로 테스트가 실행되기 전이나 후에 생긴다.
    테스트용 디비가 따로 있다.
    테스트가 독립적이어야 됨.
    필요한 데이터도 달라야 함
    유닛테스트 시작 전후로 다 지워버림 -> 테스트 마다 서로 다른 테스트에 영향을 끼치지 않기 위해
  • Assertion
    unittest에서 테스트하는 부분이 제대로 됐는지를 확인하는 부분. Assertion이 실패하면 테스트도 실패한다

(추가)Fixture
테스트를 위한 사전 준비 작업을 할 필요가 있다.
또한 테스트가 끝난 후 테스트를 하기 위해 만든 리소스들을 정리 해야 하는 경우도 있음
사전 준비 작업을 위해 setUp() 이라는 메서드를,
clean up 처리를 하기 위해 tearDown() 이라는 매서드를 제공

Client()
요청을 해주는 역할이 필요하고 응답을 받아줘야 하는 역할이 필요함 get, post, http method들이 있다

client = Client()
response = client.get('/just')

# Client 클래스를 활용하기 위해 client 객체로 만듬
# '/just' endpoint로 get메소드로 요청하겠다

http처럼 내부적으로 view를 호출해주는 역할이 필요함
프론트 역할을 대신한다!


소셜 로그인 유닛테스트

@patch
requests를 사용하는 곳을 만나면 이걸로 대체 해라
mocking
요청한걸로 친다!

response = requests.get(self.user_url, headers = headers, timeout = 3)

view 안에서 request를 요청하는 곳에 도착을 하면,
호출했다고 치고, 그에 대한 응답(내가 정한, 원하는 값)을 response에 넣는다
그러니까,

@patch("core.utils.KakaoAPI.requests")

requests 라이브러리를 쓰는 곳에다가 적용하겠다
특정 범위 내에서 mocking

patch가 붙은 requests -> mocked_requests로 들어옴
requests.get처럼 mocked_requests.getMagicMock을 활용해서 return_value에 내가 미리 세팅해 놓은 MockedResponse를 넣어줘라


라고 말을 못하니 왜 말을 못해


썰1

그도 그럴 것이
그 때도 어느 때인가 처럼 error를 만나 고생을 하고 있었고,
그 당시의 디버깅 쪼랩이었던(지금은 그냥 십랩(욕 아님)) 나로써는
해결하기 힘들었던 카카오에서 보내준 리스폰스 메세지를 그대로 가져오는 로직과 그 로직을 통과하는 유닛테스트를 SH님도 시간을 엄청 쏟아주셔서 해결을 하고 있었다.
그리고 이미 블로깅은 한 적이 있.....지.....? 유닛테스트 썰
결론은 두 갈래로 나뉘어졌다

  • 1번 스승님
    유닛테스트를 하다 보면 내 로직의 문제를 발견할 수 있기 때문에,
    이래서 유닛테스트를 같이 해야 한다.
    (결과) 테스트는 통과. 하지만 소셜 로그인을 모듈화 한 의도와는 다른 로직
  • 2번 스승님
    소셜 로그인을 모듈화 한 이유가 무엇이냐. 그 결과를 view로 다시 가져오는 것이 맞느냐 틀리냐를 return과 raise까지 얹어서 합세하여 얘기하다가 어쨌든 raise를 해 버리는 코드는 유닛테스트 통과를 하지 않았고, 1번의 해석을 전달하며 이래이래 이래서 여기까지 왔다고도 했지만, 그럼에도 유닛테스트를 변경하는 것이 맞다는 흐름으로 흘러갔다

지금의 나는 아니 지금 알고 있는 TDD는 테스트코드를 먼저 작성하고 그것을 통과하는 코드를 짜는 것이고, 그만큼 피드백을 바로 적용하여 개발하는 방법으로써 이 사건을 반추 해본다면 1번 스승님 말이 답에 가깝지 않나...

썰2

인턴십을 하는 동안 unittest를 하기 위해 초반부터 애를 쓰고 있었다.
아니 중요하다길래. 아니 근데 당시의 프로젝트의 성격상

  • DB가 여러 개였는데, 한두개가 아님, 데이터가 너무 많아
  • RDS 였는데,
  • 읽기 전용이었는데,
  • 권한이 없었지,

특히 RDS 에서 가져오는 데이터들을 테스트 하려면, 테스트 코드 내에 코드를 생성하고 티어다운 하는 과정 없이 하는 그런 뭐 코드가 있어서 그걸로 적용하려고 했지만(아니 그리고 아는 선생님이 아무도 없네?)

  • 결국 권한 문제(아니 권한이 없으니까 테스트가 안되지 라고 하심...선배님이)
  • 보통 테스트용 디비를 따로 만든다고 피드백을 받고(HJ님이)
  • 포스트맨 수준의 테스트 할 거면 안하는게 낫다(파트장님이)

썰3

이건 나중나중 아주 나중에 또 써보기로!

profile
킴릴로

0개의 댓글