티스토리 뷰

구영민

안녕하세요, 피플펀드에서 백엔드 소프트웨어 엔지니어로 일하고 있는 구영민입니다. Python을 프로덕션에서 주 언어로 사용하고 있으며, 스크래핑 및 크롤링 기술을 능숙하게 다룹니다.

 

견고한 소프트웨어 개발을 위해서 테스트를 돌리는 것은 아주 중요합니다. 소스를 수정하고 어딘가 잘못되었다는 것을 빠르게 알아차릴수록 발생한 버그를 더욱 쉽게 고칠 수 있습니다. 이를 위해서는 테스트 시간이 오래 걸리지 않아야 합니다. 테스트에 걸리는 시간이 짧으면 짧을수록 개발자의 생산성은 올라갑니다.

회사의 사업이 빠르게 성장하면서 피플펀드의 시스템에서 지원해야 하는 기능도 많아졌습니다. 이에 자연스럽게 테스트 케이스의 개수도 크게 증가하며 전체 테스트 케이스에 엄청난 시간이 걸리게 되었습니다. 개발자들의 생산성이 크게 저하되었습니다. 코드를 긴급하게 수정 및 배포해야 하는 경우 모든 테스트를 돌리지도 못하고 운영 서버에 배포하기도 하였습니다. 저는 이런 상황을 이대로 방치할 수는 없었습니다.

온갖 수단을 사용하여 테스트에 걸리는 시간을 줄였습니다. 테스트 옵션을 수정하는 것에서 그치지 않았습니다. 심지어는 Django의 소스 코드를 수정하기도 하였습니다. 그 결과, 약 40분에서 50분이 걸리던 테스트를 3분 30초 만에 끝내도록 최적화 할 수 있었습니다. 이 과정에서 사용한 여러 가지 테스트 시간을 줄이는 데 도움이 될 만한 노하우를 PyCon에서 공유하고자 합니다.

 

https://www.pycon.kr/program/talk-detail?id=67

 

 


 

테스트 시간이 90%나 줄었다는 것은 무척이나 비효율적이었다는 것.

100명의 유저를 생성하는데 얼마나 걸릴까? 

약 20여초가 걸림. 사실 엄청 이상한 일.

 

왜 이렇게 오래 걸릴까 했는데 비번 저장할 때 해시저장을 하기 때문.

 

 

---

 

비밀번호 저장

 

일반적으로 복호화 혹은 해시함수를 이용해 입력함.

- 해시함수란 복호화가 불가능하게 암호화하는 단방향 암호화

 

그래서 키 스트테칭을 사용함.

비밀번호를 확인하는데 어느 정도 시간이 걸리게 하는 것.

해시 하는 것을 여러번 반복하는 작업.

시간을 늘리는 1등 공신!

 

테스트 코드에서 한명당 .2초라 100명이면 20초!

 

----

 

해시 알고리즘 변경!

테스트 환경에서 알고리즈을 설정하여 속도 개성.

보안에 취약하니 주의.

이렇게 변경하면 테스트 시간이 0.034초만에 끝남.

 

 

----

 

2. Mocking

 

----

 

mocking obj

 

가짜 객체로 실제 객체처럼 동작. 파라미터를 검증하는 객체,

 

 

갑에서 요청 중 대량으로 외부 api를 호출해야 하는데, 1분에 10개만 보내야하는 제약이 있을 경우.

로직이 정말 잘 짰는지 테스트 할 때.

운영에서는 필요하지만, 테스트 환경에서는 불 필요.

 

테스트 코드를 할 때 10초 정도 아무엇도 안함

 

 

이때 목을 데코레이터로 적용

sleep_mock 파라미터를 받음.

 

테스트 결과실패로 나옴.

 

 

----

 

freezgun 라이브러리

 

실제 시간이 흐른것처럼 처리.

이 함수내에서는 입력한 시간으로 처리함.

아까 실패한 함수에 이 기능을 적용.

 

 

아까 10초 걸린 테스트가 0.045초만 걸림.

 

----

 

꿀팁

 

진짜 10초를 쉬는게 맞는지 검증을 할 때.

call_count, call_args로 해당 파라미터 출력 가능.

 

----

 

3. don't use transactionTestCode

 

----

 

테스트는 다른 테스트에 영향을 받으면 안된다.

 

테스트 케이스에서 생성한 데이터의 삭제 필요.

 

 

----

 

testcase

 

 

각각 트랜잭션으로 감쌈. 그리고 끝나면 롤백을 함

 

----

 

performance

 

피플펀드 약 230개의 테이블 사용.

TestCase와 TransactionTestCase의 롤백 비교는 거의 3000배 차이

테스트케이스는 1초도 안걸림.

 

그런데 트랜잭션테스트케이스 중 락 기능이 있는데, 이게 트랜잭션에서만 사용 가능.

장고에서는 이걸 외부에서 사용하면 오류 발생.

 

---

 

on_commit() 함수

예외가 발생하여 트랙잭션이 롤백하면 전송되지 않음.

트랜잭션에 롤백되면 전송되지 않음.

 

 

트랜잭션이 성공했을 때 실행할 함수 등록

sms 발송에서 실패 시 롤백을 일으키면 안 됨.

 

샐러리 등 비동기 워커로 보내면 안됨

그런데 찾아보니 방법이 있음.

 

----

 

TestCase 내부에서 on_commit() 테스트 하기

 

 

이걸 만들어 쓰면 테스트 가능

 

-----

 

4. 병렬 테스트

 

 

---

 

이 테스트는 어떻게 깨질까요?(1.11이하)

이상한 에러가 뜬다.

테스트가 그냥 강제로 꺼진다.

오류를 분석하면 병렬 옵션을 끄면 돈다고 함.

 

 

그래서 어떻게 도는지 확인해봄

마스터와 워커 프로세스 2개가 있다.

 

 

워커에 테스트를 누적하고 그 결과를 가져옴.

 

----

 

문제점

 

 

예외가 생길 때 pickle이 안됨. 그래서 저장이 안됨.

충분히 자주 발생할 수 있는 문제.

 

-----

 

모델 예외 클래스를 pickle 할 수 있도록 처리

 

장고 2.1 이상만 패치. 그래서 2.1의 내용을 1.11에 적용하면?

그래서 적용해봄. 운영에서는 사용하지 않고 테스트에만.

 

 

----

 

5. Keepdf with mysqldump

 

----

 

fresh migrations

 

마이그래션 테이블이 많아자면 오래 걸림

230개 정도 되면 4-5분이 걸림.

테스트 할 때마다 수행하면 오래 거림.

 

----

 

 django keepdb

 

마이그레이션 결과를 삭제하지 않음. 

 

 

---

 

git flow

 

처음 ok했는데 나중에 칼럼을 날리고 마이그레이션을 함. 

근데 이 변경내용이 db에 적용됨. 

 

---

 

mysqldump

 

 

개발 db를 덤프 떠놓고 이후 가져오기.

이러니 4~5분 걸리는게 5~10초로 단축!

 

 

---

 

6. Diable Linter

 

----

 

성능 오버헤드

경험상 30%정도 느려짐. 알수 없는 무한 루프가 발생.

1년만에 뺌.

 

----

 

선택적으로 필요할때만 사용

개발자가 자고 있을 때 새벽 정도레 테스트 추가하는 식으로 사용

 

 

원래 40여분 걸리는게 3.5분으로 줄어듬!

 

----

 

개발자 변화

 

 

더 자주 더 부담없이 테스트 돌릴 수 있게 됨.

이제 테스트가 빠르니 테스트 해보고 배포 가능.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함