CHAPTER 11 테스트 개요
p.282 “진화의 중심에는 개발자가 주도하는 테스트와 자동 테스트가 있었습니다…자동 테스트(automated test)는 버그가 몰래 숨어들어 고객을 놀라게 하는 사태를 막아줍니다…’버그 잡기’는 테스트를 하는 여러 이유 중 하나일 뿐입니다. 예를 들어 소프트웨어가 변화할 수 있도록 지원하는 역할 역시 버그 잡기에 못지않게 중요합니다…반복 주기가 짧은 회사는 변화하는 기술, 시장 상황, 고객 취향을 더 빠르게 받아들일 수 있습니다.”
p.283 “테스트는 시스템 코드의 첫 번째 고객이라는 자격으로 여러분이 선택한 설계에 관해 많은 이야기를 해줍니다.”
11.1 테스트를 작성하는 이유
p.283 “‘자동 테스트’라고 하는 것의 정체는 정확히 무엇일까요? 가장 단순한 테스트는 다음 요소 들로 정의할 수 있습니다.”
p.284 “테스트는 엔지니어에게 신뢰를 줄 때만 가치가 있다는 사실을 잊지 마세요. 테스트가 생산성을 떨어뜨리고 고칠 게 계속 나오거나 결과를 믿을 수 없다면 엔지니어들은 더 이상 테스트를 신뢰하지 않고 우회 방법을 찾으려 할 것입니다…구글은 문제가 터진 후에야 테스트를 고민해서는 안 된다고 결론지었습니다…품질이 떨어지는 제품이나 서비스를 만들면 필연적으로 나쁜 결과를 초래한다는 사실을 때로는 아주 큰 대가를 치르며 배웠기 때문입니다. 그 결과 구글은 테스트를 엔지니어링 문화의 중심에 두고 있습니다.”
11.1.1 구글 웹 서버 이야기
p.285 “엔지니어 주도의 자동 테스트를 정책 차원 에서 도입…모든 코드 변경에는 지속해서 실행할 수 있는 테스트가 반드시 딸려 있어야 했습니다…핵심은 제품 결함 해결을 프로그래머의 능력에만 의존해서는 안 된다는 사실…개별 엔지니어가 작성한 테스트는 팀이 공유하는 자원 풀에 추가됩 니다. 따라서 팀원 모두가 공유된 테스트를 수행하고 결함을 찾아낼 수 있습니다.”
11.1.2 오늘날의 개발 속도에 맞는 테스트
p.286 “대부분의 소프트웨어는 기능과 지원 플랫폼이 너무 폭증해서 사람이 모든 행위를 수동으로 검증할 수 있는 한계를 아득히 넘어섰습니다…테스트에서의 해법은 단 하나, 바로 ‘자동화’ 뿐입니다.”
11.1.3 작성하고, 수행하고, 조치하라
p.287 “가장 순수한 형태의 자동 테스트는 ‘테스트 작성’, ‘테스트 수행’, ‘실패한 테스트에 대한 조치’. 이렇게 세 가지 활동으로 이루어집니다.”
p.287 “오늘날 시스템의 규모와 배포 속도를 따라잡으려면 모든 엔지니어가 테스트도 함께 개발해야 만합니다.”
What if the release cycle is long enough?
- Does it mean that QA can play a role of all validation process?
- What else could we think of as advantages of automated test written by developers?
p.287 “테스트 작성은 테스트 자동화 프로세스의 첫 번째 단계일 뿐입니다. 테스트를 작성한 후에는…작성한 테스트를 실행해야 합니다. 수시로요…자동 테스트의 핵심은 같은 동작을 끊임없이 반복 하는 데 있습니다. 사람은 무언가 잘못됐을 때만 개입합니다…테스트 절차까지 ‘실행 가능한 코드’로 작성해두면 코드가 변경될 때마다. 즉 하루에 수천 번도 더 돌려볼 수 있습니다.”
p.288 “테스트 프로세스가 얼마나 효과적이냐는 이러한 테스트 실패를 어떻게 처리하느냐에 달려 있습니다. 실패하는 테 스트가 해결되지 못하고 빠르게 쌓여간다면 테스트에 투자한 노력이 허사가 되니. 그렇게 되지 않도록 하는 게 중요합니다.”
p.288 “테스트가 실패하면 바로 바로 조치하도록 권장해야 테스트 프로세스를 신뢰하고 계속 이어갈 수 있습니다.”
Flacky Test
- If there are many flaky tests in your test suite, it discourages your teammates from taking an action to test failure right away, assuming that it’ll be resolved soon…
11.1.4 테스트 코드가 주는 혜택
p.288 “구글은 테스트에 투자하는 게 개발자 생산성 향상시키는 중요한 이유를 몇 가지 발견했 습니다.”
p.289 “결함 대부분이 서브밋 전에 고쳐지기 때문에 그 코드의 존속 기간 전체 로 봤을 때 결함이 줄어든다…프 로젝트 자체 혹은 프로젝트가 의존하는 다른 코드가 변경되어 테스트가 실패한다면 테스트 인프라가 곧바로 인지해내어, 프로덕션 환경으로 릴리스되기 전에 정상 상태로 되돌릴 수 있습니다.”
p.289 “좋은 테스트들로 무장한 팀은 자신감을 가지고 변경들을 리 뷰하고 수용할 수 있습니다…이런 프로젝트에서는 자연스럽게 리팩터링을 권장합니다. 행위가 달라지지 않는 변경. 즉 리팩터링은 (이상적으로는) 기존 테스트를 수정할 필요조차 없습니다.”
p.289 “한 번에 하나의 행위만 집중해 검증하는 명확한 테스트는 마치 실행 가능한 문서 와 같습니다. 코드가 특정 상황에서 어떻게 동작하는지 궁금하다면 그 상황을 검증하는 데 스트를 보면 됩니다.”
p.290 “테스트하기 어려운 코드는 너무 많은 역할을 짊어지거나 의존성 을 관리하기 어렵게 짜여졌기 때문일 가능성이 큽니다…설계 문제를 조기에 바로잡는다면 훗날 수정할 때 고생을 덜 합니다.”
p.290 “건실한 자동 테스트 스위트를 갖춘 팀은 새로운 버전을 릴리스하며 불안에 떨지 않습니다.”
11.2 테스트 스위트 설계하기
p.290 “한 번에 하나의 서버만 테스트하지 못하는 이유는 뭘까?“. 또는 한 번에 서버 전체를 테스트할 이유가 있나?”
p.291 “모든 테스트 케이스에는 두 가지 독립된 요소가 있다는 결론에 이르렀습니 다. 바로 크기와 범위…크기는 테스트 케이스 하나를 실행하는 데 필요한 자원을 뜻합 니다. 메모리, 프로세스, 시간 등이죠. 한편 범위는 검증하려는 특정한 코드 경로code path를 뜻합니다.”
11.2.1 테스트 크기
p.291 “엔지니어들에게 주어진 기능 조각을 검사 하는 가능한 한 작은 테스트를 작성하라고 독려합니다.”
p.291 “작은 테스트는 프로세스 하 나에서 동작하고, 중간 크기 테스트는 기기 하나에서, 큰 테스트는 자원을 원하는 만큼 사용”
p.292 “구글은 전통적인 용어인 ‘단위 테스트’와’통합 테스트’ 대신 이 정의를 사용합니다. 우리가 테스 트 스위트에 바라는 품질은 바로 속도와 결정성이기 때문”
p.292 “큰 테 스트는 가장 복잡하고 검증하기 어려운 시나리오에만 제한적으로 활용합니다”
작은 테스트
p.292 “가장 중요한 제약은 바로 테스트 가 단 하나의 프로세스에서 실행되어야 한다”
p.292 “서버를 두고 독립된 테스트 프로세스에 연결해 수행하 는 방식도 허용되지 않습니다.”
p.292 “데이터베이스와 같은 제3의 프로그램을 수행해서도 안 됩 니다.”
p.293 “블로킹 호출을 사용해서는 안 됩니다…블로킹 호출을 수반하는 대상을 검사하는 테스트 코드는 테스트 대역을 사용해야 합니다. 테스트 대역은 강한 의존성을 가벼운 인프로세스-proxess 의존성으로 대체해주 는 수단”
p.293 “제약이 너무 과하다고 느껴진다면 작은 테스트 케이스 수백 개로 이루어진 스위트가 하루 종일 실행되는 환경을 생각해보세요. 그중 불규칙한 테스트laky test’가 단 몇 개만 있어도 원인을 찾아 헤매느라 생산성이 급격하게 떨어질 것입니다.”
중간 크기 테스트
p.293 “외부 시스템과의 통신은 여전히 불허합니다.”
p.294 “유연성이 커지면 반대급부로 테스트는 느려지고 비결정적이 될 가능성이 높아집니 다.”
p.294 “중간 크기 테스트는 원격 기기로의 네트워크 호출을 불허함으로써 여전히 어느 정도의 보호막은 유지”
큰 테스트
p.294 “유연해지는 만큼 위험도 늘어납니다. 여러 기기에 걸쳐 있는 시스템을 네트워크로 연결해 다루게 되면서 단일 기기에서 구동할 때보다 느려지거나 비결정성이 커질 가능성이 훨 씬 높아집니다.”
p.294 “구글은 큰 테스트를 몇 가지 용도에 한정해서 활용합니다. 하나는 전체 시스템의 종단간(end-to-end) 테스트입니다. 종단간 테스트는 코드 조각이 아닌 설정을 검증하는 게 주된 목적입니다.”
p.294 “또 다른 예로는 테스트 대역을 사용하는 게 불가능한 레거시 컴포넌트를 테스트할 때입니다.”
p.294 “구글은 큰 테스트 를 작은 테스트나 중간 크기 테스트와 분리하여, 빌드나 릴리스 때만 수행되도록 하여 개발 워 크플로에 영향을 주지 않도록 합니다.”
사례 연구: 불규칙한 테스트는 비싸다
p.295 “테스트당 실패 확률이 0.1%밖에 안 되더라도 테스트를 하루에 1만 번 수행한다면 매일 평균 10번씩은 실패 원인을 조사해서 조치해 야 합니다. 팀에 당장 필요한 더 생산적인 일을 할 시간은 그만큼 줄어듭니다.”
p.295 “어떤 경우에는 실패 시 다시 수행되도록 하는 식으로 불규칙한 테스트의 영향을 제한할 수 있습 니다.”
p.295 “언젠가는 결과를 불규칙하게 만드는 진짜 원인을 찾아 해결해야 합니다.”
p.295 “생산성 저하보다 더한 일도 겪게 됩니다. 바로 테스트를 믿지 못하게 되는 상황”
p.295 “대부분의 불규칙한 실패는 테스트 자체에 비결정적으로 동작하는 로직이 있어서 발생”
테스트 크기와 무관한 공통 특성
p.295 “모든 테스트는 밀페(hermetic) 되어야 합니다. 즉, 셋업(setup), 실행(execute), 테어다운(tear down)하는 데 필요한 모든 정보를 담고 있어야 합니다.”
실제 상황에서의 테스트 크기
p.296 “예를 들어 자바 테스트들은 사용자 정의 보안 관리자를 사용해 수행하는데, ‘작은 테스트’라고 태깅된 테스트가 네트워크 연결 같은 금지된 동작을 시도하면 실패로 처리합니다.”