기능 테스트
고친 사람 github-actions[bot]
기능 테스트는 소프트웨어가 해야 할 일을 제대로 하는지 확인하는 테스트입니다. 로그인이라면 「비밀번호를 다섯 번 틀리면 계정이 잠긴다」 같은 것이 해야 할 일입니다. 입력을 넣어 보고 나온 결과가 기대와 같은지만 따집니다. 얼마나 빠르게 도는지는 비기능 테스트가 따로 잽니다.
쉽고 빠른 이해
무슨 일을 하나 — 기능 하나를 사용자처럼 써 보고 결과가 요구한 대로인지 확인합니다. 로그인이라면 비밀번호를 다섯 번 틀린 뒤에 계정이 잠기는지를 봅니다.
왜 하나 — 코드가 오류 없이 돈다고 해서 해야 할 일을 하는 것은 아닙니다. 잠가야 할 계정을 안 잠가도 프로그램은 멀쩡히 돕니다. 요구한 동작을 하나씩 해 봐야 이런 빈틈이 드러납니다.
어떻게 도나
- 요구사항에서 확인할 경우를 골라 입력과 기대 결과를 적습니다
- 시스템의 입구로 그 입력을 넣습니다
- 나온 결과를 기대 결과와 견줘 통과와 실패를 가립니다
대가 — 결과가 맞는지만 보므로 느려진 것은 못 잡습니다. 실패해도 코드의 어느 줄이 틀렸는지는 알려 주지 않습니다. 시스템 전체를 띄워 돌리면 오래 걸립니다. 그래서 함수 하나로 확인되는 계산은 그 함수만 떼어 확인하는 테스트에 맡깁니다.
상세
이 절은 웹 서비스의 로그인 기능 하나를 예로 들어 기능 테스트를 다룹니다. 로그인은 맞는 비밀번호를 넣으면 들여보냅니다. 틀리면 거절합니다. 다섯 번 연달아 틀리면 그 계정을 잠급니다.
기능 테스트는 새로 들인 자판기를 시험해 보는 일과 닮았습니다. 동전을 넣고 콜라 버튼을 눌러 콜라가 나오는지 확인합니다. 돈이 모자라면 음료 대신 동전이 돌아오는지도 봅니다. 자판기 뚜껑을 열어 안의 톱니바퀴를 살피지는 않습니다.
기능 테스트는 시스템이 기능 요구사항대로 움직이는지 확인하는 테스트입니다. 기능 요구사항은 시스템이 무엇을 해야 하는지 적은 요구입니다. 「비밀번호를 다섯 번 연달아 틀리면 계정을 잠근다」가 로그인의 기능 요구사항 하나입니다. 기능 테스트는 비밀번호를 다섯 번 틀린 뒤 맞는 비밀번호를 넣어 봅니다. 그래도 막혀야 통과입니다.
이 확인이 따로 필요한 까닭은 코드가 멀쩡히 도는 것과 요구를 채우는 것이 다르기 때문입니다. 틀린 횟수를 세는 코드가 빠져도 로그인은 오류 없이 돕니다. 컴파일도 되고 예외도 안 납니다. 요구한 동작을 하나씩 해 봐야 잠금이 빠졌다는 것이 보입니다.
기능 테스트와 비기능 테스트
테스트는 무엇을 확인하느냐로 두 갈래로 나눌 수 있습니다. 한 갈래는 시스템이 무엇을 하는지 따집니다. 다른 갈래는 그 일을 얼마나 빠르게, 얼마나 안전하게, 얼마나 잘 버티며 하는지 잽니다.
뒤쪽 갈래가 비기능 테스트입니다. 비기능 요구사항은 비기능 테스트가 기준으로 삼는 요구입니다. 「로그인 응답은 1초 안에 온다」가 로그인의 비기능 요구사항 하나입니다. 아래 표에서 두 갈래가 로그인 기능에 각각 무엇을 묻는지 견줍니다.
| 기능 테스트 | 비기능 테스트 | |
|---|---|---|
| 묻는 것 | 무엇을 하나 | 얼마나 잘 하나 |
| 기준이 되는 요구 | 기능 요구사항 | 비기능 요구사항 |
| 로그인에서 확인하는 것 | 틀린 비밀번호를 거절하나 | 로그인 응답이 1초 안에 오나 |
두 갈래는 같은 로그인을 두고 묻는 것이 다릅니다. 기능 테스트는 결과가 맞으면 통과시킵니다. 로그인이 10초 걸려도 틀린 비밀번호를 거절했다면 기능 테스트는 통과합니다.
성능 회귀는 코드를 고친 뒤 결과는 맞는데 느려지는 일입니다. 기능 테스트는 이것을 못 잡습니다. 응답 시간을 재는 성능 테스트 같은 비기능 테스트가 잡습니다.
입구로만 들어가는 검사
기능 테스트는 대개 시스템 안쪽을 들여다보지 않습니다. 이 소절은 로그인 기능 테스트가 시스템의 어디를 건드리는지 따라갑니다.
로그인 기능의 입구는 로그인 요청을 받는 주소 하나입니다. 테스트는 이 주소로 아이디와 비밀번호를 보냅니다. 돌아온 응답만 보고 통과와 실패를 가립니다. 안쪽에서는 틀린 횟수를 세는 코드가 그 횟수를 데이터베이스에 적습니다.
flowchart TD
T["기능 테스트"]
subgraph S["로그인 시스템 · 테스트는 안을 안 봄"]
L["로그인 요청 주소"] --> C["틀린 횟수를 세는 코드"]
C --> DB[("데이터베이스")]
end
T -->|"아이디 · 비밀번호"| L
L -->|"응답"| T
그림의 상자 안, 틀린 횟수를 세는 코드가 어떻게 짜였는지는 테스트가 모릅니다. 몰라도 다섯 번 틀린 뒤의 응답이 「잠김」이면 요구가 지켜진 것입니다.
블랙박스 테스트는 이렇게 속 구조를 모르는 채 입력을 넣고 결과만 보는 방식입니다. 기능 테스트는 대개 이 방식을 따릅니다. 속을 안 보니 코드를 다시 짜도 테스트를 고칠 일이 적습니다. 횟수를 데이터베이스 대신 메모리에 적도록 바꿔도 응답이 같으면 테스트는 통과합니다.
화이트박스 테스트는 반대로 코드의 갈림길을 알고 그 갈림길을 하나씩 지나가게 짜는 방식입니다. 화이트박스 테스트는 코드 구조에 기대므로 코드를 다시 짜면 테스트도 함께 고쳐야 합니다.
코드로 쓴 기능 테스트
아래는 잠금 요구를 확인하는 기능 테스트를 파이썬으로 적은 것입니다. login 은 로그인 주소로 요청을 보내고 응답에서 결과를 꺼내 돌려주는 도우미 함수입니다. 먼저 잠기기 전의 응답부터 확인합니다.
ok = {"id": "kim", "pw": "right"}
bad = {"id": "kim", "pw": "wrong"}
login(ok)["result"] # "OK"
login(bad)["result"] # "WRONG_PW"
맞는 비밀번호에는 OK 가, 틀린 비밀번호에는 WRONG_PW 가 돌아옵니다. 테스트는 이 입구를 다섯 번 틀리게 두드린 뒤 맞는 비밀번호를 넣습니다.
def test_다섯_번_틀리면_잠긴다():
for _ in range(5):
login(bad)
assert login(ok)["result"] == "LOCKED"
마지막 줄의 assert 는 뒤에 적은 조건이 참인지 확인하는 문장입니다. 단언은 이렇게 기대 결과를 코드로 적은 확인입니다. 이 테스트는 맞는 비밀번호를 넣었는데도 LOCKED 가 와야 통과합니다.
테스트 안에는 틀린 횟수가 어디에 적히는지에 대한 말이 한 줄도 없습니다. 입력과 기대 결과만 있습니다. 그래서 이 테스트가 실패하면 잠금 요구가 깨졌다는 것만 압니다. 코드의 어느 줄이 틀렸는지는 로그를 읽거나 함수 하나를 떼어 확인하는 테스트로 내려가서 따로 찾아야 합니다.
요구사항에서 뽑는 테스트 케이스
기능 테스트는 요구사항 하나에서 확인할 경우를 여럿 뽑습니다. 테스트 케이스는 이렇게 뽑은 경우 하나입니다. 테스트 케이스에는 시작할 때의 상황, 넣는 입력, 기대 결과 셋을 적습니다.
아래 표는 잠금 요구에서 뽑은 테스트 케이스 넷입니다. 앞 소절의 코드는 셋째 줄처럼 틀려서 계정을 잠근 뒤 넷째 줄을 확인합니다.
| 시작할 때의 상황 | 넣는 입력 | 기대 결과 |
|---|---|---|
| 틀린 횟수 0 | 맞는 비밀번호 | 로그인 성공 |
| 틀린 횟수 4 | 맞는 비밀번호 | 로그인 성공, 틀린 횟수는 0으로 |
| 틀린 횟수 4 | 틀린 비밀번호 | 거절, 계정 잠김 |
| 계정 잠김 | 맞는 비밀번호 | 거절(LOCKED) |
첫째 줄은 요구와 상관없이 로그인이 되는 평범한 경우입니다. 둘째와 셋째 줄은 잠금이 걸리기 바로 앞에서 갈리는 두 경우입니다. 넷째 줄은 잠긴 뒤에 맞는 비밀번호로도 못 들어가는지 확인합니다.
경우를 고를 때 흔히 쓰는 방법이 동등 분할입니다. 같은 결과를 내야 하는 입력끼리 한 묶음으로 봅니다. 그리고 묶음마다 하나씩만 고릅니다. 틀린 횟수가 0에서 3 사이일 때 한 번 더 틀리면 결과는 전부 「거절만 한다」입니다. 그러니 그 묶음에서는 하나만 확인해도 됩니다.
경계값 분석은 묶음이 바뀌는 경계 바로 앞뒤를 골라 확인하는 방법입니다. 결함이 경계에 몰리는 일이 많아서 씁니다. 「다섯 번」을 「다섯 번을 넘으면」으로 잘못 짜면 여섯 번째에야 잠깁니다. 표에서는 셋째 줄 하나만 이 결함을 드러냅니다.
이름이 가리키는 두 쓰임
기능 테스트라는 이름은 두 기준에 걸쳐 쓰입니다. 이 소절은 두 쓰임을 가릅니다. 비슷한 이름의 테스트와 어떻게 겹치는지도 짚습니다.
첫째 쓰임은 무엇을 확인하느냐로 붙인 이름입니다. 이 쓰임에서는 검사하는 넓이를 가리지 않습니다. 함수 하나가 맞는 값을 내는지 확인하는 단위 테스트도 기능을 보는 테스트입니다. 비기능 테스트와 맞세울 때 이 뜻으로 씁니다.
둘째 쓰임은 검사하는 넓이와 얽힙니다. 테스트는 한 번에 검사하는 넓이로 좁음·중간·넓음 셋으로 나누기도 합니다. 함수 하나처럼 작은 조각만 떼어 확인하는 테스트가 좁은 범위 테스트입니다. 시스템의 여러 부분을 이어 흐름 전체를 확인하는 테스트가 넓은 범위 테스트입니다.
둘째 쓰임에서 기능 테스트는 넓은 범위 테스트를 부르는 여러 이름 가운데 하나입니다. 같은 테스트를 종단 간 테스트나 시스템 테스트라고도 합니다. 두 이름이 무엇을 뜻하는지는 아래 표에서 풉니다.
세 이름은 확인하는 넓이가 같지만 이름이 붙은 기준은 저마다 다릅니다. 기능 테스트라는 이름의 기준은 첫째 쓰임에서 물려받은 「무엇을 확인하나」입니다. 아래 표에서 세 이름이 각각 무엇을 따라 붙었는지 견줍니다.
| 이름 | 이름이 붙은 기준 | 그 이름이 묻는 것 |
|---|---|---|
| 기능 테스트 | 무엇을 확인하나 | 기능 요구사항대로 움직이나 |
| 시스템 테스트 | 검사하는 넓이 | 조립을 마친 시스템 전체가 요구사항을 채우나 |
| 종단 간 테스트 | 따라가는 방식 | 사용자의 흐름 하나가 처음부터 끝까지 이어지나 |
기준이 다르니 한 테스트가 세 이름을 같이 가질 수 있습니다. 로그인 시스템을 전부 띄워 가입부터 잠금까지 따라가는 테스트는 셋 모두에 듭니다. 이름만 듣고는 무엇을 띄우고 무엇을 확인하는지 알 수 없습니다. 팀 안에서 이 이름을 쓸 때는 그 둘을 함께 적어 둡니다.
다시 돌리는 기능 테스트
기능 테스트 케이스는 한 번 쓰고 버리지 않습니다. 코드를 고칠 때마다 다시 돌려 되던 기능이 망가지지 않았는지 확인합니다. 회귀 테스트가 이런 쓰임입니다.
배포한 직후에 핵심 기능 몇 개만 골라 빠르게 돌려 보기도 합니다. 로그인이 되는지, 첫 화면이 뜨는지 정도만 확인합니다. 스모크 테스트는 이렇게 핵심만 훑는 쓰임을 가리킵니다.
기능 테스트가 못 보는 것
기능 테스트는 요구사항에 적힌 것만 봅니다. 요구사항에서 잠금 규칙이 빠졌다면 잠금을 확인하는 테스트 케이스도 안 생깁니다. 모든 테스트가 통과해도 요구사항 자체가 틀렸다면 그 틀린 대로 만들어진 것입니다.
결과가 맞는지만 따지므로 속도와 자원은 놓칩니다. 앞에서 다룬 성능 회귀가 그렇습니다. 이 부분은 비기능 테스트를 따로 두어 채웁니다.
시스템 전체를 띄워 돌리는 기능 테스트는 무겁습니다. 서비스를 띄우고 데이터를 준비하느라 오래 걸립니다. 코드를 안 고쳐도 네트워크가 잠깐 늦으면 실패하기도 합니다. 불안정한 테스트는 이렇게 코드를 안 고쳤는데도 통과와 실패가 오가는 테스트입니다.
그래서 넓은 범위 테스트는 여러 부분이 맞물려야 드러나는 동작에 씁니다. 비밀번호 길이를 따지는 계산처럼 함수 하나로 확인되는 것은 단위 테스트에 맡깁니다. 테스트 피라미드는 넓은 범위 테스트는 적게, 좁은 범위 테스트는 많이 두라는 권장입니다.
관련 항목
기능 테스트와 맞세워지는 비기능 테스트
비기능 테스트 · 성능 테스트 · 부하 테스트 · 스트레스 테스트 · 보안 테스트 · 사용성 테스트 · 성능 회귀
기능 테스트가 확인할 기준을 담은 문서
요구사항 · 기능 요구사항 · 비기능 요구사항 · 요구사항 명세 · 테스트 케이스 · 테스트 계획
기능 테스트가 시스템을 들여다보는 방식
블랙박스 테스트 · 화이트박스 테스트 · 그레이박스 테스트
기능 테스트의 테스트 케이스를 고르는 기법
동등 분할 · 경계값 분석 · 결정 테이블 테스트 · 상태 전이 테스트
기능 테스트와 기준이 달라 겹쳐 쓰이는 테스트
시스템 테스트 · 종단 간 테스트 · 넓은 범위 테스트 · 인수 테스트 · 큰 테스트
기능 테스트를 돌리는 넓이별 테스트 수준
단위 테스트 · 통합 테스트 · 테스트 수준 · 좁은 범위 테스트 · 중간 범위 테스트 · 테스트 피라미드
기능 테스트 케이스를 다시 돌리는 쓰임
회귀 테스트 · 스모크 테스트 · 자동 테스트 · 지속적 통합
기능 테스트를 짜고 돌리는 부품
단언 · 테스트 더블 · 테스트 러너 · 테스트 스위트
기능 테스트에서 자주 나는 문제
불안정한 테스트 · 깨지기 쉬운 테스트 · 테스트 순서 의존성
기능 테스트가 속하는 상위 분류
QA와 테스트 · 소프트웨어 테스트 · 소프트웨어 품질
다른 이름: functional test · functional testing · 기능 시험 · 기능성 테스트